Bug 714579 - Don't use GetComputedStyle for object attribute calculation, r=tbsaunde, marcoz, f=bz

This commit is contained in:
Alexander Surkov 2012-02-21 00:45:29 +09:00
parent f62564ac00
commit bb70916d54
8 changed files with 431 additions and 67 deletions

View File

@ -76,6 +76,7 @@ CPPSRCS = \
nsTextAccessible.cpp \
nsTextEquivUtils.cpp \
nsTextAttrs.cpp \
StyleInfo.cpp \
TextUpdater.cpp \
$(NULL)
@ -107,6 +108,7 @@ LOCAL_INCLUDES += \
-I$(srcdir)/../html \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/style \
-I$(srcdir)/../../../layout/xul/base/src \
-I$(srcdir)/../xforms \
$(NULL)

View File

@ -0,0 +1,112 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 "StyleInfo.h"
#include "mozilla/dom/Element.h"
#include "nsComputedDOMStyle.h"
using namespace mozilla;
using namespace mozilla::a11y;
StyleInfo::StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell) :
mElement(aElement)
{
mStyleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nsnull,
aPresShell);
}
void
StyleInfo::Display(nsAString& aValue)
{
aValue.Truncate();
AppendASCIItoUTF16(
nsCSSProps::ValueToKeyword(mStyleContext->GetStyleDisplay()->mDisplay,
nsCSSProps::kDisplayKTable), aValue);
}
void
StyleInfo::TextAlign(nsAString& aValue)
{
aValue.Truncate();
AppendASCIItoUTF16(
nsCSSProps::ValueToKeyword(mStyleContext->GetStyleText()->mTextAlign,
nsCSSProps::kTextAlignKTable), aValue);
}
void
StyleInfo::TextIndent(nsAString& aValue)
{
aValue.Truncate();
const nsStyleCoord& styleCoord =
mStyleContext->GetStyleText()->mTextIndent;
nscoord coordVal;
switch (styleCoord.GetUnit()) {
case eStyleUnit_Coord:
coordVal = styleCoord.GetCoordValue();
break;
case eStyleUnit_Percent:
{
nsIFrame* frame = mElement->GetPrimaryFrame();
nsIFrame* containerFrame = frame->GetContainingBlock();
nscoord percentageBase = containerFrame->GetContentRect().width;
coordVal = NSCoordSaturatingMultiply(percentageBase,
styleCoord.GetPercentValue());
break;
}
}
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
aValue.AppendLiteral("px");
}
void
StyleInfo::Margin(css::Side aSide, nsAString& aValue)
{
aValue.Truncate();
nscoord coordVal = mElement->GetPrimaryFrame()->GetUsedMargin().Side(aSide);
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
aValue.AppendLiteral("px");
}

View File

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _mozilla_a11y_style_h_
#define _mozilla_a11y_style_h_
#include "mozilla/gfx/Types.h"
#include "nsStyleContext.h"
namespace mozilla {
namespace a11y {
class StyleInfo
{
public:
StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell);
~StyleInfo() { };
void Display(nsAString& aValue);
void TextAlign(nsAString& aValue);
void TextIndent(nsAString& aValue);
void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); }
void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); }
void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
private:
StyleInfo() MOZ_DELETE;
StyleInfo(const StyleInfo&) MOZ_DELETE;
StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
void Margin(css::Side aSide, nsAString& aValue);
dom::Element* mElement;
nsRefPtr<nsStyleContext> mStyleContext;
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -44,19 +44,18 @@
#include "AccGroupInfo.h"
#include "AccIterator.h"
#include "nsAccUtils.h"
#include "nsDocAccessible.h"
#include "nsEventShell.h"
#include "nsAccEvent.h"
#include "nsAccessibleRelation.h"
#include "nsAccessibilityService.h"
#include "nsAccTreeWalker.h"
#include "nsIAccessibleRelation.h"
#include "nsEventShell.h"
#include "nsRootAccessible.h"
#include "nsTextEquivUtils.h"
#include "Relation.h"
#include "Role.h"
#include "States.h"
#include "StyleInfo.h"
#include "nsIDOMCSSValue.h"
#include "nsIDOMCSSPrimitiveValue.h"
@ -1442,49 +1441,40 @@ nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
startContent = parentDoc->FindContentForSubDocument(doc);
}
// Expose 'display' attribute.
if (!mContent->IsElement())
return NS_OK;
// CSS style based object attributes.
nsAutoString value;
nsresult rv = GetComputedStyleValue(EmptyString(),
NS_LITERAL_STRING("display"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
StyleInfo styleInfo(mContent->AsElement(), mDoc->PresShell());
// Expose 'display' attribute.
styleInfo.Display(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
// Expose 'text-align' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("text-align"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
styleInfo.TextAlign(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
// Expose 'text-indent' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("text-indent"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
styleInfo.TextIndent(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
// Expose 'margin-left' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-left"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
styleInfo.MarginLeft(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
// Expose 'margin-right' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-right"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
styleInfo.MarginRight(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
// Expose 'margin-top' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-top"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
styleInfo.MarginTop(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
// Expose 'margin-bottom' attribute.
rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-bottom"),
value);
if (NS_SUCCEEDED(rv))
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
styleInfo.MarginBottom(value);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
// Expose draggable object attribute?
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);

View File

@ -27,6 +27,26 @@ function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs)
testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs);
}
/**
* Test CSS based object attributes.
*/
function testCSSAttrs(aID)
{
var node = document.getElementById(aID);
var computedStyle = document.defaultView.getComputedStyle(node, "");
var attrs = {
"display": computedStyle.display,
"text-align": computedStyle.textAlign,
"text-indent": computedStyle.textIndent,
"margin-left": computedStyle.marginLeft,
"margin-right": computedStyle.marginRight,
"margin-top": computedStyle.marginTop,
"margin-bottom": computedStyle.marginBottom
};
testAttrs(aID, attrs, true);
}
/**
* Test group object attributes (posinset, setsize and level) and
* nsIAccessible::groupPosition() method.

View File

@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_obj.html \
test_obj_css.html \
test_obj_css.xul \
test_obj_group.html \
test_obj_group.xul \
test_obj_group_tree.xul \

View File

@ -18,36 +18,65 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=689540
src="../attributes.js"></script>
<script type="application/javascript">
function testCSSAttrs(aID)
{
var node = document.getElementById(aID);
var computedStyle = document.defaultView.getComputedStyle(node, "");
var attrs = {
"display": computedStyle.display,
"text-align": computedStyle.textAlign,
"text-indent": computedStyle.textIndent,
"margin-left": computedStyle.marginLeft,
"margin-right": computedStyle.marginRight,
"margin-top": computedStyle.marginTop,
"margin-bottom": computedStyle.marginBottom
};
testAttrs(aID, attrs, true);
}
function doTest()
{
// CSS display
testCSSAttrs("display_block");
testCSSAttrs("display_inline");
testCSSAttrs("display_inline-block");
testCSSAttrs("display_list-item");
testCSSAttrs("display_table");
testCSSAttrs("display_inline-table");
testCSSAttrs("display_table-row-group");
testCSSAttrs("display_table-column");
testCSSAttrs("display_table-column-group");
testCSSAttrs("display_table-header-group");
testCSSAttrs("display_table-footer-group");
testCSSAttrs("display_table-row");
testCSSAttrs("display_table-cell");
testCSSAttrs("display_table-caption");
// CSS text-align
testCSSAttrs("text-align_left");
testCSSAttrs("text-align_right");
testCSSAttrs("text-align_center");
testCSSAttrs("text-align_justify");
testCSSAttrs("text-align_inherit");
// CSS text-indent
testCSSAttrs("text-indent_em");
testCSSAttrs("text-indent_ex");
testCSSAttrs("text-indent_in");
testCSSAttrs("text-indent_cm");
testCSSAttrs("text-indent_mm");
testCSSAttrs("text-indent_pt");
testCSSAttrs("text-indent_pc");
testCSSAttrs("text-indent_px");
testCSSAttrs("text-indent_percent");
testCSSAttrs("text-indent_inherit");
// CSS margin
testCSSAttrs("margin_em");
testCSSAttrs("margin_ex");
testCSSAttrs("margin_in");
testCSSAttrs("margin_cm");
testCSSAttrs("margin_mm");
testCSSAttrs("margin_pt");
testCSSAttrs("margin_pc");
testCSSAttrs("margin_px");
testCSSAttrs("margin_percent");
testCSSAttrs("margin_auto");
testCSSAttrs("margin_inherit");
testCSSAttrs("margin-left");
testCSSAttrs("margin-right");
testCSSAttrs("margin-top");
testCSSAttrs("margin-bottom");
// Elements
testCSSAttrs("span");
testCSSAttrs("div");
testCSSAttrs("p");
testCSSAttrs("p2");
testCSSAttrs("pml");
testCSSAttrs("pmr");
testCSSAttrs("pmt");
testCSSAttrs("pmb");
testCSSAttrs("input");
testCSSAttrs("table");
testCSSAttrs("tr");
@ -77,25 +106,85 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=689540
title="Expose IA2 margin- object attributes">
Mozilla Bug 689540
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579"
title="Don't use GetComputedStyle for object attribute calculation">
Mozilla Bug 714579
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="display_block" role="img"
style="display: block;">display: block</div>
<div id="display_inline" role="img"
style="display: inline;">display: inline</div>
<div id="display_inline-block" role="img"
style="display: inline-block;">display: inline-block</div>
<div id="display_list-item" role="img"
style="display: list-item;">display: list-item</div>
<div id="display_table" role="img"
style="display: table;">display: table</div>
<div id="display_inline-table" role="img"
style="display: inline-table;">display: inline-table</div>
<div id="display_table-row-group" role="img"
style="display: table-row-group;">display: table-row-group</div>
<div id="display_table-column" role="img"
style="display: table-column;">display: table-column</div>
<div id="display_table-column-group" role="img"
style="display: table-column-group;">display: table-column-group</div>
<div id="display_table-header-group" role="img"
style="display: table-header-group;">display: table-header-group</div>
<div id="display_table-footer-group" role="img"
style="display: table-footer-group;">display: table-footer-group</div>
<div id="display_table-row" role="img"
style="display: table-row;">display: table-row</div>
<div id="display_table-cell" role="img"
style="display: table-cell;">display: table-cell</div>
<div id="display_table-caption" role="img"
style="display: table-caption;">display: table-caption</div>
<p id="text-align_left" style="text-align: left;">text-align: left</p>
<p id="text-align_right" style="text-align: right;">text-align: right</p>
<p id="text-align_center" style="text-align: center;">text-align: center</p>
<p id="text-align_justify" style="text-align: justify;">text-align: justify</p>
<p id="text-align_inherit" style="text-align: inherit;">text-align: inherit</p>
<p id="text-indent_em" style="text-indent: 0.5em;">text-indent: 0.5em</p>
<p id="text-indent_ex" style="text-indent: 1ex;">text-indent: 1ex</p>
<p id="text-indent_in" style="text-indent: 0.5in;">text-indent: 0.5in</p>
<p id="text-indent_cm" style="text-indent: 2cm;">text-indent: 2cm</p>
<p id="text-indent_mm" style="text-indent: 10mm;">text-indent: 10mm</p>
<p id="text-indent_pt" style="text-indent: 30pt;">text-indent: 30pt</p>
<p id="text-indent_pc" style="text-indent: 2pc;">text-indent: 2pc</p>
<p id="text-indent_px" style="text-indent: 5px;">text-indent: 5px</p>
<p id="text-indent_percent" style="text-indent: 10%;">text-indent: 10%</p>
<p id="text-indent_inherit" style="text-indent: inherit;">text-indent: inherit</p>
<p id="margin_em" style="margin: 0.5em;">margin: 0.5em</p>
<p id="margin_ex" style="margin: 1ex;">margin: 1ex</p>
<p id="margin_in" style="margin: 0.5in;">margin: 0.5in</p>
<p id="margin_cm" style="margin: 2cm;">margin: 2cm</p>
<p id="margin_mm" style="margin: 10mm;">margin: 10mm</p>
<p id="margin_pt" style="margin: 30pt;">margin: 30pt</p>
<p id="margin_pc" style="margin: 2pc;">margin: 2pc</p>
<p id="margin_px" style="margin: 5px;">margin: 5px</p>
<p id="margin_percent" style="margin: 10%;">margin: 10%</p>
<p id="margin_auto" style="margin: auto;">margin: auto</p>
<p id="margin_inherit" style="margin: inherit;">margin: inherit</p>
<p id="margin-left" style="margin-left: 11px;">margin-left: 11px</p>
<p id="margin-right" style="margin-right: 21px;">margin-right</p>
<p id="margin-top" style="margin-top: 31px;">margin-top: 31px</p>
<p id="margin-bottom" style="margin-bottom: 41px;">margin-bottom: 41px</p>
<span id="span" role="group">It's span</span>
<div id="div">It's div</div>
<p id="p">It's paragraph"</p>
<p id="p2" style="text-indent: 5px">It's another paragraph</p>
<p id="pml" style="margin-left : 11px;">It's a paragraph with left margin</p>
<p id="pmr" style="margin-right : 21px;">It's a paragraph with right margin</p>
<p id="pmt" style="margin-top : 31px;">It's a paragraph with top margin</p>
<p id="pmb" style="margin-bottom : 41px;">It's a paragraph with bottom margin</p>
<input id="input"/>
<table id="table">
<table id="table" style="margin: 2px; text-align: center; text-indent: 10%;">
<tr id="tr" role="group">
<td id="td">td</td>
</tr>

View File

@ -0,0 +1,73 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessibility CSS-based Object Attributes Test.">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../attributes.js" />
<script type="application/javascript">
<![CDATA[
function doTest()
{
// CSS display
testCSSAttrs("display_mozbox");
testCSSAttrs("display_mozinlinebox");
testCSSAttrs("display_mozgrid");
testCSSAttrs("display_mozinlinegrid");
testCSSAttrs("display_mozgridgroup");
testCSSAttrs("display_mozgridline");
testCSSAttrs("display_mozstack");
testCSSAttrs("display_mozinlinestack");
testCSSAttrs("display_mozdeck");
testCSSAttrs("display_mozpopup");
testCSSAttrs("display_mozgroupbox");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579"
title="Don't use GetComputedStyle for object attribute calculation">
Mozilla Bug 714579
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="display_mozbox" style="display: -moz-box;" role="img"/>
<vbox id="display_mozinlinebox" style="display: -moz-inline-box;" role="img"/>
<vbox id="display_mozgrid" style="display: -moz-grid;" role="img"/>
<vbox id="display_mozinlinegrid" style="display: -moz-inline-grid;" role="img"/>
<vbox id="display_mozgridgroup" style="display: -moz-grid-group;" role="img"/>
<vbox id="display_mozgridline" style="display: -moz-grid-line;" role="img"/>
<vbox id="display_mozstack" style="display: -moz-stack;" role="img"/>
<vbox id="display_mozinlinestack" style="display: -moz-inline-stack;" role="img"/>
<vbox id="display_mozdeck" style="display: -moz-deck;" role="img"/>
<vbox id="display_mozpopup" style="display: -moz-popup;" role="img"/>
<vbox id="display_mozgroupbox" style="display: -moz-groupbox;" role="img"/>
</hbox>
</window>