mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
merge m-c to fx-team
This commit is contained in:
commit
027e96add3
@ -90,10 +90,6 @@ public:
|
||||
*/
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTML4ButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
|
@ -217,17 +217,6 @@ nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent,
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTML4ButtonAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAccessible* accessible =
|
||||
new nsHTML4ButtonAccessible(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
|
@ -89,13 +89,10 @@ public:
|
||||
// nsIAccessibilityService
|
||||
virtual nsAccessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
|
||||
bool aCanCreate);
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTML4ButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
already_AddRefed<nsAccessible>
|
||||
CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
|
@ -838,9 +838,9 @@ nsAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
|
||||
nsPresContext *presContext = frame->PresContext();
|
||||
|
||||
nsIntRect screenRect = frame->GetScreenRectExternal();
|
||||
nsPoint offset(presContext->DevPixelsToAppUnits(aX - screenRect.x),
|
||||
presContext->DevPixelsToAppUnits(aY - screenRect.y));
|
||||
nsRect screenRect = frame->GetScreenRectInAppUnits();
|
||||
nsPoint offset(presContext->DevPixelsToAppUnits(aX) - screenRect.x,
|
||||
presContext->DevPixelsToAppUnits(aY) - screenRect.y);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
|
||||
nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
|
||||
@ -853,6 +853,11 @@ nsAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
// the DOM parent chain.
|
||||
nsDocAccessible* contentDocAcc = GetAccService()->
|
||||
GetDocAccessible(content->OwnerDoc());
|
||||
|
||||
// contentDocAcc in some circumstances can be NULL
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=729861
|
||||
NS_ENSURE_TRUE(contentDocAcc, fallbackAnswer);
|
||||
|
||||
nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
|
||||
if (!accessible)
|
||||
return fallbackAnswer;
|
||||
|
@ -314,7 +314,7 @@ nsresult
|
||||
nsHTMLButtonAccessible::GetNameInternal(nsAString& aName)
|
||||
{
|
||||
nsAccessible::GetNameInternal(aName);
|
||||
if (!aName.IsEmpty())
|
||||
if (!aName.IsEmpty() || mContent->Tag() != nsGkAtoms::input)
|
||||
return NS_OK;
|
||||
|
||||
// No name from HTML or ARIA
|
||||
@ -353,71 +353,6 @@ nsHTMLButtonAccessible::IsWidget() const
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTML4ButtonAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTML4ButtonAccessible::
|
||||
nsHTML4ButtonAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHyperTextAccessibleWrap(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
PRUint8
|
||||
nsHTML4ButtonAccessible::ActionCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTML4ButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
||||
{
|
||||
if (aIndex == eAction_Click) {
|
||||
aName.AssignLiteral("press");
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTML4ButtonAccessible::DoAction(PRUint8 aIndex)
|
||||
{
|
||||
if (aIndex != 0)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
DoCommand();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
role
|
||||
nsHTML4ButtonAccessible::NativeRole()
|
||||
{
|
||||
return roles::PUSHBUTTON;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTML4ButtonAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
|
||||
|
||||
state |= states::FOCUSABLE;
|
||||
|
||||
nsEventStates elmState = mContent->AsElement()->State();
|
||||
if (elmState.HasState(NS_EVENT_STATE_DEFAULT))
|
||||
state |= states::DEFAULT;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTML4ButtonAccessible: Widgets
|
||||
|
||||
bool
|
||||
nsHTML4ButtonAccessible::IsWidget() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLTextFieldAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
|
||||
/**
|
||||
* Accessible for HTML input@type="button", @type="submit", @type="image"
|
||||
* elements.
|
||||
* and HTML button elements.
|
||||
*/
|
||||
class nsHTMLButtonAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
@ -120,33 +120,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible for HTML button element.
|
||||
*/
|
||||
class nsHTML4ButtonAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
|
||||
public:
|
||||
enum { eAction_Click = 0 };
|
||||
|
||||
nsHTML4ButtonAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
|
||||
NS_IMETHOD DoAction(PRUint8 index);
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// ActionAccessible
|
||||
virtual PRUint8 ActionCount();
|
||||
|
||||
// Widgets
|
||||
virtual bool IsWidget() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible for HTML input@type="text" element.
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@ _TEST_FILES =\
|
||||
test_aria.html \
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_inputs.html \
|
||||
test_controls.html \
|
||||
test_keys_menu.xul \
|
||||
test_keys.html \
|
||||
test_link.html \
|
||||
|
@ -25,6 +25,11 @@
|
||||
actionName: "press",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "input_button",
|
||||
actionName: "press",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "checkbox_unchecked",
|
||||
actionName: "check",
|
||||
@ -68,7 +73,9 @@
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<button id="button" value="button">Button</button>
|
||||
<button id="button">Button</button>
|
||||
|
||||
<input id="input_button" type="button" value="normal">
|
||||
|
||||
<input id="checkbox_unchecked" type="checkbox">Checkbox</input>
|
||||
|
@ -18,36 +18,19 @@
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// If your patch changes UI or default styles then please tweek the numbers.
|
||||
// Accessibility exposes coordinates and size in device pixels while DOM
|
||||
// operates with CSS pixels. Thus it seems we don't have another way for
|
||||
// accessibility testing rather than numbers hardcode.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var [outerX, outerY] = getBounds(getAccessible(currentTabDocument()).parent);
|
||||
var tabDocument = currentTabDocument();
|
||||
var p1 = tabDocument.body.firstElementChild;
|
||||
var p2 = tabDocument.body.lastElementChild;
|
||||
|
||||
var p1 = currentTabDocument().body.firstElementChild;
|
||||
var p2 = currentTabDocument().body.lastElementChild;
|
||||
testBounds(p1);
|
||||
testBounds(p2);
|
||||
|
||||
var deltaX = 8, deltaY = 8, indentY = 16, w = 584, h = (WIN ? 20 : 19);
|
||||
testBounds(p1, outerX + deltaX, outerY + deltaY, w, h);
|
||||
testBounds(p2, outerX + deltaX, outerY + deltaY + h + indentY, w, h);
|
||||
zoomDocument(tabDocument, 2.0);
|
||||
|
||||
var docShell = currentTabWindow().
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIWebNavigation).
|
||||
QueryInterface(Components.interfaces.nsIDocShell);
|
||||
var docViewer = docShell.contentViewer.
|
||||
QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
|
||||
docViewer.fullZoom = 2.0;
|
||||
|
||||
testBounds(p1, outerX + deltaX * 2, outerY + deltaY * 2, w * 2, h * 2);
|
||||
testBounds(p2, outerX + deltaX * 2, outerY + (deltaY + h + indentY) * 2,
|
||||
w * 2, h * 2);
|
||||
testBounds(p1);
|
||||
testBounds(p2);
|
||||
|
||||
closeBrowserWindow();
|
||||
SimpleTest.finish();
|
||||
|
@ -98,6 +98,21 @@ function reloadButton()
|
||||
return browserWindow().document.getElementById("urlbar-reload-button");
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom the given document.
|
||||
*/
|
||||
function zoomDocument(aDocument, aZoom)
|
||||
{
|
||||
var docShell = aDocument.defaultView.
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIWebNavigation).
|
||||
QueryInterface(Components.interfaces.nsIDocShell);
|
||||
var docViewer = docShell.contentViewer.
|
||||
QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
|
||||
|
||||
docViewer.fullZoom = aZoom;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private section
|
||||
|
||||
|
@ -46,9 +46,10 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
test_browser.html \
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_browser.html \
|
||||
test_zoom.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
@ -16,16 +16,13 @@
|
||||
function doTest()
|
||||
{
|
||||
// Hit testing. See bug #726097
|
||||
var nodeObj = { value: null };
|
||||
var hititem = getAccessible("hititem", null, nodeObj);
|
||||
var [deltaX, deltaY] = getScreenCoords(nodeObj.value);
|
||||
var hititem = getAccessible("hititem");
|
||||
var hittest = getAccessible("hittest");
|
||||
|
||||
var hitX = {}, hitY = {}, hitWidth = {}, hitHeight = {};
|
||||
hititem.getBounds(hitX, hitY, hitWidth, hitHeight);
|
||||
var [hitX, hitY, hitWidth, hitHeight] = getBounds(hititem);
|
||||
var tgtX = hitX + hitWidth / 2;
|
||||
var tgtY = hitY + hitHeight / 2;
|
||||
|
||||
var tgtX = deltaX + (hitWidth.value / 2);
|
||||
var tgtY = deltaY + (hitHeight.value / 2);
|
||||
var rootAcc = getRootAccessible();
|
||||
var docAcc = getAccessible(document);
|
||||
var outerDocAcc = docAcc.parent;
|
||||
|
57
accessible/tests/mochitest/hittest/test_zoom.html
Normal file
57
accessible/tests/mochitest/hittest/test_zoom.html
Normal file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>childAtPoint when page is zoomed</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../layout.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
var tabDocument = currentTabDocument();
|
||||
var p1 = tabDocument.body.firstElementChild;
|
||||
var p2 = tabDocument.body.lastElementChild;
|
||||
|
||||
hitTest(tabDocument, p1, p1.firstChild);
|
||||
hitTest(tabDocument, p2, p2.firstChild);
|
||||
|
||||
zoomDocument(tabDocument, 2.0);
|
||||
|
||||
hitTest(tabDocument, p1, p1.firstChild);
|
||||
hitTest(tabDocument, p2, p2.firstChild);
|
||||
|
||||
closeBrowserWindow();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
openBrowserWindow(doTest,
|
||||
"data:text/html,<html><body><p>para 1</p><p>para 2</p></body></html>",
|
||||
{ left: 100, top: 100 });
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
|
||||
title="childAtPoint may return incorrect accessibles when page zoomed">
|
||||
Mozilla Bug 727942
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -22,6 +22,29 @@ function testChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild,
|
||||
is(childAcc, actualChildAcc, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if getChildAtPoint returns the given child and grand child accessibles
|
||||
* at coordinates of child accessible (direct and deep hit test).
|
||||
*/
|
||||
function hitTest(aContainerID, aChildID, aGrandChildID)
|
||||
{
|
||||
var container = getAccessible(aContainerID);
|
||||
var child = getAccessible(aChildID);
|
||||
var grandChild = getAccessible(aGrandChildID);
|
||||
|
||||
var [x, y] = getBoundsForDOMElm(child);
|
||||
|
||||
var actualChild = container.getChildAtPoint(x + 1, y + 1);
|
||||
is(actualChild, child,
|
||||
"Wrong child, expected: " + prettyName(child) +
|
||||
", got: " + prettyName(actualChild));
|
||||
|
||||
var actualGrandChild = container.getDeepestChildAtPoint(x + 1, y + 1);
|
||||
is(actualGrandChild, grandChild,
|
||||
"Wrong deepest child, expected: " + prettyName(grandChild) +
|
||||
", got: " + prettyName(actualGrandChild));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return child accessible at the given point.
|
||||
*
|
||||
@ -34,17 +57,14 @@ function testChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild,
|
||||
*/
|
||||
function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild)
|
||||
{
|
||||
var nodeObj = { value: null };
|
||||
var acc = getAccessible(aIdentifier, null, nodeObj);
|
||||
var node = nodeObj.value;
|
||||
|
||||
if (!acc || !node)
|
||||
var acc = getAccessible(aIdentifier);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
var [deltaX, deltaY] = getScreenCoords(node);
|
||||
var [screenX, screenY] = getBoundsForDOMElm(acc.DOMNode);
|
||||
|
||||
var x = deltaX + aX;
|
||||
var y = deltaY + aY;
|
||||
var x = screenX + aX;
|
||||
var y = screenY + aY;
|
||||
|
||||
try {
|
||||
if (aFindDeepestChild)
|
||||
@ -58,14 +78,16 @@ function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild)
|
||||
/**
|
||||
* Test the accessible boundaries.
|
||||
*/
|
||||
function testBounds(aID, aX, aY, aWidth, aHeight)
|
||||
function testBounds(aID)
|
||||
{
|
||||
var [expectedX, expectedY, expectedWidth, expectedHeight] =
|
||||
getBoundsForDOMElm(aID);
|
||||
|
||||
var [x, y, width, height] = getBounds(aID);
|
||||
is(x, aX, "Wrong x coordinate of " + prettyName(aID));
|
||||
is(y, aY, "Wrong y coordinate of " + prettyName(aID));
|
||||
// XXX: width varies depending on platform
|
||||
//is(width, aWidth, "Wrong width of " + prettyName(aID));
|
||||
is(height, aHeight, "Wrong height of " + prettyName(aID));
|
||||
is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
|
||||
is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
|
||||
is(width, expectedWidth, "Wrong width of " + prettyName(aID));
|
||||
is(height, expectedHeight, "Wrong height of " + prettyName(aID));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,24 +102,21 @@ function getBounds(aID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return DOM node coordinates relative screen as pair (x, y).
|
||||
* Return DOM node coordinates relative the screen and its size in device
|
||||
* pixels.
|
||||
*/
|
||||
function getScreenCoords(aNode)
|
||||
function getBoundsForDOMElm(aID)
|
||||
{
|
||||
if (aNode instanceof nsIDOMXULElement)
|
||||
return [node.boxObject.screenX, node.boxObject.screenY];
|
||||
var elm = getNode(aID);
|
||||
var elmWindow = elm.ownerDocument.defaultView;
|
||||
var winUtil = elmWindow.
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
// Ugly hack until bug 486200 is fixed.
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var descr = document.createElementNS(XUL_NS, "description");
|
||||
descr.setAttribute("value", "helper description");
|
||||
aNode.parentNode.appendChild(descr);
|
||||
var descrBoxObject = descr.boxObject;
|
||||
var descrRect = descr.getBoundingClientRect();
|
||||
var deltaX = descrBoxObject.screenX - descrRect.left;
|
||||
var deltaY = descrBoxObject.screenY - descrRect.top;
|
||||
aNode.parentNode.removeChild(descr);
|
||||
|
||||
var rect = aNode.getBoundingClientRect();
|
||||
return [rect.left + deltaX, rect.top + deltaY];
|
||||
var ratio = winUtil.screenPixelsPerCSSPixel;
|
||||
var rect = elm.getBoundingClientRect();
|
||||
return [ (rect.left + elmWindow.mozInnerScreenX) * ratio,
|
||||
(rect.top + elmWindow.mozInnerScreenY) * ratio,
|
||||
rect.width * ratio,
|
||||
rect.height * ratio ];
|
||||
}
|
||||
|
@ -17,14 +17,16 @@
|
||||
function doTest()
|
||||
{
|
||||
// Default state.
|
||||
testStates("f1_image", STATE_DEFAULT);
|
||||
testStates("f2_submit", STATE_DEFAULT);
|
||||
testStates("f3_submitbutton", STATE_DEFAULT);
|
||||
testStates("f4_button", 0, 0, STATE_DEFAULT);
|
||||
testStates("f4_image1", STATE_DEFAULT);
|
||||
testStates("f4_image2", 0, 0, STATE_DEFAULT);
|
||||
testStates("f4_submit", 0, 0, STATE_DEFAULT);
|
||||
testStates("f4_submitbutton", 0, 0, STATE_DEFAULT);
|
||||
testStates("f1_image", STATE_DEFAULT | STATE_FOCUSABLE);
|
||||
testStates("f2_submit", STATE_DEFAULT | STATE_FOCUSABLE);
|
||||
testStates("f3_submitbutton", STATE_DEFAULT | STATE_FOCUSABLE);
|
||||
testStates("f3_disabled_reset", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE, 0);
|
||||
testStates("f4_button", STATE_FOCUSABLE, 0, STATE_DEFAULT);
|
||||
testStates("f4_disabled_button", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE, 0);
|
||||
testStates("f4_image1", STATE_DEFAULT | STATE_FOCUSABLE);
|
||||
testStates("f4_image2", STATE_FOCUSABLE, 0, STATE_DEFAULT);
|
||||
testStates("f4_submit", STATE_FOCUSABLE, 0, STATE_DEFAULT);
|
||||
testStates("f4_submitbutton", STATE_FOCUSABLE, 0, STATE_DEFAULT);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
@ -62,6 +64,7 @@
|
||||
<form name="form3" method="get">
|
||||
<input type="text" name="hi">
|
||||
<button id="f3_submitbutton" type="submit">submit</button>
|
||||
<button id="f3_disabled_reset" type="reset" disabled>reset</button>
|
||||
</form>
|
||||
|
||||
<p>A form with normal button, two image buttons, submit button,
|
||||
@ -69,6 +72,7 @@
|
||||
<form name="form4" method="get">
|
||||
<input type="text" name="hi">
|
||||
<input id="f4_button" type="button" value="normal" name="normal-button">
|
||||
<input id="f4_disabled_button" type="button" value="disabled" name="disabled-button" disabled>
|
||||
<input id="f4_image1" type="image" value="image-button1" name="image-button1">
|
||||
<input id="f4_image2" type="image" value="image-button2" name="image-button2">
|
||||
<input id="f4_submit" type="submit" value="real-submit" name="real-submit">
|
||||
|
@ -106,6 +106,7 @@ pref("mozilla.widget.force-24bpp", true);
|
||||
pref("mozilla.widget.use-buffer-pixmap", true);
|
||||
pref("mozilla.widget.disable-native-theme", true);
|
||||
pref("layout.reflow.synthMouseMove", false);
|
||||
pref("dom.send_after_paint_to_content", true);
|
||||
|
||||
/* download manager (don't show the window or alert) */
|
||||
pref("browser.download.useDownloadDir", true);
|
||||
@ -353,9 +354,6 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
|
||||
// the database.
|
||||
pref("urlclassifier.confirm-age", 2700);
|
||||
|
||||
// Maximum size of the sqlite3 cache during an update, in bytes
|
||||
pref("urlclassifier.updatecachemax", 4194304);
|
||||
|
||||
// URL for checking the reason for a malware warning.
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
#endif
|
||||
@ -392,6 +390,7 @@ pref("layers.acceleration.force-enabled", true);
|
||||
// screen.enabled and screen.brightness properties.
|
||||
pref("dom.screenEnabledProperty.enabled", true);
|
||||
pref("dom.screenBrightnessProperty.enabled", true);
|
||||
pref("dom.mozScreenWhitelist", "http://localhost:7777");
|
||||
|
||||
// handle links targeting new windows
|
||||
// 1=current window/tab, 2=new window, 3=new tab in most recent window
|
||||
@ -430,6 +429,10 @@ pref("layout.frame_rate.precise", true);
|
||||
pref("b2g.remote-js.enabled", true);
|
||||
pref("b2g.remote-js.port", 9999);
|
||||
|
||||
// Handle hardware buttons in the b2g chrome package
|
||||
pref("b2g.keys.menu.enabled", true);
|
||||
pref("b2g.keys.search.enabled", false);
|
||||
|
||||
// Screen timeout in minutes
|
||||
pref("power.screen.timeout", 60);
|
||||
|
||||
|
@ -107,6 +107,6 @@ xul|thumb {
|
||||
-moz-border-right-colors: none !important;
|
||||
-moz-border-left-colors: none !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.4) !important;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
BIN
b2g/chrome/content/images/errorpage-larry-black.png
Normal file
BIN
b2g/chrome/content/images/errorpage-larry-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 850 B |
BIN
b2g/chrome/content/images/errorpage-larry-white.png
Normal file
BIN
b2g/chrome/content/images/errorpage-larry-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 886 B |
BIN
b2g/chrome/content/images/errorpage-warning.png
Normal file
BIN
b2g/chrome/content/images/errorpage-warning.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 631 B |
127
b2g/chrome/content/netError.css
Normal file
127
b2g/chrome/content/netError.css
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This defines the look-and-feel styling of the error pages.
|
||||
* (see: netError.xhtml)
|
||||
*
|
||||
* Original styling by William Price <bugzilla@mob.rice.edu>
|
||||
* Updated for mobile by: Wes Johnston <wjohnston@mozilla.com>
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 8px 8px;
|
||||
font-family: "Nokia Sans", Tahoma, sans-serif !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0px;
|
||||
padding: 0px 0px 0px 1em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0px;
|
||||
padding: 8px 0px;
|
||||
}
|
||||
|
||||
#errorPage {
|
||||
background-color: #CEE6F4;
|
||||
}
|
||||
|
||||
#errorPage.certerror {
|
||||
background-color: #EFD400;
|
||||
}
|
||||
|
||||
#errorPage.blockedsite {
|
||||
background-color: #BF0000;
|
||||
}
|
||||
|
||||
#errorTitle {
|
||||
background: url("chrome://browser/content/images/errorpage-warning.png") left center no-repeat;
|
||||
/* Scaled by .666 of their actual size */
|
||||
background-size: 40px 40px;
|
||||
background-origin: content-box;
|
||||
min-height: 60px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 500px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#errorPage.certerror #errorTitle {
|
||||
background-image: url("chrome://browser/content/images/errorpage-larry-black.png");
|
||||
}
|
||||
|
||||
#errorPage.blockedsite #errorTitle {
|
||||
background-image: url("chrome://browser/content/images/errorpage-larry-white.png");
|
||||
color: white;
|
||||
}
|
||||
|
||||
.errorTitleText {
|
||||
padding: 0px 0px 0px 50px;
|
||||
display: inline-block;
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
#errorPageContainer {
|
||||
background-color: white;
|
||||
border: 1px solid #999999;
|
||||
border-radius: 6px;
|
||||
padding: 6px 20px 20px;
|
||||
font-size: 14px;
|
||||
max-width: 500px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#errorShortDesc > p:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#errorShortDesc > p {
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #999999;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
#errorPage.blockedsite #errorShortDesc > p {
|
||||
font-weight: bold;
|
||||
border-bottom: none;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
#securityOverrideDiv {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
div[collapsed] {
|
||||
padding-left: 15px;
|
||||
background-image: url("chrome://browser/skin/images/arrowright-16.png");
|
||||
background-size: 11px 11px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left 0.3em;
|
||||
}
|
||||
|
||||
div[collapsed="true"] {
|
||||
background-image: url("chrome://browser/skin/images/arrowright-16.png");
|
||||
}
|
||||
|
||||
div[collapsed="false"] {
|
||||
background-image: url("chrome://browser/skin/images/arrowdown-16.png");
|
||||
}
|
||||
|
||||
div[collapsed="true"] > p,
|
||||
div[collapsed="true"] > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0.3em !important;
|
||||
}
|
@ -304,7 +304,6 @@
|
||||
</head>
|
||||
|
||||
<body id="errorPage" dir="&locale.dir;">
|
||||
|
||||
<!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
|
||||
<div id="errorContainer">
|
||||
<div id="errorTitlesContainer">
|
||||
@ -318,6 +317,7 @@
|
||||
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
||||
<h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
|
||||
<h1 id="et_netReset">&netReset.title;</h1>
|
||||
<h1 id="et_notCached">¬Cached.title;</h1>
|
||||
<h1 id="et_netOffline">&netOffline.title;</h1>
|
||||
<h1 id="et_netInterrupt">&netInterrupt.title;</h1>
|
||||
<h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
|
||||
@ -342,6 +342,7 @@
|
||||
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
||||
<div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
|
||||
<div id="ed_netReset">&netReset.longDesc;</div>
|
||||
<div id="ed_notCached">¬Cached.longDesc;</div>
|
||||
<div id="ed_netOffline">&netOffline.longDesc2;</div>
|
||||
<div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
|
||||
<div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
|
||||
|
@ -37,6 +37,23 @@ XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
|
||||
.getService(Ci.nsFocusManager);
|
||||
});
|
||||
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
// In order to use http:// scheme instead of file:// scheme
|
||||
// (that is much more restricted) the following code kick-off
|
||||
// a local http server listening on http://127.0.0.1:7777 and
|
||||
// http://localhost:7777.
|
||||
function startupHttpd(baseDir, port) {
|
||||
const httpdURL = 'chrome://browser/content/httpd.js';
|
||||
let httpd = {};
|
||||
Services.scriptloader.loadSubScript(httpdURL, httpd);
|
||||
let server = new httpd.nsHttpServer();
|
||||
server.registerDirectory('/', new LocalFile(baseDir));
|
||||
server.registerContentType('appcache', 'text/cache-manifest');
|
||||
server.start(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME Bug 707625
|
||||
// until we have a proper security model, add some rights to
|
||||
// the pre-installed web applications
|
||||
@ -105,7 +122,21 @@ var shell = {
|
||||
|
||||
let fileScheme = 'file://';
|
||||
if (homeURL.substring(0, fileScheme.length) == fileScheme) {
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
homeURL = homeURL.replace(fileScheme, '');
|
||||
|
||||
let baseDir = homeURL.split('/');
|
||||
baseDir.pop();
|
||||
baseDir = baseDir.join('/');
|
||||
|
||||
const SERVER_PORT = 7777;
|
||||
startupHttpd(baseDir, SERVER_PORT);
|
||||
|
||||
let baseHost = 'http://localhost';
|
||||
homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
|
||||
#else
|
||||
homeURL = 'http://localhost:7777' + homeURL.replace(fileScheme, '');
|
||||
#endif
|
||||
}
|
||||
addPermissions([homeURL]);
|
||||
} catch (e) {
|
||||
@ -213,10 +244,12 @@ var shell = {
|
||||
case 'AppCommand':
|
||||
switch (evt.command) {
|
||||
case 'Menu':
|
||||
this.sendEvent(content, 'menu');
|
||||
if (Services.prefs.getBoolPref('b2g.keys.menu.enabled'))
|
||||
this.sendEvent(content, 'menu');
|
||||
break;
|
||||
case 'Search':
|
||||
this.toggleDebug();
|
||||
if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
|
||||
this.toggleDebug();
|
||||
break;
|
||||
case 'VolumeUp':
|
||||
this.changeVolume(1);
|
||||
|
@ -20,11 +20,18 @@
|
||||
#ifndef MOZ_TOUCH
|
||||
<script type="application/javascript" src="chrome://browser/content/touch.js"/>
|
||||
#endif
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
<script type="application/javascript" src="chrome://browser/content/httpd.js"/>
|
||||
#endif
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
</commandset>
|
||||
|
||||
<browser id="homescreen" type="content-primary" flex="1" style="overflow: hidden;"/>
|
||||
<browser id="homescreen"
|
||||
type="content-primary"
|
||||
flex="1"
|
||||
style="overflow: hidden;"
|
||||
src="data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGJvZHkgc3R5bGU9ImJhY2tncm91bmQ6YmxhY2s7Ij48L2JvZHk+PC9odG1sPgo="/>
|
||||
</window>
|
||||
|
||||
|
@ -84,6 +84,18 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
|
||||
content.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function maybeShowIme(targetElement) {
|
||||
// FIXME/bug 729623: work around apparent bug in the IME manager
|
||||
// in gecko.
|
||||
let readonly = targetElement.getAttribute('readonly');
|
||||
if (readonly)
|
||||
return false;
|
||||
|
||||
let type = targetElement.type;
|
||||
fireEvent('showime', { type: type });
|
||||
return true;
|
||||
}
|
||||
|
||||
let constructor = {
|
||||
handleEvent: function vkm_handleEvent(evt) {
|
||||
switch (evt.type) {
|
||||
@ -102,9 +114,7 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
|
||||
if (evt.target != activeElement || isKeyboardOpened)
|
||||
return;
|
||||
|
||||
let type = activeElement.type;
|
||||
fireEvent('showime', { type: type });
|
||||
isKeyboardOpened = true;
|
||||
isKeyboardOpened = maybeShowIme(activeElement);
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -112,11 +122,10 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
|
||||
let shouldOpen = parseInt(data);
|
||||
if (shouldOpen && !isKeyboardOpened) {
|
||||
activeElement = Services.fm.focusedElement;
|
||||
if (!activeElement)
|
||||
if (!activeElement || !maybeShowIme(activeElement)) {
|
||||
activeElement = null;
|
||||
return;
|
||||
|
||||
let type = activeElement.type;
|
||||
fireEvent('showime', { type: type });
|
||||
}
|
||||
} else if (!shouldOpen && isKeyboardOpened) {
|
||||
fireEvent('hideime');
|
||||
}
|
||||
@ -313,7 +322,7 @@ const KineticPanning = {
|
||||
return this.target !== null;
|
||||
},
|
||||
|
||||
_target: null,
|
||||
target: null,
|
||||
start: function kp_start(target) {
|
||||
this.target = target;
|
||||
|
||||
|
@ -5,14 +5,21 @@ chrome.jar:
|
||||
% content browser %content/
|
||||
|
||||
* content/shell.xul (content/shell.xul)
|
||||
content/shell.js (content/shell.js)
|
||||
* content/shell.js (content/shell.js)
|
||||
#ifndef MOZ_TOUCH
|
||||
content/touch.js (content/touch.js)
|
||||
#endif
|
||||
content/commandUtil.js (content/commandUtil.js)
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
content/httpd.js (content/httpd.js)
|
||||
#endif
|
||||
content/webapi.js (content/webapi.js)
|
||||
content/content.css (content/content.css)
|
||||
|
||||
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
||||
% override chrome://global/skin/netError.css chrome://browser/content/netError.css
|
||||
content/netError.xhtml (content/netError.xhtml)
|
||||
content/netError.css (content/netError.css)
|
||||
content/images/errorpage-larry-black.png (content/images/errorpage-larry-black.png)
|
||||
content/images/errorpage-larry-white.png (content/images/errorpage-larry-white.png)
|
||||
content/images/errorpage-warning.png (content/images/errorpage-warning.png)
|
@ -401,6 +401,8 @@
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
@BINPATH@/components/nsWifiWorker.js
|
||||
@BINPATH@/components/nsWifiWorker.manifest
|
||||
#endif
|
||||
|
@ -181,7 +181,7 @@ image.study-result {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 2px;
|
||||
-moz-border-radius: 100%;
|
||||
border-radius: 100%;
|
||||
margin-right: 25px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
@ -102,9 +102,8 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
font-size: 16px;
|
||||
padding: 8px 12px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
-moz-box-shadow:
|
||||
border-radius: 0.5em;
|
||||
box-shadow:
|
||||
inset rgba(0, 0, 0, 0.2) 0 1px 1px,
|
||||
inset rgba(255, 255, 255, 1) 0 3px 1px,
|
||||
inset rgba(255, 255, 255, 0.3) 0 16px 0px,
|
||||
@ -122,9 +121,8 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
padding: 8px 12px;
|
||||
width: 240px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
-moz-box-shadow:
|
||||
border-radius: 0.5em;
|
||||
box-shadow:
|
||||
inset rgba(0, 0, 0, 0.2) 0 1px 1px,
|
||||
inset rgba(255, 255, 255, 1) 0 3px 1px,
|
||||
inset rgba(255, 255, 255, 0.3) 0 16px 0px,
|
||||
@ -143,10 +141,9 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
padding: 8px 24px;
|
||||
margin: 24px auto;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/callout.png') no-repeat top center;
|
||||
-moz-box-shadow:
|
||||
box-shadow:
|
||||
inset rgba(185, 221, 234, 0.2) 0 -10px 12px,
|
||||
inset rgba(185, 221, 234, 1) 0 0px 1px,
|
||||
inset rgba(255, 255, 255, 0.2) 0 10px 12px;
|
||||
@ -161,10 +158,9 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
padding: 8px 24px;
|
||||
margin: 8px auto;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/callout.png') no-repeat top center;
|
||||
-moz-box-shadow:
|
||||
box-shadow:
|
||||
inset rgba(185, 221, 234, 0.2) 0 -10px 12px,
|
||||
inset rgba(185, 221, 234, 1) 0 0px 1px,
|
||||
inset rgba(255, 255, 255, 0.2) 0 10px 12px;
|
||||
@ -197,8 +193,7 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
padding: 4px 40px;
|
||||
width: 800px;
|
||||
text-align: left;
|
||||
-moz-border-radius: 0.25em;
|
||||
-webkit-border-radius: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
border-top: 1px solid #adb6ba;
|
||||
border-left: 1px solid #adb6ba;
|
||||
border-right: 1px solid #adb6ba;
|
||||
@ -223,7 +218,7 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
font-size: 14px;
|
||||
text-shadow: 1px 1px 1px rgba(173, 182, 186, 1);
|
||||
background-color: rgba(173, 182, 186, 0.3);
|
||||
-moz-box-shadow:
|
||||
box-shadow:
|
||||
inset rgba(0, 0, 0, 0.2) 0 -10px 12px;
|
||||
padding: 9px 8px 8px 8px;
|
||||
}
|
||||
@ -255,4 +250,4 @@ src: url('chrome://testpilot/skin/fonts/DroidSans-Bold.ttf') format('truetype');
|
||||
|
||||
p.embiggened {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ body {
|
||||
font-size: 16px;
|
||||
padding: 6px 20px 20px 20px;
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/images/callout.png') no-repeat top center;
|
||||
/* display: inline; */
|
||||
}
|
||||
@ -114,7 +113,6 @@ body {
|
||||
padding: 8px 12px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
box-shadow:
|
||||
inset rgba(0, 0, 0, 0.2) 0 1px 1px,
|
||||
inset rgba(255, 255, 255, 1) 0 3px 1px,
|
||||
@ -133,7 +131,6 @@ body {
|
||||
width: 240px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
box-shadow:
|
||||
inset rgba(0, 0, 0, 0.2) 0 1px 1px,
|
||||
inset rgba(255, 255, 255, 1) 0 3px 1px,
|
||||
@ -152,7 +149,6 @@ body {
|
||||
margin: 24px auto;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/images/callout.png') no-repeat top center;
|
||||
box-shadow:
|
||||
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
|
||||
@ -174,7 +170,6 @@ body {
|
||||
margin: 8px auto;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/images/callout.png') no-repeat top center;
|
||||
box-shadow:
|
||||
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
|
||||
@ -191,7 +186,6 @@ body {
|
||||
margin: 8px auto;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/images/callout_continue.png') no-repeat top center;
|
||||
box-shadow:
|
||||
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
|
||||
@ -238,7 +232,6 @@ body {
|
||||
width: 800px;
|
||||
text-align: left;
|
||||
border-radius: 0.25em;
|
||||
-webkit-border-radius: 0.25em;
|
||||
border-top: 1px solid #adb6ba;
|
||||
border-left: 1px solid #adb6ba;
|
||||
border-right: 1px solid #adb6ba;
|
||||
|
@ -759,12 +759,6 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
|
||||
// the database.
|
||||
pref("urlclassifier.confirm-age", 2700);
|
||||
|
||||
// Maximum size of the sqlite3 cache during an update, in bytes
|
||||
pref("urlclassifier.updatecachemax", 41943040);
|
||||
|
||||
// Maximum size of the sqlite3 cache for lookups, in bytes
|
||||
pref("urlclassifier.lookupcachemax", 1048576);
|
||||
|
||||
// URL for checking the reason for a malware warning.
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
|
@ -165,24 +165,25 @@ var StarUI = {
|
||||
return;
|
||||
}
|
||||
|
||||
var loadObserver = {
|
||||
_self: this,
|
||||
_itemId: aItemId,
|
||||
_anchorElement: aAnchorElement,
|
||||
_position: aPosition,
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
this._overlayLoading = true;
|
||||
document.loadOverlay(
|
||||
"chrome://browser/content/places/editBookmarkOverlay.xul",
|
||||
(function (aSubject, aTopic, aData) {
|
||||
//XXX We just caused localstore.rdf to be re-applied (bug 640158)
|
||||
retrieveToolbarIconsizesFromTheme();
|
||||
|
||||
this._self._overlayLoading = false;
|
||||
this._self._overlayLoaded = true;
|
||||
this._self._doShowEditBookmarkPanel(this._itemId, this._anchorElement,
|
||||
this._position);
|
||||
}
|
||||
};
|
||||
this._overlayLoading = true;
|
||||
document.loadOverlay("chrome://browser/content/places/editBookmarkOverlay.xul",
|
||||
loadObserver);
|
||||
// Move the header (star, title, button) into the grid,
|
||||
// so that it aligns nicely with the other items (bug 484022).
|
||||
let header = this._element("editBookmarkPanelHeader");
|
||||
let rows = this._element("editBookmarkPanelGrid").lastChild;
|
||||
rows.insertBefore(header, rows.firstChild);
|
||||
header.hidden = false;
|
||||
|
||||
this._overlayLoading = false;
|
||||
this._overlayLoaded = true;
|
||||
this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
|
||||
}).bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
_doShowEditBookmarkPanel:
|
||||
@ -192,13 +193,6 @@ var StarUI = {
|
||||
|
||||
this._blockCommands(); // un-done in the popuphiding handler
|
||||
|
||||
// Move the header (star, title, possibly a button) into the grid,
|
||||
// so that it aligns nicely with the other items (bug 484022).
|
||||
var rows = this._element("editBookmarkPanelGrid").lastChild;
|
||||
var header = this._element("editBookmarkPanelHeader");
|
||||
rows.insertBefore(header, rows.firstChild);
|
||||
header.hidden = false;
|
||||
|
||||
// Set panel title:
|
||||
// if we are batching, i.e. the bookmark has been added now,
|
||||
// then show Page Bookmarked, else if the bookmark did already exist,
|
||||
|
@ -3573,7 +3573,6 @@ const BrowserSearch = {
|
||||
loadAddEngines: function BrowserSearch_loadAddEngines() {
|
||||
var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
|
||||
var where = newWindowPref == 3 ? "tab" : "window";
|
||||
var regionBundle = document.getElementById("bundle_browser_region");
|
||||
var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true);
|
||||
openUILinkIn(searchEnginesURL, where);
|
||||
}
|
||||
@ -4043,7 +4042,9 @@ var FullScreen = {
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen);
|
||||
|
||||
// Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc).
|
||||
window.addEventListener("deactivate", this.exitDomFullScreen, true);
|
||||
if (gPrefService.getBoolPref("full-screen-api.exit-on-deactivate")) {
|
||||
window.addEventListener("deactivate", this.exitDomFullScreen, true);
|
||||
}
|
||||
|
||||
// Cancel any "hide the toolbar" animation which is in progress, and make
|
||||
// the toolbar hide immediately.
|
||||
|
@ -26,10 +26,8 @@ function test() {
|
||||
|
||||
// Now trigger the invalid URI test
|
||||
executeSoon(function () {
|
||||
info("Dialog closed? " + domwindow.closed + "\n");
|
||||
let consoleListener = {
|
||||
observe: function (m) {
|
||||
info("m: " + m + "\n");
|
||||
info("m.message: " + m.message + "\n");
|
||||
if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
|
||||
ok(true, "drop was blocked");
|
||||
@ -42,18 +40,27 @@ function test() {
|
||||
Services.console.unregisterListener(consoleListener);
|
||||
});
|
||||
|
||||
// The drop handler throws an exception when dragging URIs that inherit
|
||||
// principal, e.g. javascript:
|
||||
expectUncaughtException();
|
||||
let originalHandler = homeButtonObserver.onDrop;
|
||||
homeButtonObserver.onDrop = function (aEvent) {
|
||||
info("homeButtonObserver.onDrop called");
|
||||
originalHandler(aEvent);
|
||||
};
|
||||
registerCleanupFunction(function () {
|
||||
homeButtonObserver.onDrop = originalHandler;
|
||||
executeSoon(function () {
|
||||
info("Attempting second drop, of a javascript: URI");
|
||||
// The drop handler throws an exception when dragging URIs that inherit
|
||||
// principal, e.g. javascript:
|
||||
expectUncaughtException();
|
||||
let originalHandler = homeButtonObserver.onDrop;
|
||||
homeButtonObserver.onDrop = function (aEvent) {
|
||||
info("homeButtonObserver.onDrop called");
|
||||
try {
|
||||
originalHandler(aEvent);
|
||||
} catch (ex) {
|
||||
info("originalHandler threw an exception: " + ex);
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
registerCleanupFunction(function () {
|
||||
homeButtonObserver.onDrop = originalHandler;
|
||||
});
|
||||
chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "javascript:8888"}]], "copy", window, EventUtils);
|
||||
info("Triggered the second drop of a javascript: URI");
|
||||
});
|
||||
chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "javascript:8888"}]], "copy", window, EventUtils);
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -403,7 +403,8 @@ function getShellService()
|
||||
try {
|
||||
shell = Components.classes["@mozilla.org/browser/shell-service;1"]
|
||||
.getService(Components.interfaces.nsIShellService);
|
||||
} catch (e) {dump("*** e = " + e + "\n");}
|
||||
} catch (e) {
|
||||
}
|
||||
return shell;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,6 @@ FirefoxProfileMigrator.prototype = {
|
||||
migrate : function Firefox_migrate(aItems, aStartup, aProfile)
|
||||
{
|
||||
if (aStartup) {
|
||||
aStartup.doStartup();
|
||||
this._replaceBookmarks = true;
|
||||
}
|
||||
|
||||
@ -246,6 +245,11 @@ FirefoxProfileMigrator.prototype = {
|
||||
if (aItems & MIGRATOR.PASSWORDS)
|
||||
this._migratePasswords();
|
||||
|
||||
// The password manager encryption key must be copied before startup.
|
||||
if (aStartup) {
|
||||
aStartup.doStartup();
|
||||
}
|
||||
|
||||
if (aItems & MIGRATOR.FORMDATA)
|
||||
this._migrateFormData();
|
||||
|
||||
|
@ -153,6 +153,7 @@ var gEngineManagerDialog = {
|
||||
while (Services.prompt.prompt(window, title, msg, alias, null, {})) {
|
||||
var bduplicate = false;
|
||||
var eduplicate = false;
|
||||
var dupName = "";
|
||||
|
||||
if (alias.value != "") {
|
||||
try {
|
||||
@ -168,6 +169,7 @@ var gEngineManagerDialog = {
|
||||
if (engine.alias == alias.value &&
|
||||
engine.name != selectedEngine.name) {
|
||||
eduplicate = true;
|
||||
dupName = engine.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -177,8 +179,7 @@ var gEngineManagerDialog = {
|
||||
if (eduplicate || bduplicate) {
|
||||
var dtitle = strings.getString("duplicateTitle");
|
||||
var bmsg = strings.getString("duplicateBookmarkMsg");
|
||||
var emsg = strings.getFormattedString("duplicateEngineMsg",
|
||||
[engine.name]);
|
||||
var emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
|
||||
|
||||
Services.prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
|
||||
} else {
|
||||
|
@ -50,9 +50,9 @@
|
||||
]>
|
||||
|
||||
<bindings id="SearchBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="searchbar">
|
||||
<resources>
|
||||
@ -96,13 +96,12 @@
|
||||
<xul:image class="search-go-button"
|
||||
anonid="search-go-button"
|
||||
onclick="handleSearchCommand(event);"
|
||||
tooltiptext="&searchEndCap.label;" />
|
||||
tooltiptext="&searchEndCap.label;"/>
|
||||
</xul:hbox>
|
||||
</xul:textbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIObserver">
|
||||
|
||||
<constructor><![CDATA[
|
||||
if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
|
||||
return;
|
||||
@ -164,7 +163,7 @@
|
||||
<getter><![CDATA[
|
||||
var currentEngine = this.searchService.currentEngine;
|
||||
// Return a dummy engine if there is no currentEngine
|
||||
return currentEngine || {name:"", uri:null};
|
||||
return currentEngine || {name: "", uri: null};
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
@ -335,7 +334,8 @@
|
||||
// indexes as items are removed.
|
||||
var items = popup.childNodes;
|
||||
for (var i = items.length - 1; i >= 0; i--) {
|
||||
if (items[i].getAttribute("class").indexOf("addengine") != -1)
|
||||
if (items[i].classList.contains("addengine-item") ||
|
||||
items[i].classList.contains("addengine-separator"))
|
||||
popup.removeChild(items[i]);
|
||||
}
|
||||
|
||||
@ -444,7 +444,7 @@
|
||||
<body><![CDATA[
|
||||
// Find the new index
|
||||
var newIndex = this.engines.indexOf(this.currentEngine);
|
||||
newIndex += (isNextEngine) ? 1 : -1;
|
||||
newIndex += isNextEngine ? 1 : -1;
|
||||
|
||||
if (newIndex >= 0 && newIndex < this.engines.length)
|
||||
this.currentEngine = this.engines[newIndex];
|
||||
@ -495,13 +495,12 @@
|
||||
openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="command"><![CDATA[
|
||||
const target = event.originalTarget;
|
||||
if (target.getAttribute("class").indexOf("addengine-item") != -1) {
|
||||
if (target.classList.contains("addengine-item")) {
|
||||
var searchService =
|
||||
Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
@ -719,7 +718,7 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- overload |onTextEntered| in autocomplete.xml -->
|
||||
<!-- override |onTextEntered| in autocomplete.xml -->
|
||||
<method name="onTextEntered">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
|
@ -35,7 +35,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
let tab1 = gBrowser.addTab("about:robots");
|
||||
let tab1 = gBrowser.addTab("about:rights");
|
||||
let tab2 = gBrowser.addTab("about:mozilla");
|
||||
tab1.linkedBrowser.addEventListener("load", mainPart, true);
|
||||
waitForExplicitFinish();
|
||||
@ -44,7 +44,7 @@ function test() {
|
||||
tab1.linkedBrowser.removeEventListener("load", mainPart, true);
|
||||
|
||||
// Tell the session storer that the tab is pinned
|
||||
let newTabState = '{"entries":[{"url":"about:robots"}],"pinned":true,"userTypedValue":"Hello World!"}';
|
||||
let newTabState = '{"entries":[{"url":"about:rights"}],"pinned":true,"userTypedValue":"Hello World!"}';
|
||||
ss.setTabState(tab1, newTabState);
|
||||
|
||||
// Undo pinning
|
||||
|
@ -4,7 +4,7 @@
|
||||
function test() {
|
||||
let state = { windows: [{ tabs: [
|
||||
{entries: [{url: "about:mozilla"}], hidden: true},
|
||||
{entries: [{url: "about:robots"}], hidden: true}
|
||||
{entries: [{url: "about:rights"}], hidden: true}
|
||||
] }] };
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
@ -252,7 +252,7 @@ function onWindowUnloaded() {
|
||||
let previousClosedWindowData = ss.getClosedWindowData();
|
||||
|
||||
// Now we want to open a new window
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:robots");
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
|
@ -5,7 +5,7 @@ function test() {
|
||||
let oldState = {
|
||||
windows: [{
|
||||
tabs: [
|
||||
{ entries: [{ url: "about:robots" }], hidden: true },
|
||||
{ entries: [{ url: "about:mozilla" }], hidden: true },
|
||||
{ entries: [{ url: "about:blank" }], hidden: false }
|
||||
]
|
||||
}]
|
||||
|
@ -40,7 +40,7 @@ const testState = {
|
||||
windows: [{
|
||||
tabs: [
|
||||
{ entries: [{ url: "about:blank" }] },
|
||||
{ entries: [{ url: "about:robots" }] }
|
||||
{ entries: [{ url: "about:rights" }] }
|
||||
]
|
||||
}]
|
||||
};
|
||||
@ -174,7 +174,7 @@ function test_duplicateTab() {
|
||||
is(busyEventCount, 1);
|
||||
is(readyEventCount, 1);
|
||||
is(ss.getTabValue(newTab, "baz"), "qux");
|
||||
is(newTab.linkedBrowser.currentURI.spec, "about:robots");
|
||||
is(newTab.linkedBrowser.currentURI.spec, "about:rights");
|
||||
|
||||
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
|
||||
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
|
||||
@ -215,7 +215,7 @@ function test_undoCloseTab() {
|
||||
is(busyEventCount, 1);
|
||||
is(readyEventCount, 1);
|
||||
is(ss.getTabValue(reopenedTab, "baz"), "qux");
|
||||
is(reopenedTab.linkedBrowser.currentURI.spec, "about:robots");
|
||||
is(reopenedTab.linkedBrowser.currentURI.spec, "about:rights");
|
||||
|
||||
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
|
||||
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
|
||||
|
@ -40,7 +40,7 @@ const testState = {
|
||||
windows: [{
|
||||
tabs: [
|
||||
{ entries: [{ url: "about:blank" }] },
|
||||
{ entries: [{ url: "about:robots" }] }
|
||||
{ entries: [{ url: "about:mozilla" }] }
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ function test() {
|
||||
|
||||
// Open a new window, which should trigger a save event soon.
|
||||
waitForSaveState(onSaveState);
|
||||
newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:robots");
|
||||
newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:rights");
|
||||
}
|
||||
|
||||
function onSaveState() {
|
||||
|
@ -20,7 +20,7 @@ function test() {
|
||||
assertNumberOfTabs(1, "we start off with one tab");
|
||||
|
||||
// setup
|
||||
let tab = gBrowser.addTab("about:robots");
|
||||
let tab = gBrowser.addTab("about:mozilla");
|
||||
|
||||
whenTabIsLoaded(tab, function () {
|
||||
// hide the newly created tab
|
||||
@ -35,7 +35,7 @@ function test() {
|
||||
|
||||
// check that everything was restored correctly, clean up and finish
|
||||
whenTabIsLoaded(tab, function () {
|
||||
is(tab.linkedBrowser.currentURI.spec, "about:robots", "restored tab has correct url");
|
||||
is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "restored tab has correct url");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
finish();
|
||||
|
@ -11,7 +11,6 @@ function test() {
|
||||
let brokenState = {
|
||||
windows: [
|
||||
{ tabs: [{ entries: [{ url: "about:mozilla" }] }] }
|
||||
//{ tabs: [{ entries: [{ url: "about:robots" }] }] },
|
||||
],
|
||||
selectedWindow: 2
|
||||
};
|
||||
@ -32,4 +31,3 @@ function test() {
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,6 @@ nsWindowsShellService::ShortcutMaintenance()
|
||||
bool
|
||||
nsWindowsShellService::IsDefaultBrowserVista(bool* aIsDefaultBrowser)
|
||||
{
|
||||
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
||||
IApplicationAssociationRegistration* pAAR;
|
||||
|
||||
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
|
||||
@ -355,7 +354,6 @@ nsWindowsShellService::IsDefaultBrowserVista(bool* aIsDefaultBrowser)
|
||||
pAAR->Release();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@
|
||||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_sidebar.xpt
|
||||
@BINPATH@/components/dom_sms.xpt
|
||||
@ -379,6 +380,8 @@
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
@BINPATH@/components/nsWifiWorker.js
|
||||
@BINPATH@/components/nsWifiWorker.manifest
|
||||
#endif
|
||||
|
@ -169,11 +169,11 @@ libs:: $(addsuffix .xml,$(SEARCH_PLUGINS))
|
||||
done
|
||||
|
||||
install:: $(addsuffix .xml,$(SEARCH_PLUGINS))
|
||||
$(NSINSTALL) -D $(DESTDIR)$mozappdir/searchplugins
|
||||
$(NSINSTALL) -D $(DESTDIR)$(mozappdir)/searchplugins
|
||||
for i in $^; do \
|
||||
SEARCH_PLUGIN_BASE=`basename $$SEARCH_PLUGIN`;\
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
|
||||
$$SEARCH_PLUGIN > $(DESTDIR)$mozappdir/searchplugins/$$SEARCH_PLUGIN_BASE; \
|
||||
$$SEARCH_PLUGIN > $(DESTDIR)$(mozappdir)/searchplugins/$$SEARCH_PLUGIN_BASE; \
|
||||
done
|
||||
|
||||
|
||||
|
@ -75,13 +75,13 @@ OrganizerQueryAllBookmarks=All Bookmarks
|
||||
OrganizerQueryTags=Tags
|
||||
|
||||
# LOCALIZATION NOTE (tagResultLabel) :
|
||||
# This is what we use to form the label (for screen readers)
|
||||
# for url bar autocomplete results of type "tag"
|
||||
# Noun used to describe the location bar autocomplete result type
|
||||
# to users with screen readers
|
||||
# See createResultLabel() in urlbarBindings.xml
|
||||
tagResultLabel=Tag
|
||||
# LOCALIZATION NOTE (bookmarkResultLabel) :
|
||||
# This is what we use to form the label (for screen readers)
|
||||
# for url bar autocomplete results of type "bookmark"
|
||||
# Noun used to describe the location bar autocomplete result type
|
||||
# to users with screen readers
|
||||
# See createResultLabel() in urlbarBindings.xml
|
||||
bookmarkResultLabel=Bookmark
|
||||
|
||||
|
@ -282,5 +282,5 @@
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 2px 2px 2px #CCC;
|
||||
box-shadow: 2px 2px 2px #CCC;
|
||||
}
|
||||
|
@ -284,5 +284,5 @@
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 2px 2px 2px #CCC;
|
||||
box-shadow: 2px 2px 2px #CCC;
|
||||
}
|
||||
|
@ -282,5 +282,5 @@
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 2px 2px 2px #CCC;
|
||||
box-shadow: 2px 2px 2px #CCC;
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ class DMError(Exception):
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
def abstractmethod(method):
|
||||
line = method.func_code.co_firstlineno
|
||||
filename = method.func_code.co_filename
|
||||
@ -70,9 +69,18 @@ def abstractmethod(method):
|
||||
'should be implemented by a concrete class' %
|
||||
(repr(method), filename,line))
|
||||
return not_implemented
|
||||
|
||||
|
||||
class DeviceManager:
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def shell(self, cmd, outputfile, env=None, cwd=None):
|
||||
"""
|
||||
executes shell command on device
|
||||
returns:
|
||||
success: Return code from command
|
||||
failure: None
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def pushFile(self, localname, destname):
|
||||
"""
|
||||
@ -168,25 +176,27 @@ class DeviceManager:
|
||||
success: array of process tuples
|
||||
failure: None
|
||||
"""
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def fireProcess(self, appname, failIfRunning=False):
|
||||
"""
|
||||
external function
|
||||
DEPRECATED: Use shell() or launchApplication() for new code
|
||||
returns:
|
||||
success: pid
|
||||
failure: None
|
||||
"""
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
|
||||
"""
|
||||
external function
|
||||
DEPRECATED: Use shell() or launchApplication() for new code
|
||||
returns:
|
||||
success: output filename
|
||||
failure: None
|
||||
"""
|
||||
|
||||
|
||||
def communicate(self, process, timeout = 600, interval = 5):
|
||||
"""
|
||||
loops until 'process' has exited or 'timeout' seconds is reached
|
||||
@ -581,3 +591,35 @@ class NetworkTools:
|
||||
print "Socket error trying to find open port"
|
||||
|
||||
return seed
|
||||
|
||||
def _pop_last_line(file):
|
||||
'''
|
||||
Utility function to get the last line from a file (shared between ADB and
|
||||
SUT device managers). Function also removes it from the file. Intended to
|
||||
strip off the return code from a shell command.
|
||||
'''
|
||||
bytes_from_end = 1
|
||||
file.seek(0, 2)
|
||||
length = file.tell() + 1
|
||||
while bytes_from_end <= length:
|
||||
file.seek((-1)*bytes_from_end, 2)
|
||||
data = file.read()
|
||||
|
||||
if bytes_from_end == length and len(data) == 0: # no data, return None
|
||||
return None
|
||||
|
||||
if data[0] == '\n' or bytes_from_end == length:
|
||||
# found the last line, which should have the return value
|
||||
if data[0] == '\n':
|
||||
data = data[1:]
|
||||
|
||||
# truncate off the return code line
|
||||
file.truncate(length - bytes_from_end)
|
||||
file.seek(0,2)
|
||||
file.write('\0')
|
||||
|
||||
return data
|
||||
|
||||
bytes_from_end += 1
|
||||
|
||||
return None
|
||||
|
@ -1,5 +1,5 @@
|
||||
import subprocess
|
||||
from devicemanager import DeviceManager, DMError
|
||||
from devicemanager import DeviceManager, DMError, _pop_last_line
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
@ -63,6 +63,47 @@ class DeviceManagerADB(DeviceManager):
|
||||
else:
|
||||
print "restarting as root failed"
|
||||
|
||||
# external function: executes shell command on device
|
||||
# returns:
|
||||
# success: <return code>
|
||||
# failure: None
|
||||
def shell(self, cmd, outputfile, env=None, cwd=None):
|
||||
# need to quote special characters here
|
||||
for (index, arg) in enumerate(cmd):
|
||||
if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find("\""):
|
||||
cmd[index] = '\'%s\'' % arg
|
||||
|
||||
# This is more complex than you'd think because adb doesn't actually
|
||||
# return the return code from a process, so we have to capture the output
|
||||
# to get it
|
||||
# FIXME: this function buffers all output of the command into memory,
|
||||
# always. :(
|
||||
cmdline = subprocess.list2cmdline(cmd) + "; echo $?"
|
||||
|
||||
# prepend cwd and env to command if necessary
|
||||
if cwd:
|
||||
cmdline = "cd %s; %s" % (cwd, cmdline)
|
||||
if env:
|
||||
envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
|
||||
cmdline = envstr + "; " + cmdline
|
||||
|
||||
# all output should be in stdout
|
||||
proc = subprocess.Popen(["adb", "shell", cmdline],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdout, stderr) = proc.communicate()
|
||||
outputfile.write(stdout.rstrip('\n'))
|
||||
|
||||
lastline = _pop_last_line(outputfile)
|
||||
if lastline:
|
||||
m = re.search('([0-9]+)', lastline)
|
||||
if m:
|
||||
return_code = m.group(1)
|
||||
outputfile.seek(-2, 2)
|
||||
outputfile.truncate() # truncate off the return code
|
||||
return return_code
|
||||
|
||||
return None
|
||||
|
||||
# external function
|
||||
# returns:
|
||||
# success: True
|
||||
@ -264,6 +305,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
return ret
|
||||
|
||||
# external function
|
||||
# DEPRECATED: Use shell() or launchApplication() for new code
|
||||
# returns:
|
||||
# success: pid
|
||||
# failure: None
|
||||
@ -275,6 +317,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
return self.launchProcess(parts, failIfRunning)
|
||||
|
||||
# external function
|
||||
# DEPRECATED: Use shell() or launchApplication() for new code
|
||||
# returns:
|
||||
# success: output filename
|
||||
# failure: None
|
||||
@ -327,6 +370,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
if name == appname:
|
||||
p = self.runCmdAs(["shell", "kill", pid])
|
||||
return p.stdout.read()
|
||||
|
||||
return None
|
||||
|
||||
# external function
|
||||
@ -611,7 +655,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
args.insert(1, "run-as")
|
||||
args.insert(2, self.packageName)
|
||||
args.insert(0, "adb")
|
||||
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
def runCmdAs(self, args):
|
||||
if self.useRunAs:
|
||||
|
@ -47,7 +47,18 @@ import subprocess
|
||||
from threading import Thread
|
||||
import traceback
|
||||
import sys
|
||||
from devicemanager import DeviceManager, DMError, FileError, NetworkTools
|
||||
import StringIO
|
||||
from devicemanager import DeviceManager, DMError, FileError, NetworkTools, _pop_last_line
|
||||
|
||||
class AgentError(Exception):
|
||||
"SUTAgent-specific exception."
|
||||
|
||||
def __init__(self, msg= '', fatal = False):
|
||||
self.msg = msg
|
||||
self.fatal = fatal
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class DeviceManagerSUT(DeviceManager):
|
||||
host = ''
|
||||
@ -76,7 +87,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
self._sock = None
|
||||
self.getDeviceRoot()
|
||||
|
||||
def cmdNeedsResponse(self, cmd):
|
||||
def _cmdNeedsResponse(self, cmd):
|
||||
""" Not all commands need a response from the agent:
|
||||
* if the cmd matches the pushRE then it is the first half of push
|
||||
and therefore we want to wait until the second half before looking
|
||||
@ -93,18 +104,44 @@ class DeviceManagerSUT(DeviceManager):
|
||||
for c in noResponseCmds:
|
||||
if (c.match(cmd)):
|
||||
return False
|
||||
|
||||
|
||||
# If the command is not in our list, then it gets a response
|
||||
return True
|
||||
|
||||
def shouldCmdCloseSocket(self, cmd):
|
||||
def _stripPrompt(self, data):
|
||||
'''
|
||||
internal function
|
||||
take a data blob and strip instances of the prompt '$>\x00'
|
||||
'''
|
||||
promptre = re.compile(self.prompt_regex + '.*')
|
||||
retVal = []
|
||||
lines = data.split('\n')
|
||||
for line in lines:
|
||||
foundPrompt = False
|
||||
try:
|
||||
while (promptre.match(line)):
|
||||
foundPrompt = True
|
||||
pieces = line.split(self.prompt_sep)
|
||||
index = pieces.index('$>')
|
||||
pieces.pop(index)
|
||||
line = self.prompt_sep.join(pieces)
|
||||
except(ValueError):
|
||||
pass
|
||||
|
||||
# we don't want to append lines that are blank after stripping the
|
||||
# prompt (those are basically "prompts")
|
||||
if not foundPrompt or line:
|
||||
retVal.append(line)
|
||||
|
||||
return '\n'.join(retVal)
|
||||
|
||||
def _shouldCmdCloseSocket(self, cmd):
|
||||
""" Some commands need to close the socket after they are sent:
|
||||
* push
|
||||
* rebt
|
||||
* uninst
|
||||
* quit
|
||||
"""
|
||||
|
||||
socketClosingCmds = [re.compile('^push .*$'),
|
||||
re.compile('^quit.*'),
|
||||
re.compile('^rebt.*'),
|
||||
@ -116,85 +153,86 @@ class DeviceManagerSUT(DeviceManager):
|
||||
|
||||
return False
|
||||
|
||||
# convenience function to enable checks for agent errors
|
||||
def verifySendCMD(self, cmdline, newline = True):
|
||||
return self.sendCMD(cmdline, newline, False)
|
||||
|
||||
|
||||
#
|
||||
# create a wrapper for sendCMD that loops up to self.retrylimit iterations.
|
||||
# this allows us to move the retry logic outside of the _doCMD() to make it
|
||||
# easier for debugging in the future.
|
||||
# note that since cmdline is a list of commands, they will all be retried if
|
||||
# one fails. this is necessary in particular for pushFile(), where we don't want
|
||||
# to accidentally send extra data if a failure occurs during data transmission.
|
||||
#
|
||||
def sendCMD(self, cmdline, newline = True, ignoreAgentErrors = True):
|
||||
def sendCmds(self, cmdlist, outputfile, timeout = None, newline = True):
|
||||
'''
|
||||
a wrapper for _doCmds that loops up to self.retrylimit iterations.
|
||||
this allows us to move the retry logic outside of the _doCmds() to make it
|
||||
easier for debugging in the future.
|
||||
note that since cmdlist is a list of commands, they will all be retried if
|
||||
one fails. this is necessary in particular for pushFile(), where we don't want
|
||||
to accidentally send extra data if a failure occurs during data transmission.
|
||||
'''
|
||||
done = False
|
||||
while (not done):
|
||||
retVal = self._doCMD(cmdline, newline)
|
||||
if (retVal is None):
|
||||
while self.retries < self.retrylimit:
|
||||
try:
|
||||
self._doCmds(cmdlist, outputfile, timeout, newline)
|
||||
return
|
||||
except AgentError, err:
|
||||
# re-raise error if it's fatal (i.e. the device got the command but
|
||||
# couldn't execute it). retry otherwise
|
||||
if err.fatal:
|
||||
raise err
|
||||
if self.debug >= 2:
|
||||
print err
|
||||
self.retries += 1
|
||||
else:
|
||||
self.retries = 0
|
||||
if ignoreAgentErrors == False:
|
||||
if (self.agentErrorRE.match(retVal)):
|
||||
raise DMError("error on the agent executing '%s'" % cmdline)
|
||||
return retVal
|
||||
|
||||
if (self.retries >= self.retrylimit):
|
||||
done = True
|
||||
raise AgentError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))
|
||||
|
||||
raise DMError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))
|
||||
def runCmds(self, cmdlist, timeout = None, newline = True):
|
||||
'''
|
||||
similar to sendCmds, but just returns any output as a string instead of
|
||||
writing to a file. this is normally what you want to call to send a set
|
||||
of commands to the agent
|
||||
'''
|
||||
outputfile = StringIO.StringIO()
|
||||
self.sendCmds(cmdlist, outputfile, timeout, newline)
|
||||
outputfile.seek(0)
|
||||
return outputfile.read()
|
||||
|
||||
def _doCMD(self, cmdline, newline = True):
|
||||
def _doCmds(self, cmdlist, outputfile, timeout, newline):
|
||||
promptre = re.compile(self.prompt_regex + '$')
|
||||
data = ""
|
||||
shouldCloseSocket = False
|
||||
recvGuard = 1000
|
||||
|
||||
if (self._sock == None):
|
||||
if not self._sock:
|
||||
try:
|
||||
if (self.debug >= 1):
|
||||
if self.debug >= 1:
|
||||
print "reconnecting socket"
|
||||
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
except:
|
||||
self._sock = None
|
||||
if (self.debug >= 2):
|
||||
print "unable to create socket"
|
||||
return None
|
||||
|
||||
raise AgentError("unable to create socket")
|
||||
|
||||
try:
|
||||
self._sock.connect((self.host, int(self.port)))
|
||||
self._sock.recv(1024)
|
||||
except:
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
if (self.debug >= 2):
|
||||
print "unable to connect socket"
|
||||
return None
|
||||
|
||||
for cmd in cmdline:
|
||||
raise AgentError("unable to connect socket")
|
||||
|
||||
for cmd in cmdlist:
|
||||
if newline: cmd += '\r\n'
|
||||
|
||||
|
||||
try:
|
||||
numbytes = self._sock.send(cmd)
|
||||
if (numbytes != len(cmd)):
|
||||
print "ERROR: our cmd was " + str(len(cmd)) + " bytes and we only sent " + str(numbytes)
|
||||
return None
|
||||
raise AgentError("ERROR: our cmd was %s bytes and we only sent %s" % (len(cmd),
|
||||
numbytes))
|
||||
if (self.debug >= 4): print "send cmd: " + str(cmd)
|
||||
except:
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
return None
|
||||
|
||||
return False
|
||||
|
||||
# Check if the command should close the socket
|
||||
shouldCloseSocket = self.shouldCmdCloseSocket(cmd)
|
||||
shouldCloseSocket = self._shouldCmdCloseSocket(cmd)
|
||||
|
||||
# Handle responses from commands
|
||||
if (self.cmdNeedsResponse(cmd)):
|
||||
if (self._cmdNeedsResponse(cmd)):
|
||||
found = False
|
||||
loopguard = 0
|
||||
data = ""
|
||||
|
||||
while (found == False and (loopguard < recvGuard)):
|
||||
temp = ''
|
||||
@ -207,14 +245,14 @@ class DeviceManagerSUT(DeviceManager):
|
||||
except:
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
return None
|
||||
raise AgentError("Error receiving data from socket")
|
||||
|
||||
data += temp
|
||||
|
||||
# If something goes wrong in the agent it will send back a string that
|
||||
# starts with '##AGENT-ERROR##'
|
||||
if self.agentErrorRE.match(data):
|
||||
break
|
||||
raise AgentError("Agent Error processing command: %s" % cmd, fatal=True)
|
||||
|
||||
for line in data.splitlines():
|
||||
if promptre.match(line):
|
||||
@ -222,40 +260,54 @@ class DeviceManagerSUT(DeviceManager):
|
||||
data = self._stripPrompt(data)
|
||||
break
|
||||
|
||||
# periodically flush data to output file to make sure it doesn't get
|
||||
# too big/unwieldly
|
||||
if len(data) > 1024:
|
||||
outputfile.write(data[0:1024])
|
||||
data = data[1024:]
|
||||
|
||||
# If we violently lose the connection to the device, this loop tends to spin,
|
||||
# this guard prevents that
|
||||
if (temp == ''):
|
||||
loopguard += 1
|
||||
|
||||
if (shouldCloseSocket == True):
|
||||
# Write any remaining data to outputfile
|
||||
outputfile.write(data)
|
||||
|
||||
if shouldCloseSocket:
|
||||
try:
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
except:
|
||||
self._sock = None
|
||||
return None
|
||||
raise AgentError("Error closing socket")
|
||||
|
||||
return data
|
||||
|
||||
# internal function
|
||||
# take a data blob and strip instances of the prompt '$>\x00'
|
||||
def _stripPrompt(self, data):
|
||||
promptre = re.compile(self.prompt_regex + '.*')
|
||||
retVal = []
|
||||
lines = data.split('\n')
|
||||
for line in lines:
|
||||
try:
|
||||
while (promptre.match(line)):
|
||||
pieces = line.split(self.prompt_sep)
|
||||
index = pieces.index('$>')
|
||||
pieces.pop(index)
|
||||
line = self.prompt_sep.join(pieces)
|
||||
except(ValueError):
|
||||
pass
|
||||
retVal.append(line)
|
||||
# external function: executes shell command on device
|
||||
# returns:
|
||||
# success: <return code>
|
||||
# failure: None
|
||||
def shell(self, cmd, outputfile, env=None, cwd=None):
|
||||
cmdline = subprocess.list2cmdline(cmd)
|
||||
if env:
|
||||
cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
|
||||
|
||||
return '\n'.join(retVal)
|
||||
|
||||
try:
|
||||
if cwd:
|
||||
self.sendCmds(['execcwd %s %s' % (cwd, cmdline)], outputfile)
|
||||
else:
|
||||
self.sendCmds(['exec %s' % cmdline], outputfile)
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
# dig through the output to get the return code
|
||||
lastline = _pop_last_line(outputfile)
|
||||
if lastline:
|
||||
m = re.search('return code \[([0-9]+)\]', lastline)
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
||||
# woops, we couldn't find an end of line/return value
|
||||
return None
|
||||
|
||||
# external function
|
||||
# returns:
|
||||
@ -286,8 +338,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
f.close()
|
||||
|
||||
try:
|
||||
retVal = self.verifySendCMD(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
|
||||
except(DMError):
|
||||
retVal = self.runCmds(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
|
||||
except AgentError:
|
||||
retVal = False
|
||||
|
||||
if (self.debug >= 3): print "push returned: " + str(retVal)
|
||||
@ -323,8 +375,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return name
|
||||
else:
|
||||
try:
|
||||
retVal = self.verifySendCMD(['mkdr ' + name])
|
||||
except(DMError):
|
||||
retVal = self.runCmds(['mkdr ' + name])
|
||||
except AgentError:
|
||||
retVal = None
|
||||
return retVal
|
||||
|
||||
@ -376,8 +428,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
match = ".*" + dirname + "$"
|
||||
dirre = re.compile(match)
|
||||
try:
|
||||
data = self.verifySendCMD(['cd ' + dirname, 'cwd'])
|
||||
except(DMError):
|
||||
data = self.runCmds(['cd ' + dirname, 'cwd'])
|
||||
except AgentError:
|
||||
return False
|
||||
|
||||
found = False
|
||||
@ -412,8 +464,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
if (self.dirExists(rootdir) == False):
|
||||
return []
|
||||
try:
|
||||
data = self.verifySendCMD(['cd ' + rootdir, 'ls'])
|
||||
except(DMError):
|
||||
data = self.runCmds(['cd ' + rootdir, 'ls'])
|
||||
except AgentError:
|
||||
return []
|
||||
|
||||
files = filter(lambda x: x, data.splitlines())
|
||||
@ -429,8 +481,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
def removeFile(self, filename):
|
||||
if (self.debug>= 2): print "removing file: " + filename
|
||||
try:
|
||||
retVal = self.verifySendCMD(['rm ' + filename])
|
||||
except(DMError):
|
||||
retVal = self.runCmds(['rm ' + filename])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return retVal
|
||||
@ -442,8 +494,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def removeDir(self, remoteDir):
|
||||
try:
|
||||
retVal = self.verifySendCMD(['rmdr ' + remoteDir])
|
||||
except(DMError):
|
||||
retVal = self.runCmds(['rmdr ' + remoteDir])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return retVal
|
||||
@ -454,8 +506,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: []
|
||||
def getProcessList(self):
|
||||
try:
|
||||
data = self.verifySendCMD(['ps'])
|
||||
except DMError:
|
||||
data = self.runCmds(['ps'])
|
||||
except AgentError:
|
||||
return []
|
||||
|
||||
files = []
|
||||
@ -470,6 +522,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return files
|
||||
|
||||
# external function
|
||||
# DEPRECATED: Use shell() or launchApplication() for new code
|
||||
# returns:
|
||||
# success: pid
|
||||
# failure: None
|
||||
@ -486,8 +539,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return None
|
||||
|
||||
try:
|
||||
data = self.verifySendCMD(['exec ' + appname])
|
||||
except(DMError):
|
||||
data = self.runCmds(['exec ' + appname])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
# wait up to 30 seconds for process to start up
|
||||
@ -503,6 +556,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return process
|
||||
|
||||
# external function
|
||||
# DEPRECATED: Use shell() or launchApplication() for new code
|
||||
# returns:
|
||||
# success: output filename
|
||||
# failure: None
|
||||
@ -532,8 +586,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def killProcess(self, appname):
|
||||
try:
|
||||
data = self.verifySendCMD(['kill ' + appname])
|
||||
except(DMError):
|
||||
data = self.runCmds(['kill ' + appname])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data
|
||||
@ -544,8 +598,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def getTempDir(self):
|
||||
try:
|
||||
data = self.verifySendCMD(['tmpd'])
|
||||
except(DMError):
|
||||
data = self.runCmds(['tmpd'])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data.strip()
|
||||
@ -556,12 +610,12 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def catFile(self, remoteFile):
|
||||
try:
|
||||
data = self.verifySendCMD(['cat ' + remoteFile])
|
||||
except(DMError):
|
||||
data = self.runCmds(['cat ' + remoteFile])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# external function
|
||||
# returns:
|
||||
# success: output of pullfile, string
|
||||
@ -625,8 +679,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# or, if error,
|
||||
# <filename>,-1\n<error message>
|
||||
try:
|
||||
data = self.verifySendCMD(['pull ' + remoteFile])
|
||||
except(DMError):
|
||||
data = self.runCmds(['pull ' + remoteFile])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
# read metadata; buffer the rest
|
||||
@ -744,8 +798,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# Throws a FileError exception when null (invalid dir/filename)
|
||||
def isDir(self, remotePath):
|
||||
try:
|
||||
data = self.verifySendCMD(['isdir ' + remotePath])
|
||||
except(DMError):
|
||||
data = self.runCmds(['isdir ' + remotePath])
|
||||
except AgentError:
|
||||
# normally there should be no error here; a nonexistent file/directory will
|
||||
# return the string "<filename>: No such file or directory".
|
||||
# However, I've seen AGENT-WARNING returned before.
|
||||
@ -780,8 +834,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def getRemoteHash(self, filename):
|
||||
try:
|
||||
data = self.verifySendCMD(['hash ' + filename])
|
||||
except(DMError):
|
||||
data = self.runCmds(['hash ' + filename])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
retVal = None
|
||||
@ -809,7 +863,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def getDeviceRoot(self):
|
||||
try:
|
||||
data = self.verifySendCMD(['testroot'])
|
||||
data = self.runCmds(['testroot'])
|
||||
except:
|
||||
return None
|
||||
|
||||
@ -823,7 +877,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
|
||||
def getAppRoot(self, packageName):
|
||||
try:
|
||||
data = self.verifySendCMD(['getapproot '+packageName])
|
||||
data = self.runCmds(['getapproot '+packageName])
|
||||
except:
|
||||
return None
|
||||
|
||||
@ -851,8 +905,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return None
|
||||
|
||||
try:
|
||||
data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
|
||||
except(DMError):
|
||||
data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data
|
||||
@ -872,8 +926,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
try:
|
||||
destname = '/data/data/com.mozilla.SUTAgentAndroid/files/update.info'
|
||||
data = "%s,%s\rrebooting\r" % (ipAddr, port)
|
||||
self.verifySendCMD(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
|
||||
except(DMError):
|
||||
self.runCmds(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
ip, port = self.getCallbackIpAndPort(ipAddr, port)
|
||||
@ -882,8 +936,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
callbacksvr = callbackServer(ip, port, self.debug)
|
||||
|
||||
try:
|
||||
status = self.verifySendCMD([cmd])
|
||||
except(DMError):
|
||||
status = self.runCmds([cmd])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
if (ipAddr is not None):
|
||||
@ -918,7 +972,7 @@ class DeviceManagerSUT(DeviceManager):
|
||||
directives = [directive]
|
||||
|
||||
for d in directives:
|
||||
data = self.verifySendCMD(['info ' + d])
|
||||
data = self.runCmds(['info ' + d])
|
||||
if (data is None):
|
||||
continue
|
||||
data = collapseSpaces.sub(' ', data)
|
||||
@ -955,8 +1009,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
if destPath:
|
||||
cmd += ' ' + destPath
|
||||
try:
|
||||
data = self.verifySendCMD([cmd])
|
||||
except(DMError):
|
||||
data = self.runCmds([cmd])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
f = re.compile('Failure')
|
||||
@ -981,8 +1035,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
if installPath:
|
||||
cmd += ' ' + installPath
|
||||
try:
|
||||
data = self.verifySendCMD([cmd])
|
||||
except(DMError):
|
||||
data = self.runCmds([cmd])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
if (self.debug > 3): print "uninstallAppAndReboot: " + str(data)
|
||||
@ -1026,8 +1080,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
if (self.debug >= 3): print "INFO: updateApp using command: " + str(cmd)
|
||||
|
||||
try:
|
||||
status = self.verifySendCMD([cmd])
|
||||
except(DMError):
|
||||
status = self.runCmds([cmd])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
if ipAddr is not None:
|
||||
@ -1046,8 +1100,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
# failure: None
|
||||
def getCurrentTime(self):
|
||||
try:
|
||||
data = self.verifySendCMD(['clok'])
|
||||
except(DMError):
|
||||
data = self.runCmds(['clok'])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data.strip()
|
||||
@ -1079,8 +1133,8 @@ class DeviceManagerSUT(DeviceManager):
|
||||
return None
|
||||
|
||||
try:
|
||||
data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
|
||||
except(DMError):
|
||||
data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
|
||||
except AgentError:
|
||||
return None
|
||||
|
||||
return data
|
||||
@ -1150,9 +1204,9 @@ class DeviceManagerSUT(DeviceManager):
|
||||
|
||||
if (self.debug >= 3): print "INFO: adjusting screen resolution to %s, %s and rebooting" % (width, height)
|
||||
try:
|
||||
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
|
||||
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
|
||||
except(DMError):
|
||||
self.runCmds(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
|
||||
self.runCmds(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
|
||||
except AgentError:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
87
build/mobile/droid.py
Normal file
87
build/mobile/droid.py
Normal file
@ -0,0 +1,87 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Test Automation Framework.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla foundation
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2009
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Joel Maher <joel.maher@gmail.com> (Original Developer)
|
||||
# William Lachance <wlachance@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
from devicemanagerADB import DeviceManagerADB
|
||||
from devicemanagerSUT import DeviceManagerSUT
|
||||
|
||||
class DroidMixin(object):
|
||||
"""Mixin to extend DeviceManager with Android-specific functionality"""
|
||||
|
||||
def launchApplication(self, app, activity="App",
|
||||
intent="android.intent.action.VIEW", env=None,
|
||||
url=None, extra_args=None):
|
||||
"""
|
||||
Launches an Android application
|
||||
returns:
|
||||
success: True
|
||||
failure: False
|
||||
"""
|
||||
# only one instance of an application may be running at once
|
||||
if self.processExist(app):
|
||||
return False
|
||||
|
||||
acmd = [ "am", "start", "-a", intent, "-W", "-n", "%s/.%s" % (app, activity)]
|
||||
|
||||
if extra_args:
|
||||
acmd.extend(["--es", "args", " ".join(args)])
|
||||
|
||||
if env:
|
||||
envCnt = 0
|
||||
# env is expected to be a dict of environment variables
|
||||
for envkey, envval in env.iteritems():
|
||||
acmd.extend(["--es", "env" + str(envCnt), envkey + "=" + envval])
|
||||
envCnt += 1
|
||||
|
||||
if url:
|
||||
acmd.extend(["-d", ''.join(['"', url, '"'])])
|
||||
|
||||
# shell output not that interesting and debugging logs should already
|
||||
# show what's going on here... so just create an empty memory buffer
|
||||
# and ignore
|
||||
shellOutput = StringIO.StringIO()
|
||||
if self.shell(acmd, shellOutput) == 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class DroidADB(DeviceManagerADB, DroidMixin):
|
||||
pass
|
||||
|
||||
class DroidSUT(DeviceManagerSUT, DroidMixin):
|
||||
pass
|
@ -136,12 +136,13 @@ public class DoCommand {
|
||||
String ffxProvider = "org.mozilla.ffxcp";
|
||||
String fenProvider = "org.mozilla.fencp";
|
||||
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.05";
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.06";
|
||||
|
||||
public enum Command
|
||||
{
|
||||
RUN ("run"),
|
||||
EXEC ("exec"),
|
||||
EXECCWD ("execcwd"),
|
||||
ENVRUN ("envrun"),
|
||||
KILL ("kill"),
|
||||
PS ("ps"),
|
||||
@ -692,7 +693,25 @@ public class DoCommand {
|
||||
theArgs[lcv - 1] = Argv[lcv];
|
||||
}
|
||||
|
||||
strReturn = StartPrg2(theArgs, cmdOut);
|
||||
strReturn = StartPrg2(theArgs, cmdOut, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
|
||||
}
|
||||
break;
|
||||
|
||||
case EXECCWD:
|
||||
if (Argc >= 3)
|
||||
{
|
||||
String [] theArgs = new String [Argc - 2];
|
||||
|
||||
for (int lcv = 2; lcv < Argc; lcv++)
|
||||
{
|
||||
theArgs[lcv - 2] = Argv[lcv];
|
||||
}
|
||||
|
||||
strReturn = StartPrg2(theArgs, cmdOut, Argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1262,6 +1281,11 @@ private void CancelNotification()
|
||||
{
|
||||
String sRet = null;
|
||||
|
||||
File tmpFile = new java.io.File("/data/local/tests");
|
||||
if (tmpFile.exists() && tmpFile.isDirectory())
|
||||
{
|
||||
return("/data/local");
|
||||
}
|
||||
if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED))
|
||||
{
|
||||
sRet = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
@ -3463,7 +3487,7 @@ private void CancelNotification()
|
||||
return (sRet);
|
||||
}
|
||||
|
||||
public String StartPrg2(String [] progArray, OutputStream out)
|
||||
public String StartPrg2(String [] progArray, OutputStream out, String cwd)
|
||||
{
|
||||
String sRet = "";
|
||||
|
||||
@ -3553,7 +3577,15 @@ private void CancelNotification()
|
||||
|
||||
if (theArgs[0].contains("/") || theArgs[0].contains("\\") || !theArgs[0].contains("."))
|
||||
{
|
||||
pProc = Runtime.getRuntime().exec(theArgs, envArray);
|
||||
if (cwd != null)
|
||||
{
|
||||
File f = new File(cwd);
|
||||
pProc = Runtime.getRuntime().exec(theArgs, envArray, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
pProc = Runtime.getRuntime().exec(theArgs, envArray);
|
||||
}
|
||||
|
||||
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
|
||||
outThrd.start();
|
||||
|
@ -52,7 +52,7 @@ interface nsIContentSecurityPolicy;
|
||||
[ptr] native JSContext(JSContext);
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
|
||||
[scriptable, uuid(B406A2DB-E547-4C95-B8E2-AD09ECB54CE0)]
|
||||
[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
@ -206,6 +206,12 @@ interface nsIPrincipal : nsISerializable
|
||||
*/
|
||||
boolean subsumes(in nsIPrincipal other);
|
||||
|
||||
/**
|
||||
* Same as the previous method, subsumes(), but for codebase principals
|
||||
* ignores changes to document.domain.
|
||||
*/
|
||||
boolean subsumesIgnoringDomain(in nsIPrincipal other);
|
||||
|
||||
/**
|
||||
* Checks whether this principal is allowed to load the network resource
|
||||
* located at the given URI under the same-origin policy. This means that
|
||||
|
@ -336,6 +336,12 @@ nsNullPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
return Subsumes(aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
||||
{
|
||||
|
@ -377,6 +377,12 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
|
||||
return Equals(aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
return EqualsIgnoringDomain(aOther, aResult);
|
||||
}
|
||||
|
||||
static bool
|
||||
URIIsLocalFile(nsIURI *aURI)
|
||||
{
|
||||
|
@ -125,6 +125,13 @@ nsSystemPrincipal::Subsumes(nsIPrincipal *other, bool *result)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
|
||||
{
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
{
|
||||
|
@ -697,6 +697,8 @@ JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
|
||||
|
||||
MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
|
||||
|
||||
MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@
|
||||
|
||||
# We only want to do the pymake sanity on Windows, other os's can cope
|
||||
ifeq ($(HOST_OS_ARCH),WINNT)
|
||||
# Ensure invariants between GNU Make and pymake
|
||||
|
@ -792,8 +792,10 @@ EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-
|
||||
EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(MKSHLIB)
|
||||
|
||||
ifdef STDCXX_COMPAT
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
|
||||
endif
|
||||
endif
|
||||
|
||||
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
|
||||
# this file
|
||||
|
41
configure.in
41
configure.in
@ -979,8 +979,6 @@ EOF
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOZ_WINSDK_TARGETVER,0x$MOZ_WINSDK_TARGETVER)
|
||||
# Definitions matching sdkddkver.h
|
||||
AC_DEFINE_UNQUOTED(MOZ_NTDDI_WS03, 0x05020000)
|
||||
AC_DEFINE_UNQUOTED(MOZ_NTDDI_LONGHORN, 0x06000000)
|
||||
AC_DEFINE_UNQUOTED(MOZ_NTDDI_WIN7, 0x06010000)
|
||||
;;
|
||||
esac
|
||||
@ -1051,6 +1049,16 @@ if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([python was not found in \$PATH])
|
||||
fi
|
||||
|
||||
MOZ_ARG_WITH_BOOL(system-ply,
|
||||
[ --with-system-ply Use system installed python ply library],
|
||||
[if $PYTHON -c 'import ply' 2>&5; then
|
||||
MOZ_SYSTEM_PLY=1
|
||||
else
|
||||
AC_MSG_ERROR([python ply library is not found but --with-system-ply was requested])
|
||||
fi])
|
||||
|
||||
AC_SUBST(MOZ_SYSTEM_PLY)
|
||||
|
||||
if test -z "$COMPILE_ENVIRONMENT"; then
|
||||
NSINSTALL_BIN='$(PYTHON) $(topsrcdir)/config/nsinstall.py'
|
||||
fi
|
||||
@ -3720,20 +3728,23 @@ AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat6
|
||||
AC_CHECK_FUNCS(flockfile getpagesize)
|
||||
AC_CHECK_FUNCS(localtime_r strtok_r)
|
||||
|
||||
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -lrt"
|
||||
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC) and -lrt,
|
||||
ac_cv_have_clock_monotonic,
|
||||
[AC_TRY_LINK([#include <time.h>],
|
||||
[ struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts); ],
|
||||
ac_cv_have_clock_monotonic=yes,
|
||||
ac_cv_have_clock_monotonic=no)])
|
||||
LDFLAGS=$_SAVE_LDFLAGS
|
||||
if test "$ac_cv_have_clock_monotonic" = "yes"; then
|
||||
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
|
||||
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
|
||||
ac_cv_clock_monotonic,
|
||||
[for libs in "" -lrt; do
|
||||
_SAVE_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $libs"
|
||||
AC_TRY_LINK([#include <time.h>],
|
||||
[ struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts); ],
|
||||
ac_cv_clock_monotonic=$libs
|
||||
break,
|
||||
ac_cv_clock_monotonic=no)
|
||||
LDFLAGS="$_SAVE_LDFLAGS"
|
||||
done])
|
||||
if test "$ac_cv_clock_monotonic" != "no"; then
|
||||
HAVE_CLOCK_MONOTONIC=1
|
||||
REALTIME_LIBS=-lrt
|
||||
REALTIME_LIBS=$ac_cv_clock_monotonic
|
||||
AC_DEFINE(HAVE_CLOCK_MONOTONIC)
|
||||
AC_SUBST(HAVE_CLOCK_MONOTONIC)
|
||||
AC_SUBST(REALTIME_LIBS)
|
||||
|
@ -131,7 +131,6 @@ class nsIInterfaceRequestor;
|
||||
template<class E> class nsCOMArray;
|
||||
template<class K, class V> class nsRefPtrHashtable;
|
||||
struct JSRuntime;
|
||||
class nsIUGenCategory;
|
||||
class nsIWidget;
|
||||
class nsIDragSession;
|
||||
class nsIPresShell;
|
||||
@ -625,11 +624,6 @@ public:
|
||||
return sWordBreaker;
|
||||
}
|
||||
|
||||
static nsIUGenCategory* GetGenCat()
|
||||
{
|
||||
return sGenCat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regster aObserver as a shutdown observer. A strong reference is held
|
||||
* to aObserver until UnregisterShutdownObserver is called.
|
||||
@ -2017,7 +2011,6 @@ private:
|
||||
|
||||
static nsILineBreaker* sLineBreaker;
|
||||
static nsIWordBreaker* sWordBreaker;
|
||||
static nsIUGenCategory* sGenCat;
|
||||
|
||||
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||
|
@ -691,6 +691,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
|
||||
getter_AddRefs(transferable));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupportsString> data;
|
||||
PRUint32 dataSize;
|
||||
|
@ -122,6 +122,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsLWBrkCIID.h"
|
||||
#include "nsILineBreaker.h"
|
||||
#include "nsIWordBreaker.h"
|
||||
#include "nsUnicodeProperties.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIDOMDocumentXBL.h"
|
||||
@ -154,7 +155,6 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsReferencedElement.h"
|
||||
#include "nsIUGenCategory.h"
|
||||
#include "nsIDragService.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
@ -260,7 +260,6 @@ nsIContentPolicy *nsContentUtils::sContentPolicyService;
|
||||
bool nsContentUtils::sTriedToGetContentPolicy = false;
|
||||
nsILineBreaker *nsContentUtils::sLineBreaker;
|
||||
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
||||
nsIUGenCategory *nsContentUtils::sGenCat;
|
||||
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||
PRUint32 nsContentUtils::sJSGCThingRootCount;
|
||||
@ -389,9 +388,6 @@ nsContentUtils::Init()
|
||||
rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = CallGetService(NS_UNICHARCATEGORY_CONTRACTID, &sGenCat);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!InitializeEventTable())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -977,7 +973,7 @@ nsContentUtils::IsPunctuationMarkAt(const nsTextFragment* aFrag, PRUint32 aOffse
|
||||
// static
|
||||
bool nsContentUtils::IsAlphanumeric(PRUint32 aChar)
|
||||
{
|
||||
nsIUGenCategory::nsUGenCategory cat = sGenCat->Get(aChar);
|
||||
nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
|
||||
|
||||
return (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kNumber);
|
||||
}
|
||||
@ -1138,7 +1134,6 @@ nsContentUtils::Shutdown()
|
||||
NS_IF_RELEASE(sIOService);
|
||||
NS_IF_RELEASE(sLineBreaker);
|
||||
NS_IF_RELEASE(sWordBreaker);
|
||||
NS_IF_RELEASE(sGenCat);
|
||||
#ifdef MOZ_XTF
|
||||
NS_IF_RELEASE(sXTFService);
|
||||
#endif
|
||||
|
@ -480,10 +480,14 @@ nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMAttribute::CloneNode(bool aDeep, nsIDOMNode** aResult)
|
||||
nsDOMAttribute::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aResult)
|
||||
{
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eCloneNode);
|
||||
|
||||
if (!aOptionalArgc) {
|
||||
aDeep = true;
|
||||
}
|
||||
|
||||
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
|
||||
}
|
||||
|
||||
|
@ -5830,8 +5830,12 @@ nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::CloneNode(bool aDeep, nsIDOMNode** aReturn)
|
||||
nsDocument::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
|
||||
{
|
||||
if (!aOptionalArgc) {
|
||||
aDeep = true;
|
||||
}
|
||||
|
||||
return nsNodeUtils::CloneNodeImpl(this, aDeep, !mCreatingStaticClone, aReturn);
|
||||
}
|
||||
|
||||
@ -8062,7 +8066,7 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
|
||||
nsCOMPtr<nsISupports> originalContainer = GetContainer();
|
||||
SetContainer(aCloneContainer);
|
||||
nsCOMPtr<nsIDOMNode> clonedNode;
|
||||
nsresult rv = domDoc->CloneNode(true, getter_AddRefs(clonedNode));
|
||||
nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
|
||||
SetContainer(originalContainer);
|
||||
|
||||
nsCOMPtr<nsIDocument> clonedDoc;
|
||||
|
@ -143,8 +143,12 @@ public:
|
||||
nsresult IsSupported(const nsAString& aFeature,
|
||||
const nsAString& aVersion,
|
||||
bool* aReturn);
|
||||
nsresult CloneNode(bool aDeep, nsIDOMNode** aReturn)
|
||||
nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
|
||||
{
|
||||
if (!aOptionalArgc) {
|
||||
aDeep = true;
|
||||
}
|
||||
|
||||
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aReturn);
|
||||
}
|
||||
|
||||
|
@ -437,8 +437,12 @@ public:
|
||||
// nsIDOMElement method implementation
|
||||
NS_DECL_NSIDOMELEMENT
|
||||
|
||||
nsresult CloneNode(bool aDeep, nsIDOMNode **aResult)
|
||||
nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode **aResult)
|
||||
{
|
||||
if (!aOptionalArgc) {
|
||||
aDeep = true;
|
||||
}
|
||||
|
||||
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
|
||||
}
|
||||
|
||||
|
@ -1596,7 +1596,7 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
|
||||
cutValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMNode> clone;
|
||||
rv = charData->CloneNode(false, getter_AddRefs(clone));
|
||||
rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
clone->SetNodeValue(cutValue);
|
||||
nodeToResult = clone;
|
||||
@ -1656,7 +1656,7 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
|
||||
{
|
||||
if (retval) {
|
||||
nsCOMPtr<nsIDOMNode> clone;
|
||||
rv = node->CloneNode(false, getter_AddRefs(clone));
|
||||
rv = node->CloneNode(false, 1, getter_AddRefs(clone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nodeToResult = clone;
|
||||
}
|
||||
@ -1827,7 +1827,7 @@ nsRange::CloneParentsBetween(nsIDOMNode *aAncestor,
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> clone, tmpNode;
|
||||
|
||||
res = parent->CloneNode(false, getter_AddRefs(clone));
|
||||
res = parent->CloneNode(false, 1, getter_AddRefs(clone));
|
||||
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!clone) return NS_ERROR_FAILURE;
|
||||
@ -1928,7 +1928,7 @@ nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
|
||||
// Clone the current subtree!
|
||||
|
||||
nsCOMPtr<nsIDOMNode> clone;
|
||||
res = node->CloneNode(deepClone, getter_AddRefs(clone));
|
||||
res = node->CloneNode(deepClone, 1, getter_AddRefs(clone));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// If it's CharacterData, make sure we only clone what
|
||||
|
@ -555,6 +555,7 @@ _TEST_FILES2 = \
|
||||
file_bug717511_2.html \
|
||||
file_bug717511_2.html^headers^ \
|
||||
test_bug726364.html \
|
||||
test_bug698381.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
@ -30,13 +30,13 @@ var constants = [
|
||||
"INVALID_ACCESS_ERR",
|
||||
"VALIDATION_ERR",
|
||||
"TYPE_MISMATCH_ERR",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"SECURITY_ERR",
|
||||
"NETWORK_ERR",
|
||||
"ABORT_ERR",
|
||||
"URL_MISMATCH_ERR",
|
||||
"QUOTA_EXCEEDED_ERR",
|
||||
"TIMEOUT_ERR",
|
||||
"INVALID_NODE_TYPE_ERR",
|
||||
"DATA_CLONE_ERR"
|
||||
];
|
||||
for (var i = 0; i < constants.length; ++i) {
|
||||
|
56
content/base/test/test_bug698381.html
Normal file
56
content/base/test/test_bug698381.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=698381
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 698381</title>
|
||||
<script type="text/javascript"
|
||||
src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"
|
||||
type="text/javascript"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="runTests();">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=698381">
|
||||
Mozilla Bug 698381</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<div id="noChildren" style="display: none"></div>
|
||||
<div id="hasChildren" style="display: none">
|
||||
<div id="childOne" style="display: none"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript">
|
||||
/*
|
||||
Checks to see if default parameter handling is correct when 0
|
||||
parameters are passed.
|
||||
|
||||
If none are passed, then Node.cloneNode should default aDeep
|
||||
to true.
|
||||
*/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var hasChildren = document.getElementById("hasChildren"),
|
||||
noChildren = document.getElementById("noChildren"),
|
||||
clonedNode;
|
||||
|
||||
function runTests() {
|
||||
|
||||
// Test Node.cloneNode when no arguments are given
|
||||
clonedNode = hasChildren.cloneNode();
|
||||
is(clonedNode.hasChildNodes(), true, "Node.cloneNode with true " +
|
||||
"default on a node with children clones the child nodes.");
|
||||
|
||||
clonedNode = noChildren.cloneNode();
|
||||
is(clonedNode.hasChildNodes(), false, "Node.cloneNode with true " +
|
||||
"default on a node without children doesn't clone child nodes." );
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -71,6 +71,7 @@ CPPSRCS += \
|
||||
WebGLContextReporter.cpp \
|
||||
WebGLContextValidate.cpp \
|
||||
WebGLExtensionStandardDerivatives.cpp \
|
||||
WebGLExtensionTextureFilterAnisotropic.cpp \
|
||||
WebGLExtensionLoseContext.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
@ -820,7 +820,6 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
|
||||
|
||||
switch (ei) {
|
||||
case WebGL_OES_texture_float:
|
||||
MakeContextCurrent();
|
||||
isSupported = gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float
|
||||
: GLContext::ARB_texture_float);
|
||||
break;
|
||||
@ -828,6 +827,9 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
|
||||
// We always support this extension.
|
||||
isSupported = true;
|
||||
break;
|
||||
case WebGL_EXT_texture_filter_anisotropic:
|
||||
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
|
||||
break;
|
||||
case WebGL_MOZ_WEBGL_lose_context:
|
||||
// We always support this extension.
|
||||
isSupported = true;
|
||||
@ -860,6 +862,10 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
|
||||
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
|
||||
ei = WebGL_OES_standard_derivatives;
|
||||
}
|
||||
else if (aName.EqualsLiteral("MOZ_EXT_texture_filter_anisotropic")) {
|
||||
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
|
||||
ei = WebGL_EXT_texture_filter_anisotropic;
|
||||
}
|
||||
else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
|
||||
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
|
||||
ei = WebGL_MOZ_WEBGL_lose_context;
|
||||
@ -871,6 +877,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
|
||||
case WebGL_OES_standard_derivatives:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case WebGL_EXT_texture_filter_anisotropic:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
|
||||
break;
|
||||
case WebGL_MOZ_WEBGL_lose_context:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
@ -1295,6 +1304,11 @@ NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
|
||||
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
|
||||
|
||||
NS_IMPL_ADDREF(WebGLExtensionTextureFilterAnisotropic)
|
||||
NS_IMPL_RELEASE(WebGLExtensionTextureFilterAnisotropic)
|
||||
|
||||
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
|
||||
|
||||
NS_IMPL_ADDREF(WebGLExtensionLoseContext)
|
||||
NS_IMPL_RELEASE(WebGLExtensionLoseContext)
|
||||
|
||||
@ -1409,6 +1423,8 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval)
|
||||
extList.InsertElementAt(extList.Length(), "OES_texture_float");
|
||||
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
|
||||
extList.InsertElementAt(extList.Length(), "OES_standard_derivatives");
|
||||
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
|
||||
extList.InsertElementAt(extList.Length(), "MOZ_EXT_texture_filter_anisotropic");
|
||||
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
|
||||
extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");
|
||||
|
||||
|
@ -745,6 +745,7 @@ protected:
|
||||
enum WebGLExtensionID {
|
||||
WebGL_OES_texture_float,
|
||||
WebGL_OES_standard_derivatives,
|
||||
WebGL_EXT_texture_filter_anisotropic,
|
||||
WebGL_MOZ_WEBGL_lose_context,
|
||||
WebGLExtensionID_Max
|
||||
};
|
||||
|
@ -2210,6 +2210,15 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
|
||||
break;
|
||||
|
||||
// float
|
||||
case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
GLfloat f = 0.f;
|
||||
gl->fGetFloatv(pname, &f);
|
||||
wrval->SetAsFloat(f);
|
||||
} else {
|
||||
return ErrorInvalidEnum("getParameter: parameter", pname);
|
||||
}
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_CLEAR_VALUE:
|
||||
case LOCAL_GL_LINE_WIDTH:
|
||||
case LOCAL_GL_POLYGON_OFFSET_FACTOR:
|
||||
@ -2679,6 +2688,7 @@ nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
|
||||
return ErrorInvalidOperation("texParameter: no texture is bound to this target");
|
||||
|
||||
bool pnameAndParamAreIncompatible = false;
|
||||
bool paramValueInvalid = false;
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_TEXTURE_MIN_FILTER:
|
||||
@ -2727,18 +2737,33 @@ nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
|
||||
pnameAndParamAreIncompatible = true;
|
||||
}
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
if (floatParamPtr && floatParam < 1.f)
|
||||
paramValueInvalid = true;
|
||||
else if (intParamPtr && intParam < 1)
|
||||
paramValueInvalid = true;
|
||||
}
|
||||
else
|
||||
pnameAndParamAreIncompatible = true;
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
}
|
||||
|
||||
if (pnameAndParamAreIncompatible) {
|
||||
// note that currently all params are enums, and the tex-input-validation test wants INVALID_ENUM errors
|
||||
// even for texParameterf. why not.
|
||||
if (intParamPtr)
|
||||
return ErrorInvalidEnum("texParameteri: pname %x and param %x (decimal %d) are mutually incompatible",
|
||||
pname, intParam, intParam);
|
||||
else
|
||||
return ErrorInvalidEnum("texParameterf: pname %x and floating-point param %e are mutually incompatible",
|
||||
return ErrorInvalidEnum("texParameterf: pname %x and param %g are mutually incompatible",
|
||||
pname, floatParam);
|
||||
} else if (paramValueInvalid) {
|
||||
if (intParamPtr)
|
||||
return ErrorInvalidValue("texParameteri: pname %x and param %x (decimal %d) is invalid",
|
||||
pname, intParam, intParam);
|
||||
else
|
||||
return ErrorInvalidValue("texParameterf: pname %x and param %g is invalid",
|
||||
pname, floatParam);
|
||||
}
|
||||
|
||||
@ -2799,6 +2824,15 @@ WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **re
|
||||
wrval->SetAsInt32(i);
|
||||
}
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
GLfloat f = 0.f;
|
||||
gl->fGetTexParameterfv(target, pname, &f);
|
||||
wrval->SetAsFloat(f);
|
||||
}
|
||||
else
|
||||
return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
|
||||
|
@ -55,4 +55,5 @@ DOMCI_DATA(WebGLShaderPrecisionFormat, void)
|
||||
DOMCI_DATA(WebGLActiveInfo, void)
|
||||
DOMCI_DATA(WebGLExtension, void)
|
||||
DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
|
||||
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
|
||||
DOMCI_DATA(WebGLExtensionLoseContext, void)
|
||||
|
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Florian Boesch <pyalot@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLExtensions.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionTextureFilterAnisotropic)
|
||||
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
|
||||
|
||||
WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context) :
|
||||
WebGLExtension(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic()
|
||||
{
|
||||
|
||||
}
|
@ -41,9 +41,6 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLExtensionLoseContext;
|
||||
class WebGLExtensionStandardDerivatives;
|
||||
|
||||
class WebGLExtensionLoseContext :
|
||||
public nsIWebGLExtensionLoseContext,
|
||||
public WebGLExtension
|
||||
@ -68,6 +65,18 @@ public:
|
||||
NS_DECL_NSIWEBGLEXTENSION
|
||||
};
|
||||
|
||||
class WebGLExtensionTextureFilterAnisotropic :
|
||||
public nsIWebGLExtensionTextureFilterAnisotropic,
|
||||
public WebGLExtension
|
||||
{
|
||||
public:
|
||||
WebGLExtensionTextureFilterAnisotropic(WebGLContext* context);
|
||||
virtual ~WebGLExtensionTextureFilterAnisotropic();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLEXTENSION
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WEBGLEXTENSIONS_H_
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=685518
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SECURITY_ERR = 0x805303e8;
|
||||
const SECURITY_ERR = 0x80530012;
|
||||
const BAD_URI_ERR = 0x805303f4;
|
||||
const OK = 0;
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=682299
|
||||
/** Test for Bug 682299 **/
|
||||
|
||||
const MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
|
||||
const SECURITY_ERR = 0x805303e8;
|
||||
const SECURITY_ERR = 0x80530012;
|
||||
|
||||
function createCanvas(width, height) {
|
||||
var c = document.createElement("canvas");
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SECURITY_ERR = 0x805303e8;
|
||||
const SECURITY_ERR = 0x80530012;
|
||||
const OK = 0;
|
||||
|
||||
var gl;
|
||||
|
@ -19702,7 +19702,7 @@ function test_bug397524() {
|
||||
try {
|
||||
$("canvas2").toDataURL("image/png");
|
||||
gotData = true;
|
||||
} catch (ex if (ex.code == 1000 && ex.name == "NS_ERROR_DOM_SECURITY_ERR")) {
|
||||
} catch (ex if (ex.code == 18 && ex.name == "SecurityError")) {
|
||||
}
|
||||
is(gotData, false, "Shouldn't be able to read images cross-site!");
|
||||
|
||||
@ -19711,7 +19711,7 @@ function test_bug397524() {
|
||||
try {
|
||||
$("canvas3").toDataURL("image/png");
|
||||
gotData = true;
|
||||
} catch (ex if (ex.code == 1000 && ex.name == "NS_ERROR_DOM_SECURITY_ERR")) {
|
||||
} catch (ex if (ex.code == 18 && ex.name == "SecurityError")) {
|
||||
}
|
||||
is(gotData, false, "Shouldn't be able to read images redirected cross-site!");
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
oes-standard-derivatives.html
|
||||
ext-texture-filter-anisotropic.html
|
||||
oes-texture-float.html
|
||||
oes-vertex-array-object.html
|
||||
webgl-debug-renderer-info.html
|
||||
|
@ -0,0 +1,157 @@
|
||||
<!--
|
||||
Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the LICENSE file.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
|
||||
<script src="../../resources/js-test-pre.js"></script>
|
||||
<script src="../resources/webgl-test.js"></script>
|
||||
<script src="../resources/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
|
||||
<script>
|
||||
description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = create3DContext(canvas);
|
||||
var ext = null;
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context does not exist");
|
||||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
// Run tests with extension disabled
|
||||
runHintTestDisabled();
|
||||
|
||||
// Query the extension and store globally so shouldBe can access it
|
||||
ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
|
||||
if (!ext) {
|
||||
testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
|
||||
|
||||
runSupportedTest(false);
|
||||
} else {
|
||||
testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
|
||||
|
||||
runSupportedTest(true);
|
||||
runHintTestEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
function runSupportedTest(extensionEnabled) {
|
||||
var supported = gl.getSupportedExtensions();
|
||||
if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
|
||||
if (extensionEnabled) {
|
||||
testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
|
||||
} else {
|
||||
testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
|
||||
}
|
||||
} else {
|
||||
if (extensionEnabled) {
|
||||
testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
|
||||
} else {
|
||||
testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runHintTestDisabled() {
|
||||
debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
|
||||
var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
|
||||
gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
|
||||
|
||||
debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
var TEXTURE_MAX_ANISOTROPY = 0x84FE;
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
|
||||
gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
|
||||
|
||||
gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
|
||||
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
|
||||
function runHintTestEnabled() {
|
||||
debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
|
||||
|
||||
shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
|
||||
|
||||
var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
|
||||
|
||||
if(max_anisotropy >= 2){
|
||||
testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
|
||||
}
|
||||
else{
|
||||
testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
|
||||
}
|
||||
|
||||
// TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
|
||||
|
||||
debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
|
||||
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
|
||||
var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
|
||||
|
||||
if(queried_value == 1){
|
||||
testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
|
||||
}
|
||||
else{
|
||||
testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
|
||||
}
|
||||
|
||||
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
|
||||
glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
|
||||
glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
|
||||
|
||||
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
|
||||
|
||||
var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
|
||||
if(queried_value == max_anisotropy){
|
||||
testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
|
||||
}
|
||||
else{
|
||||
testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
|
||||
}
|
||||
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
|
||||
debug("");
|
||||
successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../resources/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
174
content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
Normal file
174
content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
Normal file
@ -0,0 +1,174 @@
|
||||
diff --git a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
|
||||
--- a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
|
||||
+++ b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
|
||||
@@ -1,7 +1,8 @@
|
||||
oes-standard-derivatives.html
|
||||
+ext-texture-filter-anisotropic.html
|
||||
oes-texture-float.html
|
||||
oes-vertex-array-object.html
|
||||
webgl-debug-renderer-info.html
|
||||
webgl-debug-shaders.html
|
||||
--min-version 1.0.2 webgl-experimental-compressed-textures.html
|
||||
|
||||
diff --git a/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
|
||||
@@ -0,0 +1,157 @@
|
||||
+<!--
|
||||
+Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. All rights reserved.
|
||||
+Use of this source code is governed by a BSD-style license that can be
|
||||
+found in the LICENSE file.
|
||||
+ -->
|
||||
+<!DOCTYPE html>
|
||||
+<html>
|
||||
+<head>
|
||||
+<meta charset="utf-8">
|
||||
+<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
|
||||
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
+<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
|
||||
+<script src="../../resources/js-test-pre.js"></script>
|
||||
+<script src="../resources/webgl-test.js"></script>
|
||||
+<script src="../resources/webgl-test-utils.js"></script>
|
||||
+</head>
|
||||
+<body>
|
||||
+<div id="description"></div>
|
||||
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
+<div id="console"></div>
|
||||
+
|
||||
+<script>
|
||||
+description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
|
||||
+
|
||||
+debug("");
|
||||
+
|
||||
+var wtu = WebGLTestUtils;
|
||||
+var canvas = document.getElementById("canvas");
|
||||
+var gl = create3DContext(canvas);
|
||||
+var ext = null;
|
||||
+
|
||||
+if (!gl) {
|
||||
+ testFailed("WebGL context does not exist");
|
||||
+} else {
|
||||
+ testPassed("WebGL context exists");
|
||||
+
|
||||
+ // Run tests with extension disabled
|
||||
+ runHintTestDisabled();
|
||||
+
|
||||
+ // Query the extension and store globally so shouldBe can access it
|
||||
+ ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
|
||||
+ if (!ext) {
|
||||
+ testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
|
||||
+
|
||||
+ runSupportedTest(false);
|
||||
+ } else {
|
||||
+ testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
|
||||
+
|
||||
+ runSupportedTest(true);
|
||||
+ runHintTestEnabled();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function runSupportedTest(extensionEnabled) {
|
||||
+ var supported = gl.getSupportedExtensions();
|
||||
+ if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
|
||||
+ if (extensionEnabled) {
|
||||
+ testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
|
||||
+ } else {
|
||||
+ testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (extensionEnabled) {
|
||||
+ testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
|
||||
+ } else {
|
||||
+ testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function runHintTestDisabled() {
|
||||
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
+
|
||||
+ var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
|
||||
+ gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
|
||||
+
|
||||
+ debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
+ var TEXTURE_MAX_ANISOTROPY = 0x84FE;
|
||||
+ var texture = gl.createTexture();
|
||||
+ gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
+
|
||||
+ gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
|
||||
+
|
||||
+ gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
|
||||
+
|
||||
+ gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
|
||||
+
|
||||
+ gl.deleteTexture(texture);
|
||||
+}
|
||||
+
|
||||
+function runHintTestEnabled() {
|
||||
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
|
||||
+
|
||||
+ shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
|
||||
+
|
||||
+ var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
|
||||
+ glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
|
||||
+
|
||||
+ if(max_anisotropy >= 2){
|
||||
+ testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
|
||||
+ }
|
||||
+ else{
|
||||
+ testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
|
||||
+ }
|
||||
+
|
||||
+ // TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
|
||||
+
|
||||
+ debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
|
||||
+ shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
|
||||
+
|
||||
+ var texture = gl.createTexture();
|
||||
+ gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
+
|
||||
+ var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
|
||||
+ glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
|
||||
+
|
||||
+ if(queried_value == 1){
|
||||
+ testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
|
||||
+ }
|
||||
+ else{
|
||||
+ testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
|
||||
+ }
|
||||
+
|
||||
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
|
||||
+
|
||||
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
|
||||
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
|
||||
+
|
||||
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
+ glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
|
||||
+
|
||||
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
+ glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
|
||||
+
|
||||
+ var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
|
||||
+ if(queried_value == max_anisotropy){
|
||||
+ testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
|
||||
+ }
|
||||
+ else{
|
||||
+ testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
|
||||
+ }
|
||||
+
|
||||
+ gl.deleteTexture(texture);
|
||||
+}
|
||||
+
|
||||
+debug("");
|
||||
+successfullyParsed = true;
|
||||
+</script>
|
||||
+<script src="../../resources/js-test-post.js"></script>
|
||||
+
|
||||
+</body>
|
||||
+</html>
|
@ -78,7 +78,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=415498
|
||||
browser.loadURI(chromeDir + "bug415498-doc1.html");
|
||||
yield;
|
||||
|
||||
ok(verifyErrorReceived("NS_ERROR_DOM_HIERARCHY_REQUEST_ERR"),
|
||||
ok(verifyErrorReceived("HierarchyRequestError"),
|
||||
"Error message not reported in event listener callback!");
|
||||
gMessages = [];
|
||||
|
||||
@ -87,7 +87,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=415498
|
||||
browser.loadURI(chromeDir + "bug415498-doc2.html");
|
||||
yield;
|
||||
|
||||
ok(verifyErrorReceived("NS_ERROR_DOM_HIERARCHY_REQUEST_ERR"),
|
||||
ok(verifyErrorReceived("HierarchyRequestError"),
|
||||
"Error message not reported in window.onload!");
|
||||
}
|
||||
|
||||
|
@ -38,17 +38,17 @@ function afterDragTests()
|
||||
checkTypes(gDataTransfer, [], 0, "after dragstart event");
|
||||
|
||||
expectError(function() gDataTransfer.setData("text/plain", "Some Text"),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "setData when read only");
|
||||
"NoModificationAllowedError", "setData when read only");
|
||||
expectError(function() gDataTransfer.clearData("text/plain"),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "clearData when read only");
|
||||
"NoModificationAllowedError", "clearData when read only");
|
||||
expectError(function() gDataTransfer.mozSetDataAt("text/plain", "Some Text", 0),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "setDataAt when read only");
|
||||
"NoModificationAllowedError", "setDataAt when read only");
|
||||
expectError(function() gDataTransfer.mozClearDataAt("text/plain", 0),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "clearDataAt when read only");
|
||||
"NoModificationAllowedError", "clearDataAt when read only");
|
||||
expectError(function() gDataTransfer.setDragImage(draggable, 10, 10),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "setDragImage when read only");
|
||||
"NoModificationAllowedError", "setDragImage when read only");
|
||||
expectError(function() gDataTransfer.addElement(draggable),
|
||||
"NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR", "addElement when read only");
|
||||
"NoModificationAllowedError", "addElement when read only");
|
||||
|
||||
var evt = document.createEvent("dragevent");
|
||||
ok(evt instanceof DragEvent, "synthetic dragevent class")
|
||||
@ -154,7 +154,7 @@ function test_DataTransfer(dt)
|
||||
|
||||
// calling setDataAt requires an index that is 0 <= index <= dt.itemCount
|
||||
expectError(function() dt.mozSetDataAt("text/plain", "Some Text", 1),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "setDataAt index too high");
|
||||
"IndexSizeError", "setDataAt index too high");
|
||||
|
||||
is(dt.mozUserCancelled, false, "userCancelled");
|
||||
|
||||
@ -172,9 +172,9 @@ function test_DataTransfer(dt)
|
||||
|
||||
// similar with clearDataAt and getDataAt
|
||||
expectError(function() dt.mozGetDataAt("text/plain", 1),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "getDataAt index too high");
|
||||
"IndexSizeError", "getDataAt index too high");
|
||||
expectError(function() dt.mozClearDataAt("text/plain", 1),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "clearDataAt index too high");
|
||||
"IndexSizeError", "clearDataAt index too high");
|
||||
|
||||
dt.setData("text/plain", "Sample Text");
|
||||
is(dt.mozItemCount, 1, "added plaintext itemCount");
|
||||
@ -285,7 +285,7 @@ function test_DataTransfer(dt)
|
||||
dt.mozSetDataAt("text/plain", "First Item", 0);
|
||||
dt.mozSetDataAt("text/plain", "Second Item", 1);
|
||||
expectError(function() dt.mozSetDataAt("text/plain", "Some Text", 3),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "setDataAt index too high with two items");
|
||||
"IndexSizeError", "setDataAt index too high with two items");
|
||||
is(dt.mozItemCount, 2, "setDataAt item itemCount");
|
||||
checkOneDataItem(dt, ["text/plain"], ["First Item"], 0, "setDataAt item at index 0");
|
||||
checkOneDataItem(dt, ["text/plain"], ["Second Item"], 1, "setDataAt item at index 1");
|
||||
@ -329,7 +329,7 @@ function test_DataTransfer(dt)
|
||||
["First Item", "Changed with setData"], 0, "clearDataAt last type at index 0");
|
||||
checkOneDataItem(dt, ["application/-moz-node"], [draggable], 1, "clearDataAt last type item at index 2");
|
||||
expectError(function() dt.mozGetDataAt("text/plain", 2),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "getDataAt after item removed index too high");
|
||||
"IndexSizeError", "getDataAt after item removed index too high");
|
||||
|
||||
dt.mozSetDataAt("text/unknown", "Unknown type", 2);
|
||||
dt.mozSetDataAt("text/unknown", "Unknown type", 1);
|
||||
@ -356,7 +356,7 @@ function test_DataTransfer(dt)
|
||||
["Unknown type"], 1, "clearData type that does not exist item at index 1");
|
||||
|
||||
expectError(function() dt.mozClearDataAt("text/plain", 3),
|
||||
"NS_ERROR_DOM_INDEX_SIZE_ERR", "clearData index too high with two items");
|
||||
"IndexSizeError", "clearData index too high with two items");
|
||||
|
||||
// ensure that clearData() removes all data associated with the first item
|
||||
dt.clearData();
|
||||
|
@ -808,7 +808,7 @@ nsHTMLSelectElement::SetLength(PRUint32 aLength)
|
||||
if (i + 1 < aLength) {
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
|
||||
rv = node->CloneNode(true, getter_AddRefs(newNode));
|
||||
rv = node->CloneNode(true, 1, getter_AddRefs(newNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
node = newNode;
|
||||
|
@ -849,15 +849,11 @@ nsTextInputListener::EditAction()
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
frame->GetEditor(getter_AddRefs(editor));
|
||||
|
||||
nsCOMPtr<nsITransactionManager> manager;
|
||||
editor->GetTransactionManager(getter_AddRefs(manager));
|
||||
NS_ENSURE_TRUE(manager, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the number of undo / redo items
|
||||
PRInt32 numUndoItems = 0;
|
||||
PRInt32 numRedoItems = 0;
|
||||
manager->GetNumberOfUndoItems(&numUndoItems);
|
||||
manager->GetNumberOfRedoItems(&numRedoItems);
|
||||
editor->GetNumberOfUndoItems(&numUndoItems);
|
||||
editor->GetNumberOfRedoItems(&numRedoItems);
|
||||
if ((numUndoItems && !mHadUndoItems) || (!numUndoItems && mHadUndoItems) ||
|
||||
(numRedoItems && !mHadRedoItems) || (!numRedoItems && mHadRedoItems)) {
|
||||
// Modify the menu if undo or redo items are different
|
||||
|
@ -41,163 +41,16 @@
|
||||
|
||||
#include "mozilla/StdInt.h"
|
||||
|
||||
// Adds two 32bit unsigned numbers, retuns true if addition succeeded,
|
||||
// or false the if addition would result in an overflow.
|
||||
bool AddOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult) {
|
||||
PRUint64 rl = static_cast<PRUint64>(a) + static_cast<PRUint64>(b);
|
||||
if (rl > PR_UINT32_MAX) {
|
||||
return false;
|
||||
}
|
||||
aResult = static_cast<PRUint32>(rl);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult)
|
||||
{
|
||||
// 32 bit integer multiplication with overflow checking. Returns true
|
||||
// if the multiplication was successful, or false if the operation resulted
|
||||
// in an integer overflow.
|
||||
PRUint64 a64 = a;
|
||||
PRUint64 b64 = b;
|
||||
PRUint64 r64 = a64 * b64;
|
||||
if (r64 > PR_UINT32_MAX)
|
||||
return false;
|
||||
aResult = static_cast<PRUint32>(r64);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adds two 64bit numbers, retuns true if addition succeeded, or false
|
||||
// if addition would result in an overflow.
|
||||
bool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) {
|
||||
if (b < 1) {
|
||||
if (INT64_MIN - b <= a) {
|
||||
aResult = a + b;
|
||||
return true;
|
||||
}
|
||||
} else if (INT64_MAX - b >= a) {
|
||||
aResult = a + b;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 64 bit integer multiplication with overflow checking. Returns true
|
||||
// if the multiplication was successful, or false if the operation resulted
|
||||
// in an integer overflow.
|
||||
bool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) {
|
||||
// We break a multiplication a * b into of sign_a * sign_b * abs(a) * abs(b)
|
||||
//
|
||||
// This is equivalent to:
|
||||
//
|
||||
// (sign_a * sign_b) * ((a_hi * 2^32) + a_lo) * ((b_hi * 2^32) + b_lo)
|
||||
//
|
||||
// Which is equivalent to:
|
||||
//
|
||||
// (sign_a * sign_b) *
|
||||
// ((a_hi * b_hi << 64) +
|
||||
// (a_hi * b_lo << 32) + (a_lo * b_hi << 32) +
|
||||
// a_lo * b_lo)
|
||||
//
|
||||
// So to check if a*b overflows, we must check each sub part of the above
|
||||
// sum.
|
||||
//
|
||||
// Note: -1 * INT64_MIN == INT64_MIN ; we can't negate INT64_MIN!
|
||||
// Note: Shift of negative numbers is undefined.
|
||||
//
|
||||
// Figure out the sign after multiplication. Then we can just work with
|
||||
// unsigned numbers.
|
||||
PRInt64 sign = (!(a < 0) == !(b < 0)) ? 1 : -1;
|
||||
|
||||
PRInt64 abs_a = (a < 0) ? -a : a;
|
||||
PRInt64 abs_b = (b < 0) ? -b : b;
|
||||
|
||||
if (abs_a < 0) {
|
||||
NS_ASSERTION(a == INT64_MIN, "How else can this happen?");
|
||||
if (b == 0 || b == 1) {
|
||||
aResult = a * b;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs_b < 0) {
|
||||
NS_ASSERTION(b == INT64_MIN, "How else can this happen?");
|
||||
if (a == 0 || a == 1) {
|
||||
aResult = a * b;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(abs_a >= 0 && abs_b >= 0, "abs values must be non-negative");
|
||||
|
||||
PRInt64 a_hi = abs_a >> 32;
|
||||
PRInt64 a_lo = abs_a & 0xFFFFFFFF;
|
||||
PRInt64 b_hi = abs_b >> 32;
|
||||
PRInt64 b_lo = abs_b & 0xFFFFFFFF;
|
||||
|
||||
NS_ASSERTION((a_hi<<32) + a_lo == abs_a, "Partition must be correct");
|
||||
NS_ASSERTION((b_hi<<32) + b_lo == abs_b, "Partition must be correct");
|
||||
|
||||
// In the sub-equation (a_hi * b_hi << 64), if a_hi or b_hi
|
||||
// are non-zero, this will overflow as it's shifted by 64.
|
||||
// Abort if this overflows.
|
||||
if (a_hi != 0 && b_hi != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can now assume that either a_hi or b_hi is 0.
|
||||
NS_ASSERTION(a_hi == 0 || b_hi == 0, "One of these must be 0");
|
||||
|
||||
// Next we calculate:
|
||||
// (a_hi * b_lo << 32) + (a_lo * b_hi << 32)
|
||||
// We can factor this as:
|
||||
// (a_hi * b_lo + a_lo * b_hi) << 32
|
||||
PRInt64 q = a_hi * b_lo + a_lo * b_hi;
|
||||
if (q > PR_INT32_MAX) {
|
||||
// q will overflow when we shift by 32; abort.
|
||||
return false;
|
||||
}
|
||||
q <<= 32;
|
||||
|
||||
// Both a_lo and b_lo are less than INT32_MAX, so can't overflow.
|
||||
PRUint64 lo = a_lo * b_lo;
|
||||
if (lo > INT64_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the final result. We must check for overflow during addition.
|
||||
if (!AddOverflow(q, static_cast<PRInt64>(lo), aResult)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult *= sign;
|
||||
NS_ASSERTION(a * b == aResult, "We didn't overflow, but result is wrong!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts from number of audio frames to microseconds, given the specified
|
||||
// audio rate.
|
||||
bool FramesToUsecs(PRInt64 aFrames, PRUint32 aRate, PRInt64& aOutUsecs)
|
||||
{
|
||||
PRInt64 x;
|
||||
if (!MulOverflow(aFrames, USECS_PER_S, x))
|
||||
return false;
|
||||
aOutUsecs = x / aRate;
|
||||
return true;
|
||||
CheckedInt64 FramesToUsecs(PRInt64 aFrames, PRUint32 aRate) {
|
||||
return (CheckedInt64(aFrames) * USECS_PER_S) / aRate;
|
||||
}
|
||||
|
||||
// Converts from microseconds to number of audio frames, given the specified
|
||||
// audio rate.
|
||||
bool UsecsToFrames(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutFrames)
|
||||
{
|
||||
PRInt64 x;
|
||||
if (!MulOverflow(aUsecs, aRate, x))
|
||||
return false;
|
||||
aOutFrames = x / USECS_PER_S;
|
||||
return true;
|
||||
CheckedInt64 UsecsToFrames(PRInt64 aUsecs, PRUint32 aRate) {
|
||||
return (CheckedInt64(aUsecs) * aRate) / USECS_PER_S;
|
||||
}
|
||||
|
||||
static PRInt32 ConditionDimension(float aValue)
|
||||
|
@ -44,6 +44,13 @@
|
||||
#include "nsRect.h"
|
||||
#include "nsIThreadManager.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
using mozilla::CheckedInt64;
|
||||
using mozilla::CheckedUint64;
|
||||
using mozilla::CheckedInt32;
|
||||
using mozilla::CheckedUint32;
|
||||
|
||||
// This file contains stuff we'd rather put elsewhere, but which is
|
||||
// dependent on other changes which we don't want to wait for. We plan to
|
||||
// remove this file in the near future.
|
||||
@ -97,35 +104,17 @@ private:
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// Adds two 32bit unsigned numbers, retuns true if addition succeeded,
|
||||
// or false the if addition would result in an overflow.
|
||||
bool AddOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult);
|
||||
|
||||
// 32 bit integer multiplication with overflow checking. Returns true
|
||||
// if the multiplication was successful, or false if the operation resulted
|
||||
// in an integer overflow.
|
||||
bool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult);
|
||||
|
||||
// Adds two 64bit numbers, retuns true if addition succeeded, or false
|
||||
// if addition would result in an overflow.
|
||||
bool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
|
||||
|
||||
// 64 bit integer multiplication with overflow checking. Returns true
|
||||
// if the multiplication was successful, or false if the operation resulted
|
||||
// in an integer overflow.
|
||||
bool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
|
||||
|
||||
// Converts from number of audio frames (aFrames) to microseconds, given
|
||||
// the specified audio rate (aRate). Stores result in aOutUsecs. Returns true
|
||||
// if the operation succeeded, or false if there was an integer overflow
|
||||
// while calulating the conversion.
|
||||
bool FramesToUsecs(PRInt64 aFrames, PRUint32 aRate, PRInt64& aOutUsecs);
|
||||
CheckedInt64 FramesToUsecs(PRInt64 aFrames, PRUint32 aRate);
|
||||
|
||||
// Converts from microseconds (aUsecs) to number of audio frames, given the
|
||||
// specified audio rate (aRate). Stores the result in aOutFrames. Returns
|
||||
// true if the operation succeeded, or false if there was an integer
|
||||
// overflow while calulating the conversion.
|
||||
bool UsecsToFrames(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutFrames);
|
||||
CheckedInt64 UsecsToFrames(PRInt64 aUsecs, PRUint32 aRate);
|
||||
|
||||
// Number of microseconds per second. 1e6.
|
||||
static const PRInt64 USECS_PER_S = 1000000;
|
||||
|
@ -142,12 +142,10 @@ VideoData* VideoData::Create(nsVideoInfo& aInfo,
|
||||
|
||||
// Ensure the picture size specified in the headers can be extracted out of
|
||||
// the frame we've been supplied without indexing out of bounds.
|
||||
PRUint32 xLimit;
|
||||
PRUint32 yLimit;
|
||||
if (!AddOverflow32(aPicture.x, aPicture.width, xLimit) ||
|
||||
xLimit > aBuffer.mPlanes[0].mStride ||
|
||||
!AddOverflow32(aPicture.y, aPicture.height, yLimit) ||
|
||||
yLimit > aBuffer.mPlanes[0].mHeight)
|
||||
CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
|
||||
CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
|
||||
if (!xLimit.valid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
|
||||
!yLimit.valid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
|
||||
{
|
||||
// The specified picture dimensions can't be contained inside the video
|
||||
// frame, we'll stomp memory if we try to copy it. Fail.
|
||||
@ -312,10 +310,6 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
|
||||
if (HasAudio()) {
|
||||
// Decode audio forward to the seek target.
|
||||
PRInt64 targetFrame = 0;
|
||||
if (!UsecsToFrames(aTarget, mInfo.mAudioRate, targetFrame)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
bool eof = false;
|
||||
while (HasAudio() && !eof) {
|
||||
while (!eof && mAudioQueue.GetSize() == 0) {
|
||||
@ -330,18 +324,19 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
const AudioData* audio = mAudioQueue.PeekFront();
|
||||
if (!audio)
|
||||
break;
|
||||
PRInt64 startFrame = 0;
|
||||
if (!UsecsToFrames(audio->mTime, mInfo.mAudioRate, startFrame)) {
|
||||
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudioRate);
|
||||
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudioRate);
|
||||
if (!startFrame.valid() || !targetFrame.valid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (startFrame + audio->mFrames <= targetFrame) {
|
||||
if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
|
||||
// Our seek target lies after the frames in this AudioData. Pop it
|
||||
// off the queue, and keep decoding forwards.
|
||||
delete mAudioQueue.PopFront();
|
||||
audio = nsnull;
|
||||
continue;
|
||||
}
|
||||
if (startFrame > targetFrame) {
|
||||
if (startFrame.value() > targetFrame.value()) {
|
||||
// The seek target doesn't lie in the audio block just after the last
|
||||
// audio frames we've seen which were before the seek target. This
|
||||
// could have been the first audio data we've seen after seek, i.e. the
|
||||
@ -356,10 +351,12 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
// The seek target lies somewhere in this AudioData's frames, strip off
|
||||
// any frames which lie before the seek target, so we'll begin playback
|
||||
// exactly at the seek target.
|
||||
NS_ASSERTION(targetFrame >= startFrame, "Target must at or be after data start.");
|
||||
NS_ASSERTION(targetFrame < startFrame + audio->mFrames, "Data must end after target.");
|
||||
NS_ASSERTION(targetFrame.value() >= startFrame.value(),
|
||||
"Target must at or be after data start.");
|
||||
NS_ASSERTION(targetFrame.value() < startFrame.value() + audio->mFrames,
|
||||
"Data must end after target.");
|
||||
|
||||
PRInt64 framesToPrune = targetFrame - startFrame;
|
||||
PRInt64 framesToPrune = targetFrame.value() - startFrame.value();
|
||||
if (framesToPrune > audio->mFrames) {
|
||||
// We've messed up somehow. Don't try to trim frames, the |frames|
|
||||
// variable below will overflow.
|
||||
@ -372,13 +369,13 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
memcpy(audioData.get(),
|
||||
audio->mAudioData.get() + (framesToPrune * channels),
|
||||
frames * channels * sizeof(AudioDataValue));
|
||||
PRInt64 duration;
|
||||
if (!FramesToUsecs(frames, mInfo.mAudioRate, duration)) {
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudioRate);
|
||||
if (!duration.valid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoPtr<AudioData> data(new AudioData(audio->mOffset,
|
||||
aTarget,
|
||||
duration,
|
||||
duration.value(),
|
||||
frames,
|
||||
audioData.forget(),
|
||||
channels));
|
||||
|
@ -806,53 +806,39 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||
|
||||
// Calculate the number of frames that have been pushed onto the audio
|
||||
// hardware.
|
||||
PRInt64 playedFrames = 0;
|
||||
if (!UsecsToFrames(audioStartTime, rate, playedFrames)) {
|
||||
NS_WARNING("Int overflow converting playedFrames");
|
||||
break;
|
||||
}
|
||||
if (!AddOverflow(playedFrames, audioDuration, playedFrames)) {
|
||||
NS_WARNING("Int overflow adding playedFrames");
|
||||
break;
|
||||
}
|
||||
|
||||
CheckedInt64 playedFrames = UsecsToFrames(audioStartTime, rate) +
|
||||
audioDuration;
|
||||
// Calculate the timestamp of the next chunk of audio in numbers of
|
||||
// samples.
|
||||
PRInt64 sampleTime = 0;
|
||||
if (!UsecsToFrames(s->mTime, rate, sampleTime)) {
|
||||
NS_WARNING("Int overflow converting sampleTime");
|
||||
break;
|
||||
}
|
||||
PRInt64 missingFrames = 0;
|
||||
if (!AddOverflow(sampleTime, -playedFrames, missingFrames)) {
|
||||
NS_WARNING("Int overflow adding missingFrames");
|
||||
CheckedInt64 sampleTime = UsecsToFrames(s->mTime, rate);
|
||||
CheckedInt64 missingFrames = sampleTime - playedFrames;
|
||||
if (!missingFrames.valid() || !sampleTime.valid()) {
|
||||
NS_WARNING("Int overflow adding in AudioLoop()");
|
||||
break;
|
||||
}
|
||||
|
||||
PRInt64 framesWritten = 0;
|
||||
if (missingFrames > 0) {
|
||||
if (missingFrames.value() > 0) {
|
||||
// The next audio chunk begins some time after the end of the last chunk
|
||||
// we pushed to the audio hardware. We must push silence into the audio
|
||||
// hardware so that the next audio chunk begins playback at the correct
|
||||
// time.
|
||||
missingFrames = NS_MIN(static_cast<PRInt64>(PR_UINT32_MAX), missingFrames);
|
||||
framesWritten = PlaySilence(static_cast<PRUint32>(missingFrames),
|
||||
channels, playedFrames);
|
||||
missingFrames = NS_MIN(static_cast<PRInt64>(PR_UINT32_MAX),
|
||||
missingFrames.value());
|
||||
framesWritten = PlaySilence(static_cast<PRUint32>(missingFrames.value()),
|
||||
channels, playedFrames.value());
|
||||
} else {
|
||||
framesWritten = PlayFromAudioQueue(sampleTime, channels);
|
||||
framesWritten = PlayFromAudioQueue(sampleTime.value(), channels);
|
||||
}
|
||||
audioDuration += framesWritten;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
PRInt64 playedUsecs;
|
||||
if (!FramesToUsecs(audioDuration, rate, playedUsecs)) {
|
||||
NS_WARNING("Int overflow calculating playedUsecs");
|
||||
break;
|
||||
}
|
||||
if (!AddOverflow(audioStartTime, playedUsecs, mAudioEndTime)) {
|
||||
CheckedInt64 playedUsecs = FramesToUsecs(audioDuration, rate) + audioStartTime;
|
||||
if (!playedUsecs.valid()) {
|
||||
NS_WARNING("Int overflow calculating audio end time");
|
||||
break;
|
||||
}
|
||||
mAudioEndTime = playedUsecs.value();
|
||||
}
|
||||
}
|
||||
if (mReader->mAudioQueue.AtEndOfStream() &&
|
||||
|
@ -318,33 +318,27 @@ PRInt64 nsTheoraState::Time(th_info* aInfo, PRInt64 aGranulepos)
|
||||
if (aGranulepos < 0 || aInfo->fps_numerator == 0) {
|
||||
return -1;
|
||||
}
|
||||
PRInt64 t = 0;
|
||||
// Implementation of th_granule_frame inlined here to operate
|
||||
// on the th_info structure instead of the theora_state.
|
||||
int shift = aInfo->keyframe_granule_shift;
|
||||
ogg_int64_t iframe = aGranulepos >> shift;
|
||||
ogg_int64_t pframe = aGranulepos - (iframe << shift);
|
||||
PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
|
||||
if (!AddOverflow(frameno, 1, t))
|
||||
CheckedInt64 t = ((CheckedInt64(frameno) + 1) * USECS_PER_S) * aInfo->fps_denominator;
|
||||
if (!t.valid())
|
||||
return -1;
|
||||
if (!MulOverflow(t, USECS_PER_S, t))
|
||||
return -1;
|
||||
if (!MulOverflow(t, aInfo->fps_denominator, t))
|
||||
return -1;
|
||||
return t / aInfo->fps_numerator;
|
||||
t /= aInfo->fps_numerator;
|
||||
return t.valid() ? t.value() : -1;
|
||||
}
|
||||
|
||||
PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
|
||||
if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) {
|
||||
return -1;
|
||||
}
|
||||
PRInt64 t = 0;
|
||||
PRInt64 frameno = th_granule_frame(mCtx, granulepos);
|
||||
if (!MulOverflow(frameno, USECS_PER_S, t))
|
||||
CheckedInt64 t = (CheckedInt64(th_granule_frame(mCtx, granulepos)) * USECS_PER_S) * mInfo.fps_denominator;
|
||||
if (!t.valid())
|
||||
return -1;
|
||||
if (!MulOverflow(t, mInfo.fps_denominator, t))
|
||||
return -1;
|
||||
return t / mInfo.fps_numerator;
|
||||
return t.value() / mInfo.fps_numerator;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
@ -361,9 +355,10 @@ nsTheoraState::MaxKeyframeOffset()
|
||||
PRInt64 keyframeDiff = (1 << mInfo.keyframe_granule_shift) - 1;
|
||||
|
||||
// Length of frame in usecs.
|
||||
PRInt64 d = 0; // d will be 0 if multiplication overflows.
|
||||
MulOverflow(USECS_PER_S, mInfo.fps_denominator, d);
|
||||
frameDuration = d / mInfo.fps_numerator;
|
||||
CheckedInt64 d = CheckedInt64(mInfo.fps_denominator) * USECS_PER_S;
|
||||
if (!d.valid())
|
||||
d = 0;
|
||||
frameDuration = d.value() / mInfo.fps_numerator;
|
||||
|
||||
// Total time in usecs keyframe can be offset from any given frame.
|
||||
return frameDuration * keyframeDiff;
|
||||
@ -601,9 +596,10 @@ PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
|
||||
if (aGranulepos == -1 || aInfo->rate == 0) {
|
||||
return -1;
|
||||
}
|
||||
PRInt64 t = 0;
|
||||
MulOverflow(USECS_PER_S, aGranulepos, t);
|
||||
return t / aInfo->rate;
|
||||
CheckedInt64 t = CheckedInt64(aGranulepos) * USECS_PER_S;
|
||||
if (!t.valid())
|
||||
t = 0;
|
||||
return t.value() / aInfo->rate;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -872,7 +868,6 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
PRUint32 serialno = LEUint32(aPacket->packet + INDEX_SERIALNO_OFFSET);
|
||||
PRInt64 numKeyPoints = LEInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET);
|
||||
|
||||
PRInt64 n = 0;
|
||||
PRInt64 endTime = 0, startTime = 0;
|
||||
const unsigned char* p = aPacket->packet;
|
||||
|
||||
@ -884,34 +879,32 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
}
|
||||
|
||||
// Extract the start time.
|
||||
n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET);
|
||||
PRInt64 t;
|
||||
if (!MulOverflow(n, USECS_PER_S, t)) {
|
||||
CheckedInt64 t = CheckedInt64(LEInt64(p + INDEX_FIRST_NUMER_OFFSET)) * USECS_PER_S;
|
||||
if (!t.valid()) {
|
||||
return (mActive = false);
|
||||
} else {
|
||||
startTime = t / timeDenom;
|
||||
startTime = t.value() / timeDenom;
|
||||
}
|
||||
|
||||
// Extract the end time.
|
||||
n = LEInt64(p + INDEX_LAST_NUMER_OFFSET);
|
||||
if (!MulOverflow(n, USECS_PER_S, t)) {
|
||||
t = LEInt64(p + INDEX_LAST_NUMER_OFFSET) * USECS_PER_S;
|
||||
if (!t.valid()) {
|
||||
return (mActive = false);
|
||||
} else {
|
||||
endTime = t / timeDenom;
|
||||
endTime = t.value() / timeDenom;
|
||||
}
|
||||
|
||||
// Check the numKeyPoints value read, ensure we're not going to run out of
|
||||
// memory while trying to decode the index packet.
|
||||
PRInt64 minPacketSize;
|
||||
if (!MulOverflow(numKeyPoints, MIN_KEY_POINT_SIZE, minPacketSize) ||
|
||||
!AddOverflow(INDEX_KEYPOINT_OFFSET, minPacketSize, minPacketSize))
|
||||
CheckedInt64 minPacketSize = (CheckedInt64(numKeyPoints) * MIN_KEY_POINT_SIZE) + INDEX_KEYPOINT_OFFSET;
|
||||
if (!minPacketSize.valid())
|
||||
{
|
||||
return (mActive = false);
|
||||
}
|
||||
|
||||
PRInt64 sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
|
||||
PRInt64 maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
|
||||
if (aPacket->bytes < minPacketSize ||
|
||||
if (aPacket->bytes < minPacketSize.value() ||
|
||||
numKeyPoints > maxNumKeyPoints ||
|
||||
numKeyPoints < 0)
|
||||
{
|
||||
@ -933,32 +926,34 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
p = aPacket->packet + INDEX_KEYPOINT_OFFSET;
|
||||
const unsigned char* limit = aPacket->packet + aPacket->bytes;
|
||||
PRInt64 numKeyPointsRead = 0;
|
||||
PRInt64 offset = 0;
|
||||
PRInt64 time = 0;
|
||||
CheckedInt64 offset = 0;
|
||||
CheckedInt64 time = 0;
|
||||
while (p < limit &&
|
||||
numKeyPointsRead < numKeyPoints)
|
||||
{
|
||||
PRInt64 delta = 0;
|
||||
p = ReadVariableLengthInt(p, limit, delta);
|
||||
offset += delta;
|
||||
if (p == limit ||
|
||||
!AddOverflow(offset, delta, offset) ||
|
||||
offset > mLength ||
|
||||
offset < 0)
|
||||
!offset.valid() ||
|
||||
offset.value() > mLength ||
|
||||
offset.value() < 0)
|
||||
{
|
||||
return (mActive = false);
|
||||
}
|
||||
p = ReadVariableLengthInt(p, limit, delta);
|
||||
if (!AddOverflow(time, delta, time) ||
|
||||
time > endTime ||
|
||||
time < startTime)
|
||||
time += delta;
|
||||
if (!time.valid() ||
|
||||
time.value() > endTime ||
|
||||
time.value() < startTime)
|
||||
{
|
||||
return (mActive = false);
|
||||
}
|
||||
PRInt64 timeUsecs = 0;
|
||||
if (!MulOverflow(time, USECS_PER_S, timeUsecs))
|
||||
CheckedInt64 timeUsecs = time * USECS_PER_S;
|
||||
if (!timeUsecs.valid())
|
||||
return mActive = false;
|
||||
timeUsecs /= timeDenom;
|
||||
keyPoints->Add(offset, timeUsecs);
|
||||
keyPoints->Add(offset.value(), timeUsecs.value());
|
||||
numKeyPointsRead++;
|
||||
}
|
||||
|
||||
@ -1064,7 +1059,9 @@ nsresult nsSkeletonState::GetDuration(const nsTArray<PRUint32>& aTracks,
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(endTime > startTime, "Duration must be positive");
|
||||
return AddOverflow(endTime, -startTime, aDuration) ? NS_OK : NS_ERROR_FAILURE;
|
||||
CheckedInt64 duration = CheckedInt64(endTime) - startTime;
|
||||
aDuration = duration.valid() ? duration.value() : 0;
|
||||
return duration.valid() ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user