Merge last green PGO from inbound to central

This commit is contained in:
Marco Bonardo 2012-03-13 11:17:21 +01:00
commit 720c67a69d
261 changed files with 5667 additions and 2319 deletions

View File

@ -59,7 +59,7 @@ interface nsIAccessibleRelation;
* Mozilla creates the implementations of nsIAccessible on demand.
* See http://www.mozilla.org/projects/ui/accessibility for more information.
*/
[scriptable, uuid(3126544c-826c-4694-a2ed-67bfe56a1f37)]
[scriptable, uuid(e7c44e0d-736e-4ead-afee-b51f4b574020)]
interface nsIAccessible : nsISupports
{
/**
@ -110,26 +110,6 @@ interface nsIAccessible : nsISupports
*/
readonly attribute DOMString innerHTML;
/**
* Retrieve the computed style value for this DOM node, if it is a DOM element.
* Note: the meanings of width, height and other size measurements depend
* on the version of CSS being used. Therefore, for bounds information,
* it is better to use nsIAccessible::accGetBounds.
*
* @param pseudoElt [in] The pseudo element to retrieve style for, or NULL
* for general computed style information for this node.
* @param propertyName [in] Retrieve the computed style value for this property name,
* for example "border-bottom".
*/
DOMString getComputedStyleValue(in DOMString pseudoElt, in DOMString propertyName);
/**
* The method is similar to getComputedStyleValue() excepting that this one
* returns nsIDOMCSSPrimitiveValue.
*/
nsIDOMCSSPrimitiveValue getComputedStyleCSSValue(in DOMString pseudoElt,
in DOMString propertyName);
/**
* The DOM node this nsIAccessible is associated with.
*/

View File

@ -66,6 +66,8 @@ public:
role != mozilla::a11y::roles::OPTION &&
role != mozilla::a11y::roles::LISTITEM &&
role != mozilla::a11y::roles::MENUITEM &&
role != mozilla::a11y::roles::COMBOBOX_OPTION &&
role != mozilla::a11y::roles::PARENT_MENUITEM &&
role != mozilla::a11y::roles::CHECK_MENU_ITEM &&
role != mozilla::a11y::roles::RADIO_MENU_ITEM &&
role != mozilla::a11y::roles::RADIOBUTTON &&
@ -83,6 +85,7 @@ private:
static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
{
if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
aRole == mozilla::a11y::roles::PARENT_MENUITEM ||
aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
return mozilla::a11y::roles::MENUITEM;
return aRole;

View File

@ -175,70 +175,6 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent,
(*aPosInSet)++; // group position is 1-index based.
}
void
nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
PRInt32 *aPosInSet,
PRInt32 *aSetSize)
{
nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent));
if (!item)
return;
nsCOMPtr<nsIDOMXULContainerElement> container;
item->GetParentContainer(getter_AddRefs(container));
if (!container)
return;
// Get item count.
PRUint32 itemsCount = 0;
container->GetItemCount(&itemsCount);
// Get item index.
PRInt32 indexOf = 0;
container->GetIndexOfItem(item, &indexOf);
// Calculate set size and position in the set.
*aSetSize = 0, *aPosInSet = 0;
for (PRInt32 index = indexOf; index >= 0; index--) {
nsCOMPtr<nsIDOMXULElement> item;
container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc = itemNode ?
GetAccService()->GetAccessible(itemNode, nsnull) : nsnull;
if (itemAcc) {
PRUint32 itemRole = Role(itemAcc);
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
break; // We reached the beginning of our group.
if (!(itemAcc->State() & states::INVISIBLE)) {
(*aSetSize)++;
(*aPosInSet)++;
}
}
}
for (PRInt32 index = indexOf + 1; index < static_cast<PRInt32>(itemsCount);
index++) {
nsCOMPtr<nsIDOMXULElement> item;
container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc =
itemNode ? GetAccService()->GetAccessible(itemNode, nsnull) : nsnull;
if (itemAcc) {
PRUint32 itemRole = Role(itemAcc);
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
break; // We reached the end of our group.
if (!(itemAcc->State() & states::INVISIBLE))
(*aSetSize)++;
}
}
}
PRInt32
nsAccUtils::GetLevelForXULContainerItem(nsIContent *aContent)
{

View File

@ -115,14 +115,6 @@ public:
PRInt32 *aPosInSet,
PRInt32 *aSetSize);
/**
* Compute group position and group size (posinset and setsize) for
* nsIDOMXULContainerItemElement node.
*/
static void GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
PRInt32 *aPosInSet,
PRInt32 *aSetSize);
/**
* Compute group level for nsIDOMXULContainerItemElement node.
*/

View File

@ -231,42 +231,6 @@ nsAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
mRoleMapEntry = aRoleMapEntry;
}
NS_IMETHODIMP
nsAccessible::GetComputedStyleValue(const nsAString& aPseudoElt,
const nsAString& aPropertyName,
nsAString& aValue)
{
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent);
NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
return styleDecl->GetPropertyValue(aPropertyName, aValue);
}
NS_IMETHODIMP
nsAccessible::GetComputedStyleCSSValue(const nsAString& aPseudoElt,
const nsAString& aPropertyName,
nsIDOMCSSPrimitiveValue **aCSSValue) {
NS_ENSURE_ARG_POINTER(aCSSValue);
*aCSSValue = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent);
NS_ENSURE_STATE(styleDecl);
nsCOMPtr<nsIDOMCSSValue> cssValue;
styleDecl->GetPropertyCSSValue(aPropertyName, getter_AddRefs(cssValue));
NS_ENSURE_TRUE(cssValue, NS_ERROR_FAILURE);
return CallQueryInterface(cssValue, aCSSValue);
}
NS_IMETHODIMP
nsAccessible::GetDocument(nsIAccessibleDocument **aDocument)
{

View File

@ -467,24 +467,6 @@ nsApplicationAccessible::ScrollToPoint(PRUint32 aCoordinateType,
return NS_OK;
}
NS_IMETHODIMP
nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt,
const nsAString &aPropertyName,
nsAString &aValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsApplicationAccessible::GetComputedStyleCSSValue(const nsAString &aPseudoElt,
const nsAString &aPropertyName,
nsIDOMCSSPrimitiveValue **aCSSPrimitiveValue)
{
NS_ENSURE_ARG_POINTER(aCSSPrimitiveValue);
*aCSSPrimitiveValue = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
{

View File

@ -76,12 +76,6 @@ public:
NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt,
const nsAString& aPropertyName,
nsAString& aValue NS_OUTPARAM);
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleCSSValue(const nsAString& aPseudoElt,
const nsAString& aPropertyName,
nsIDOMCSSPrimitiveValue** aValue NS_OUTPARAM);
NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);

View File

@ -570,26 +570,6 @@ nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
walkUp = walkUp->GetParent();
}
already_AddRefed<nsIDOMCSSStyleDeclaration>
nsCoreUtils::GetComputedStyleDeclaration(const nsAString& aPseudoElt,
nsIContent *aContent)
{
nsIContent* content = GetDOMElementFor(aContent);
if (!content)
return nsnull;
// Returns number of items in style declaration
nsCOMPtr<nsIDOMWindow> window =
do_QueryInterface(content->OwnerDoc()->GetWindow());
if (!window)
return nsnull;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(content));
window->GetComputedStyle(domElement, aPseudoElt, getter_AddRefs(cssDecl));
return cssDecl.forget();
}
already_AddRefed<nsIBoxObject>
nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
{

View File

@ -288,13 +288,6 @@ public:
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
nsAString& aLanguage);
/**
* Return computed styles declaration for the given node.
*/
static already_AddRefed<nsIDOMCSSStyleDeclaration>
GetComputedStyleDeclaration(const nsAString& aPseudoElt,
nsIContent *aContent);
/**
* Return box object for XUL treechildren element by tree box object.
*/

View File

@ -1441,9 +1441,26 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
if (rowElm->IsHTML() && rowElm->Tag() == nsGkAtoms::tr) {
for (nsIContent* cellElm = rowElm->GetFirstChild(); cellElm;
cellElm = cellElm->GetNextSibling()) {
if (cellElm->IsHTML() && cellElm->Tag() == nsGkAtoms::th) {
RETURN_LAYOUT_ANSWER(false,
"Has th -- legitimate table structures");
if (cellElm->IsHTML()) {
if (cellElm->NodeInfo()->Equals(nsGkAtoms::th)) {
RETURN_LAYOUT_ANSWER(false,
"Has th -- legitimate table structures");
}
if (cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::headers) ||
cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::scope) ||
cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::abbr)) {
RETURN_LAYOUT_ANSWER(false,
"Has headers, scope, or abbr attribute -- legitimate table structures");
}
nsAccessible* cell = mDoc->GetAccessible(cellElm);
if (cell && cell->GetChildCount() == 1 &&
cell->FirstChild()->IsAbbreviation()) {
RETURN_LAYOUT_ANSWER(false,
"has abbr -- legitimate table structures");
}
}
}
}

View File

@ -43,6 +43,8 @@
#include "AccessibleComponent_i.c"
#include "nsAccessible.h"
#include "nsCoreUtils.h"
#include "nsWinUtils.h"
#include "States.h"
#include "nsString.h"
@ -156,17 +158,23 @@ __try {
*aColorValue = 0;
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
if (!acc)
if (acc->IsDefunct())
return E_FAIL;
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue;
nsresult rv = acc->GetComputedStyleCSSValue(EmptyString(), aPropName,
getter_AddRefs(cssValue));
if (NS_FAILED(rv) || !cssValue)
return GetHRESULT(rv);
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
nsWinUtils::GetComputedStyleDeclaration(acc->GetContent());
NS_ENSURE_STATE(styleDecl);
nsCOMPtr<nsIDOMCSSValue> cssGenericValue;
styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue));
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue =
do_QueryInterface(cssGenericValue);
if (!cssValue)
return E_FAIL;
nsCOMPtr<nsIDOMRGBColor> rgbColor;
rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
if (NS_FAILED(rv) || !rgbColor)
return GetHRESULT(rv);

View File

@ -339,7 +339,7 @@ __try{
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
nsWinUtils::GetComputedStyleDeclaration(mContent);
NS_ENSURE_TRUE(cssDecl, E_FAIL);
PRUint32 length;
@ -374,7 +374,7 @@ __try {
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
nsWinUtils::GetComputedStyleDeclaration(mContent);
NS_ENSURE_TRUE(cssDecl, E_FAIL);
PRUint32 index;

View File

@ -55,6 +55,25 @@ using namespace mozilla::a11y;
// tab windows.
const PRUnichar* kPropNameTabContent = L"AccessibleTabWindow";
already_AddRefed<nsIDOMCSSStyleDeclaration>
nsWinUtils::GetComputedStyleDeclaration(nsIContent* aContent)
{
nsIContent* elm = nsCoreUtils::GetDOMElementFor(aContent);
if (!elm)
return nsnull;
// Returns number of items in style declaration
nsCOMPtr<nsIDOMWindow> window =
do_QueryInterface(elm->OwnerDoc()->GetWindow());
if (!window)
return nsnull;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(elm));
window->GetComputedStyle(domElement, EmptyString(), getter_AddRefs(cssDecl));
return cssDecl.forget();
}
HRESULT
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
long *aIA2ArrayLen)

View File

@ -52,6 +52,15 @@ const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
class nsWinUtils
{
public:
/**
* Return computed styles declaration for the given node.
*
* @note Please use it carefully since it can shutdown the accessible tree
* you operate on.
*/
static already_AddRefed<nsIDOMCSSStyleDeclaration>
GetComputedStyleDeclaration(nsIContent* aContent);
/**
* Convert nsIArray array of accessible objects to an array of IUnknown*
* objects used in IA2 methods.

View File

@ -311,14 +311,6 @@ nsXULMenuitemAccessible::GetLevelInternal()
return nsAccUtils::GetLevelForXULContainerItem(mContent);
}
void
nsXULMenuitemAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet,
PRInt32 *aSetSize)
{
nsAccUtils::GetPositionAndSizeForXULContainerItem(mContent, aPosInSet,
aSetSize);
}
bool
nsXULMenuitemAccessible::CanHaveAnonChildren()
{

View File

@ -63,8 +63,6 @@ public:
virtual mozilla::a11y::role NativeRole();
virtual PRUint64 NativeState();
virtual PRInt32 GetLevelInternal();
virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
PRInt32 *aSetSize);
virtual bool CanHaveAnonChildren();

View File

@ -101,7 +101,6 @@ _TEST_FILES =\
test_descr.html \
test_nsIAccessibleDocument.html \
test_nsIAccessibleImage.html \
test_nsIAccessNode_utils.html \
test_nsOuterDocAccessible.html \
test_role_nsHyperTextAcc.html \
test_textboxes.html \

View File

@ -139,6 +139,13 @@
testGroupAttrs("h5", 0, 0, 5);
testGroupAttrs("h6", 0, 0, 6);
//////////////////////////////////////////////////////////////////////////
// ARIA combobox
testGroupAttrs("combo1_opt1", 1, 4);
testGroupAttrs("combo1_opt2", 2, 4);
testGroupAttrs("combo1_opt3", 3, 4);
testGroupAttrs("combo1_opt4", 4, 4);
SimpleTest.finish();
}
@ -305,5 +312,12 @@
<h5 id="h5">heading5</h5>
<h6 id="h6">heading6</h6>
<ul id="combo1" role="combobox">Password
<li id="combo1_opt1" role="option">Xyzzy</li>
<li id="combo1_opt2" role="option">Plughs</li>
<li id="combo1_opt3" role="option">Shazaam</li>
<li id="combo1_opt4" role="option">JoeSentMe</li>
</ul>
</body>
</html>

View File

@ -90,6 +90,13 @@
testGroupAttrs("radio1", 1, 2);
testGroupAttrs("radio2", 2, 2);
//////////////////////////////////////////////////////////////////////////
// xul:menulist
testGroupAttrs("menulist1.1", 1);
testGroupAttrs("menulist1.2", 2);
testGroupAttrs("menulist1.3", 3);
testGroupAttrs("menulist1.4", 4);
//////////////////////////////////////////////////////////////////////////
// ARIA menu (bug 441888)
testGroupAttrs("aria-menuitem", 1, 3);
@ -175,6 +182,15 @@
<radio id="radio2" label="radio2"/>
</radiogroup>
<menulist id="menulist1" label="Vehicle">
<menupopup>
<menuitem id="menulist1.1" label="Car"/>
<menuitem id="menulist1.2" label="Taxi"/>
<menuitem id="menulist1.3" label="Bus" selected="true"/>
<menuitem id="menulist1.4" label="Train"/>
</menupopup>
</menulist>
<vbox>
<description role="menuitem" id="aria-menuitem"
value="conventional menuitem"/>

View File

@ -35,21 +35,39 @@
// table with caption
testAbsentAttrs("table4", attr);
// table with empty caption
// layout table with empty caption
testAttrs("table4.2", attr, true);
// table with th element
// table with thead element
testAbsentAttrs("table5", attr);
// table with thead element
testAbsentAttrs("table6", attr);
// table with tfoot element
testAbsentAttrs("table7", attr);
testAbsentAttrs("table5.1", attr);
// table with colgroup or col elements
testAbsentAttrs("table8", attr);
testAbsentAttrs("table8.2", attr);
testAbsentAttrs("table5.2", attr);
testAbsentAttrs("table5.3", attr);
// table with th element
testAbsentAttrs("table6", attr);
// table with headers attribute
testAbsentAttrs("table6.2", attr);
// table with scope attribute
testAbsentAttrs("table6.2.2", attr);
// table with abbr attribute
testAbsentAttrs("table6.2.3", attr);
// table with abbr element
testAbsentAttrs("table6.3", attr);
// table with abbr element having empty text node
testAbsentAttrs("table6.4", attr);
// table with abbr element and non-empty text node
testAttrs("table6.5", attr, true);
// layout table with nested table
testAttrs("table9", attr, true);
@ -125,6 +143,11 @@
title="Expose layout-guess: true object attribute on CSS table accessible">
Mozilla Bug 693948
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=696975"
title="Extend the list of legitimate data table structures">
Mozilla Bug 696975
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -200,7 +223,7 @@
</tr>
</table>
<!-- table with empty caption -->
<!-- layout table with empty caption -->
<table id="table4.2">
<caption> </caption>
<tr>
@ -208,15 +231,8 @@
</tr>
</table>
<!-- table with th element -->
<table id="table5">
<tr>
<th>Cell1</th><th>cell2</th>
</tr>
</table>
<!-- table with thead element -->
<table id="table6">
<table id="table5">
<thead>
<tr>
<td>Cell1</td><td>cell2</td>
@ -225,7 +241,7 @@
</table>
<!-- table with tfoot element -->
<table id="table7">
<table id="table5.1">
<tfoot>
<tr>
<td>Cell1</td><td>cell2</td>
@ -234,19 +250,73 @@
</table>
<!-- table with colgroup and col elements -->
<table id="table8">
<table id="table5.2">
<colgroup width="20"></colgroup>
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
</table>
<table id="table8.2">
<table id="table5.3">
<col width="20">
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
</table>
<!-- table with th element -->
<table id="table6">
<tr>
<th>Cell1</th><th>cell2</th>
</tr>
</table>
<!-- table with headers attribute -->
<table id="table6.2">
<tr>
<td headers="a">table6.2 cell</td>
</tr>
</table>
<!-- table with scope attribute -->
<table id="table6.2.2">
<tr>
<td scope="a">table6.2.2 cell</td>
</tr>
</table>
<!-- table with abbr attribute -->
<table id="table6.2.3">
<tr>
<td abbr="table6.2.3">table6.2.3 cell1</td>
</tr>
</table>
<!-- table with abbr element -->
<table id="table6.3">
<tr>
<td>table6.3 cell1</td>
<td><abbr>table6.3 cell2</abbr></td>
</tr>
</table>
<!-- table with abbr element having empty text node -->
<table id="table6.4">
<tr>
<td>
<abbr>abbr</abbr>
</td>
</tr>
</table>
<!-- table with abbr element and non-empty text node -->
<table id="table6.5">
<tr>
<td>
This is a really long text (<abbr>tiarlt</abbr>) inside layout table
</td>
</tr>
</table>
<!-- layout table with nested table -->
<table id="table9">
<tr>

View File

@ -1,53 +0,0 @@
<html>
<head>
<title>nsIAccessNode util methods testing</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">
function doTest()
{
var elmObj = {};
var acc = getAccessible("span", null, elmObj);
computedStyle = document.defaultView.getComputedStyle(elmObj.value, "");
// html:span element
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
"Wrong color for element with ID 'span'");
// text child of html:span element
acc = getAccessible(acc.firstChild);
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
"Wrong color for text child of element with ID 'span'");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=454211"
title="nsIAccessNode util methods testing">
Mozilla Bug 454211
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<span role="note" style="color: red" id="span">text</span>
</body>
</html>

View File

@ -440,7 +440,8 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
#notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon,
#notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon,
#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon {
#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon,
#notification-popup-box[anchorid="webapps-notification-icon"] > #webapps-notification-icon {
display: -moz-box;
}

View File

@ -4752,10 +4752,15 @@ var XULBrowserWindow = {
}
// Show or hide browser chrome based on the whitelist
if (this.hideChromeForLocation(location))
if (this.hideChromeForLocation(location)) {
document.documentElement.setAttribute("disablechrome", "true");
else
document.documentElement.removeAttribute("disablechrome");
} else {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
if (ss.getTabValue(gBrowser.selectedTab, "appOrigin"))
document.documentElement.setAttribute("disablechrome", "true");
else
document.documentElement.removeAttribute("disablechrome");
}
// Disable find commands in documents that ask for them to be disabled.
let disableFind = false;
@ -9100,7 +9105,6 @@ XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#endif
});
var MousePosTracker = {
_listeners: [],
_x: 0,

View File

@ -527,6 +527,7 @@
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="webapps-notification-icon" class="webapps-anchor-icon" role="button"/>
</box>
<!-- Use onclick instead of normal popup= syntax since the popup
code fires onmousedown, and hence eats our favicon drag events.

View File

@ -98,6 +98,12 @@ source-package::
upload::
@$(MAKE) -C browser/installer upload
source-upload::
@$(MAKE) -C browser/installer source-upload
hg-bundle::
@$(MAKE) -C browser/installer hg-bundle
l10n-check::
@$(MAKE) -C browser/locales l10n-check

View File

@ -67,6 +67,9 @@ XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
"resource:///modules/KeywordURLResetPrompter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
"resource://gre/modules/webappsUI.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -346,6 +349,7 @@ BrowserGlue.prototype = {
if (this._isPlacesShutdownObserver)
os.removeObserver(this, "places-shutdown");
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
webappsUI.uninit();
},
_onAppDefaults: function BG__onAppDefaults() {
@ -370,6 +374,9 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
// Initialize webapps UI
webappsUI.init();
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
},
@ -405,7 +412,6 @@ BrowserGlue.prototype = {
#endif
}
// Show update notification, if needed.
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
this._showUpdateNotification();

View File

@ -887,6 +887,14 @@ function PlacesToolbar(aPlace) {
this._addEventListeners(this._rootElt, ["overflow", "underflow"], true);
this._addEventListeners(window, ["resize", "unload"], false);
// If personal-bookmarks has been dragged to the tabs toolbar,
// we have to track addition and removals of tabs, to properly
// recalculate the available space for bookmarks.
// TODO (bug 734730): Use a performant mutation listener when available.
if (this._viewElt.parentNode.parentNode == document.getElementById("TabsToolbar")) {
this._addEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
}
PlacesViewBase.call(this, aPlace);
Services.telemetry.getHistogramById("FX_BOOKMARKS_TOOLBAR_INIT_MS")
@ -913,6 +921,7 @@ PlacesToolbar.prototype = {
true);
this._removeEventListeners(this._rootElt, ["overflow", "underflow"], true);
this._removeEventListeners(window, ["resize", "unload"], false);
this._removeEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
PlacesViewBase.prototype.uninit.apply(this, arguments);
},
@ -1067,7 +1076,11 @@ PlacesToolbar.prototype = {
if (aEvent.detail == 0)
return;
this.updateChevron();
this._chevron.collapsed = true;
break;
case "TabOpen":
case "TabClose":
this.updateChevron();
break;
case "dragstart":

View File

@ -144,6 +144,7 @@
@BINPATH@/components/directory.xpt
@BINPATH@/components/docshell.xpt
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_apps.xpt
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@ -410,6 +411,8 @@
@BINPATH@/components/TelemetryPing.manifest
@BINPATH@/components/messageWakeupService.js
@BINPATH@/components/messageWakeupService.manifest
@BINPATH@/components/Webapps.js
@BINPATH@/components/Webapps.manifest
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest

View File

@ -334,6 +334,12 @@ telemetryYesButtonAccessKey = Y
telemetryNoButtonLabel = No
telemetryNoButtonAccessKey = N
# Webapps notification popup
webapps.install = Install
webapps.install.accesskey = I
#LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
# Keyword.URL reset prompt
# LOCALIZATION NOTE (keywordPrompt.message):
# - %1$S is brandShortName

View File

@ -53,6 +53,7 @@ EXTRA_JS_MODULES = \
offlineAppCache.jsm \
TelemetryTimestamps.jsm \
KeywordURLResetPrompter.jsm \
webappsUI.jsm \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)

View File

@ -0,0 +1,133 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
let EXPORTED_SYMBOLS = ["webappsUI"];
let Ci = Components.interfaces;
let Cc = Components.classes;
let Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Webapps.jsm");
let webappsUI = {
init: function webappsUI_init() {
Services.obs.addObserver(this, "webapps-ask-install", false);
Services.obs.addObserver(this, "webapps-launch", false);
},
uninit: function webappsUI_uninit() {
Services.obs.removeObserver(this, "webapps-ask-install");
Services.obs.removeObserver(this, "webapps-launch");
},
observe: function webappsUI_observe(aSubject, aTopic, aData) {
let data = JSON.parse(aData);
switch(aTopic) {
case "webapps-ask-install":
let [chromeWin, browser] = this._getBrowserForId(data.oid);
if (chromeWin)
this.doInstall(data, browser, chromeWin);
break;
case "webapps-launch":
DOMApplicationRegistry.getManifestFor(data.origin, (function(aManifest) {
if (!aManifest)
return;
let manifest = new DOMApplicationManifest(aManifest, data.origin);
this.openURL(manifest.fullLaunchPath(), data.origin);
}).bind(this));
break;
}
},
openURL: function(aUrl, aOrigin) {
let browserEnumerator = Services.wm.getEnumerator("navigator:browser");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
// Check each browser instance for our URL
let found = false;
while (!found && browserEnumerator.hasMoreElements()) {
let browserWin = browserEnumerator.getNext();
let tabbrowser = browserWin.gBrowser;
// Check each tab of this browser instance
let numTabs = tabbrowser.tabs.length;
for (let index = 0; index < numTabs; index++) {
let tab = tabbrowser.tabs[index];
let appURL = ss.getTabValue(tab, "appOrigin");
if (appURL == aOrigin) {
// The URL is already opened. Select this tab.
tabbrowser.selectedTab = tab;
browserWin.focus();
found = true;
break;
}
}
}
// Our URL isn't open. Open it now.
if (!found) {
let recentWindow = Services.wm.getMostRecentWindow("navigator:browser");
if (recentWindow) {
// Use an existing browser window
let browser = recentWindow.gBrowser;
let tab = browser.addTab(aUrl);
browser.pinTab(tab);
browser.selectedTab = tab;
ss.setTabValue(tab, "appOrigin", aOrigin);
}
}
},
_getBrowserForId: function(aId) {
let someWindow = Services.wm.getMostRecentWindow(null);
if (someWindow) {
let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let content = windowUtils.getOuterWindowWithId(aId);
if (content) {
let browser = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
let win = browser.ownerDocument.defaultView;
return [win, browser];
}
}
return [null, null];
},
doInstall: function(aData, aBrowser, aWindow) {
let bundle = aWindow.gNavigatorBundle;
let mainAction = {
label: bundle.getString("webapps.install"),
accessKey: bundle.getString("webapps.install.accesskey"),
callback: function(notification) {
installDone = true;
DOMApplicationRegistry.confirmInstall(aData);
}
};
let requestingURI = aWindow.makeURI(aData.from);
let manifest = new DOMApplicationManifest(aData.app.manifest, aData.app.origin);
let host;
try {
host = requestingURI.host;
} catch(e) {
host = requestingURI.spec;
}
let message = bundle.getFormattedString("webapps.requestInstall",
[manifest.name, host], 2);
aWindow.PopupNotifications.show(aBrowser, "webapps-install", message, "webapps-notification-icon",
mainAction, null, { popupIconURL: manifest.iconURLForSize(64) });
}
}

View File

@ -1230,6 +1230,10 @@ toolbar[iconsize="small"] #feed-button {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
/* Notification icon box */
#notification-popup-box {
position: relative;
@ -1284,6 +1288,10 @@ toolbar[iconsize="small"] #feed-button {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
#treecolAutoCompleteImage {
max-width : 36px;
}

View File

@ -145,3 +145,5 @@ browser.jar:
skin/classic/browser/syncQuota.css
skin/classic/browser/syncProgress.css
#endif
skin/classic/browser/webapps-16.png
skin/classic/browser/webapps-64.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -2359,6 +2359,10 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
.popup-notification-icon {
width: 64px;
height: 64px;
@ -2425,6 +2429,10 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
/* Popup Buttons */
#identity-popup-more-info-button {
@hudButton@

View File

@ -191,6 +191,8 @@ browser.jar:
skin/classic/browser/lion/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon-lion.png)
skin/classic/browser/lion/tabview/tabview.png (tabview/tabview-lion.png)
skin/classic/browser/lion/places/toolbar.png (places/toolbar-lion.png)
skin/classic/browser/webapps-16.png
skin/classic/browser/webapps-64.png
% override chrome://browser/skin/keyhole-circle.png chrome://browser/skin/lion/keyhole-circle.png os=Darwin osversion>=10.7
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/lion/Toolbar.png os=Darwin osversion>=10.7

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -2323,6 +2323,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
/* Notification icon box */
#notification-popup-box {
position: relative;
@ -2375,6 +2379,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
#identity-popup-container {
min-width: 280px;
}

View File

@ -21,6 +21,8 @@ browser.jar:
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/webapps-16.png
skin/classic/browser/webapps-64.png
skin/classic/browser/Info.png (Info.png)
skin/classic/browser/identity.png (identity.png)
skin/classic/browser/keyhole-forward-mask.svg
@ -191,6 +193,8 @@ browser.jar:
* skin/classic/aero/browser/engineManager.css (engineManager.css)
skin/classic/aero/browser/Geolocation-16.png
skin/classic/aero/browser/Geolocation-64.png
skin/classic/aero/browser/webapps-16.png
skin/classic/aero/browser/webapps-64.png
skin/classic/aero/browser/Info.png (Info-aero.png)
skin/classic/aero/browser/identity.png (identity-aero.png)
skin/classic/aero/browser/keyhole-forward-mask.svg

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -39,6 +39,9 @@
package @ANDROID_PACKAGE_NAME@;
import java.util.List;
import java.util.ArrayList;
import android.database.Cursor;
public interface Actions {
@ -92,4 +95,9 @@ public interface Actions {
void sendSpecialKey(SpecialKey key);
void drag(int startingX, int endingX, int startingY, int endingY);
/**
* Run a sql query on the specified database
*/
public Cursor querySql(String dbPath, String sql);
}

View File

@ -166,21 +166,13 @@ public class FennecMochitestAssert implements Assert {
}
public void is(Object a, Object b, String name) {
boolean pass = a.equals(b);
String diag = "got " + a.toString() + ", expected " + b.toString();
if (pass) {
diag = a.toString() + " should equal " + b.toString();
}
ok(pass, name, diag);
boolean pass = checkObjectsEqual(a,b);
ok(pass, name, getEqualString(a,b, pass));
}
public void isnot(Object a, Object b, String name) {
boolean pass = !a.equals(b);
String diag = "didn't expect " + a.toString() + ", but got it";
if (pass) {
diag = a.toString() + " should not equal " + b.toString();
}
ok(pass, name, diag);
boolean pass = checkObjectsNotEqual(a,b);
ok(pass, name, getNotEqualString(a,b,pass));
}
public void ispixel(int actual, int r, int g, int b, String name) {
@ -207,21 +199,50 @@ public class FennecMochitestAssert implements Assert {
}
public void todo_is(Object a, Object b, String name) {
boolean pass = a.equals(b);
String diag = "got " + a.toString() + ", expected " + b.toString();
if (pass) {
diag = a.toString() + " should equal " + b.toString();
}
todo(pass, name, diag);
boolean pass = checkObjectsEqual(a,b);
todo(pass, name, getEqualString(a,b,pass));
}
public void todo_isnot(Object a, Object b, String name) {
boolean pass = !a.equals(b);
String diag = "didn't expect " + a.toString() + ", but got it";
if (pass) {
diag = a.toString() + " should not equal " + b.toString();
boolean pass = checkObjectsNotEqual(a,b);
todo(pass, name, getNotEqualString(a,b,pass));
}
private boolean checkObjectsEqual(Object a, Object b) {
if (a == null || b == null) {
if (a == null && b == null) {
return true;
}
return false;
} else {
return a.equals(b);
}
todo(pass, name, diag);
}
private String getEqualString(Object a, Object b, boolean pass) {
if (pass) {
return a + " should equal " + b;
}
return "got " + a + ", expected " + b;
}
private boolean checkObjectsNotEqual(Object a, Object b) {
if (a == null || b == null) {
if ((a == null && b != null) || (a != null && b == null)) {
return true;
} else {
return false;
}
} else {
return !a.equals(b);
}
}
private String getNotEqualString(Object a, Object b, boolean pass) {
if(pass) {
return a + " should not equal " + b;
}
return "didn't expect " + a + ", but got it";
}
public void info(String name, String message) {

View File

@ -40,19 +40,24 @@
package @ANDROID_PACKAGE_NAME@;
import java.lang.Class;
import java.lang.ClassLoader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.Long;
import java.util.concurrent.SynchronousQueue;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.app.Instrumentation;
import android.database.Cursor;
import android.os.SystemClock;
import android.view.View;
import android.view.KeyEvent;
import java.util.concurrent.SynchronousQueue;
import android.util.Log;
import org.json.*;
@ -74,6 +79,7 @@ public class FennecNativeActions implements Actions {
private Method mSendGE;
private Method mGetLayerClient;
private Method mSetDrawListener;
private static final String LOGTAG = "FennecNativeActions";
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation) {
mSolo = robocop;
@ -349,4 +355,36 @@ public class FennecNativeActions implements Actions {
public void drag(int startingX, int endingX, int startingY, int endingY) {
mSolo.drag(startingX, endingX, startingY, endingY, 10);
}
public Cursor querySql(String dbPath, String sql) {
try {
ClassLoader classLoader = mGeckoApp.getClassLoader();
Class sqlClass = classLoader.loadClass("org.mozilla.gecko.sqlite.SQLiteBridge");
Class stringClass = String.class;
Class stringArrayClass = String[].class;
Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class contextClass = Context.class;
Constructor bridgeConstructor = sqlClass.getConstructor(stringClass);
Method query = sqlClass.getMethod("rawQuery", stringClass, stringArrayClass);
Method loadSQLiteLibs = appshell.getMethod("loadSQLiteLibs", contextClass, stringClass);
Object bridge = bridgeConstructor.newInstance(dbPath);
String resourcePath = mGeckoApp.getApplication().getPackageResourcePath();
loadSQLiteLibs.invoke(null, mGeckoApp, resourcePath);
return (Cursor)query.invoke(bridge, sql, null);
} catch(ClassNotFoundException ex) {
Log.e(LOGTAG, "Error getting class", ex);
} catch(NoSuchMethodException ex) {
Log.e(LOGTAG, "Error getting method", ex);
} catch(InvocationTargetException ex) {
Log.e(LOGTAG, "Error invoking method", ex);
} catch(InstantiationException ex) {
Log.e(LOGTAG, "Error calling constructor", ex);
} catch(IllegalAccessException ex) {
Log.e(LOGTAG, "Error using field", ex);
}
return null;
}
}

View File

@ -60,6 +60,7 @@
#include "nsPrincipal.h"
#include "mozilla/Preferences.h"
#include "mozilla/HashFunctions.h"
using namespace mozilla;
@ -801,7 +802,7 @@ nsPrincipal::GetHashValue(PRUint32* aValue)
// If there is a certificate, it takes precendence over the codebase.
if (mCert) {
*aValue = nsCRT::HashCode(mCert->fingerprint.get());
*aValue = HashString(mCert->fingerprint);
}
else {
*aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);

View File

@ -175,11 +175,14 @@ enum {
// Set if the node is handling a click.
NODE_HANDLING_CLICK = 0x00040000U,
// Set if the node has had :hover selectors matched against it
NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U,
// Two bits for the script-type ID. Not enough to represent all
// nsIProgrammingLanguage values, but we don't care. In practice,
// we can represent the ones we want, and we can fail the others at
// runtime.
NODE_SCRIPT_TYPE_OFFSET = 19,
NODE_SCRIPT_TYPE_OFFSET = 20,
NODE_SCRIPT_TYPE_SIZE = 2,

View File

@ -129,4 +129,10 @@ interface nsIObjectLoadingContent : nsISupports
[noscript] void syncStartPluginInstance();
[noscript] void asyncStartPluginInstance();
/**
* The URL of the data/src loaded in the object. This may be null (i.e.
* an <embed> with no src).
*/
readonly attribute nsIURI srcURI;
};

View File

@ -51,10 +51,9 @@
#include "nsContentUtils.h"
#include "nsReadableUtils.h"
#include "prprf.h"
#include "mozilla/HashFunctions.h"
namespace css = mozilla::css;
using mozilla::SVGAttrValueWrapper;
using namespace mozilla;
#define MISC_STR_PTR(_cont) \
reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
@ -392,7 +391,7 @@ nsAttrValue::SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized)
}
void
nsAttrValue::SetTo(const mozilla::SVGLengthList& aValue,
nsAttrValue::SetTo(const SVGLengthList& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as a length list, there's no need to store
@ -404,7 +403,7 @@ nsAttrValue::SetTo(const mozilla::SVGLengthList& aValue,
}
void
nsAttrValue::SetTo(const mozilla::SVGNumberList& aValue,
nsAttrValue::SetTo(const SVGNumberList& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as a number list, there's no need to store
@ -422,7 +421,7 @@ nsAttrValue::SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized)
}
void
nsAttrValue::SetTo(const mozilla::SVGPathData& aValue,
nsAttrValue::SetTo(const SVGPathData& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as path data, there's no need to store it
@ -434,7 +433,7 @@ nsAttrValue::SetTo(const mozilla::SVGPathData& aValue,
}
void
nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
nsAttrValue::SetTo(const SVGPointList& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as a point list, there's no need to store
@ -446,14 +445,14 @@ nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
}
void
nsAttrValue::SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
nsAttrValue::SetTo(const SVGAnimatedPreserveAspectRatio& aValue,
const nsAString* aSerialized)
{
SetSVGType(eSVGPreserveAspectRatio, &aValue, aSerialized);
}
void
nsAttrValue::SetTo(const mozilla::SVGStringList& aValue,
nsAttrValue::SetTo(const SVGStringList& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as a string list, there's no need to store
@ -465,7 +464,7 @@ nsAttrValue::SetTo(const mozilla::SVGStringList& aValue,
}
void
nsAttrValue::SetTo(const mozilla::SVGTransformList& aValue,
nsAttrValue::SetTo(const SVGTransformList& aValue,
const nsAString* aSerialized)
{
// While an empty string will parse as a transform list, there's no need to
@ -764,7 +763,7 @@ nsAttrValue::HashValue() const
nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
if (str) {
PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1;
return nsCRT::HashCode(static_cast<PRUnichar*>(str->Data()), len);
return HashString(static_cast<PRUnichar*>(str->Data()), len);
}
return 0;
@ -812,14 +811,14 @@ nsAttrValue::HashValue() const
}
case eAtomArray:
{
PRUint32 retval = 0;
PRUint32 hash = 0;
PRUint32 count = cont->mAtomArray->Length();
for (nsCOMPtr<nsIAtom> *cur = cont->mAtomArray->Elements(),
*end = cur + count;
cur != end; ++cur) {
retval ^= NS_PTR_TO_INT32(cur->get());
hash = AddToHash(hash, cur->get());
}
return retval;
return hash;
}
case eDoubleValue:
{

View File

@ -55,8 +55,8 @@
#include "nsINameSpaceManager.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsCRT.h"
#include "nsHashKeys.h"
#include "mozilla/HashFunctions.h"
// Magic namespace id that means "match all namespaces". This is
// negative so it won't collide with actual namespace constants.
@ -204,10 +204,8 @@ struct nsContentListKey
inline PRUint32 GetHash(void) const
{
return
HashString(mTagname) ^
(NS_PTR_TO_INT32(mRootNode) << 12) ^
(mMatchNameSpaceId << 24);
PRUint32 hash = mozilla::HashString(mTagname);
return mozilla::AddToHash(hash, mRootNode, mMatchNameSpaceId);
}
nsINode* const mRootNode; // Weak ref
@ -490,8 +488,8 @@ public:
PRUint32 GetHash(void) const
{
return NS_PTR_TO_INT32(mRootNode) ^ (NS_PTR_TO_INT32(mFunc) << 12) ^
nsCRT::HashCode(mString.BeginReading(), mString.Length());
PRUint32 hash = mozilla::HashString(mString);
return mozilla::AddToHash(hash, mRootNode, mFunc);
}
private:

View File

@ -112,8 +112,7 @@ public:
if (!aKey)
return 0;
return PR_ROTATE_LEFT32(static_cast<PRUint32>(aKey->mNamespaceID), 4) ^
NS_PTR_TO_INT32(aKey->mLocalName);
return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName);
}
enum { ALLOW_MEMMOVE = true };

View File

@ -238,8 +238,7 @@ public:
static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey)
{
return (NS_PTR_TO_INT32(aKey->mCallback) >> 2) ^
(NS_PTR_TO_INT32(aKey->mData));
return mozilla::HashGeneric(aKey->mCallback, aKey->mData);
}
enum { ALLOW_MEMMOVE = true };

View File

@ -1934,6 +1934,13 @@ GK_ATOM(VolumeUp, "VolumeUp")
GK_ATOM(VolumeDown, "VolumeDown")
GK_ATOM(Menu, "Menu")
// Smooth scroll profiles
GK_ATOM(pixels, "pixels")
GK_ATOM(lines, "lines")
GK_ATOM(pages, "pages")
GK_ATOM(scrollbars, "scrollbars")
GK_ATOM(other, "other")
#ifdef ACCESSIBILITY
GK_ATOM(anonid, "anonid")
GK_ATOM(aria_activedescendant, "aria-activedescendant")

View File

@ -45,6 +45,9 @@
#include "nsHTMLStyleSheet.h"
#include "nsRuleWalker.h"
#include "prmem.h"
#include "mozilla/HashFunctions.h"
using namespace mozilla;
nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
nsMapRuleToAttributesFunc aMapRuleFunc)
@ -176,14 +179,16 @@ nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const
PRUint32
nsMappedAttributes::HashValue() const
{
PRUint32 value = NS_PTR_TO_INT32(mRuleMapper);
PRUint32 hash = HashGeneric(mRuleMapper);
PRUint32 i;
for (i = 0; i < mAttrCount; ++i) {
value ^= Attrs()[i].mName.HashValue() ^ Attrs()[i].mValue.HashValue();
hash = AddToHash(hash,
Attrs()[i].mName.HashValue(),
Attrs()[i].mValue.HashValue());
}
return value;
return hash;
}
void

View File

@ -57,6 +57,7 @@
static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#endif
using namespace mozilla;
using namespace mozilla::dom;
#define kXMLNSNameSpaceURI "http://www.w3.org/2000/xmlns/"

View File

@ -56,6 +56,8 @@
#include "nsHashKeys.h"
#include "nsCCUncollectableMarker.h"
using namespace mozilla;
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
#define FORCE_PR_LOG 1
@ -75,6 +77,9 @@ nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key);
if (node->mName) {
// Ideally, we'd return node->mName->hash() here. But that doesn't work at
// the moment because node->mName->hash() is not the same as
// HashString(*(node->mNameString)). See bug 732815.
return HashString(nsDependentAtomString(node->mName));
}
return HashString(*(node->mNameString));

View File

@ -2070,6 +2070,13 @@ nsObjectLoadingContent::AsyncStartPluginInstance()
return rv;
}
NS_IMETHODIMP
nsObjectLoadingContent::GetSrcURI(nsIURI** aURI)
{
NS_IF_ADDREF(*aURI = mURI);
return NS_OK;
}
static bool
DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop)
{

View File

@ -1562,17 +1562,12 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal,
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
JSContext* cx = nsnull;
if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
if (fp) {
JSScript *script = JS_GetFrameScript(cx, fp);
if (script) {
mScriptFile = JS_GetScriptFilename(cx, script);
}
unsigned lineno;
JSScript *script;
jsbytecode *pc = JS_GetFramePC(cx, fp);
if (script && pc) {
mScriptLine = JS_PCToLineNumber(cx, script, pc);
}
if (JS_DescribeScriptedCaller(cx, &script, &lineno)) {
mScriptFile = JS_GetScriptFilename(cx, script);
mScriptLine = lineno;
}
mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);

View File

@ -26,6 +26,34 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=525816
<script class="testbody"
type="text/javascript"
src="test_XHR_timeout.js"></script>
<script type="text/javascript">
window.addEventListener("message", function (event) {
if (event.data == "done") {
SimpleTest.finish();
return;
}
if (event.data == "start") {
return;
}
if (event.data.type == "is") {
SimpleTest.is(event.data.got, event.data.expected, event.data.msg);
return;
}
if (event.data.type == "ok") {
SimpleTest.ok(event.data.bool, event.data.msg);
return;
}
});
// Final test harness setup and launch.
(function() {
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(TestRequests.length);
var msg = "This test will take approximately " + (TestRequests.length * 10)
msg += " seconds to complete, at most.";
document.getElementById("content").firstChild.nodeValue = msg;
window.postMessage("start", "*");
})();
</script>
</pre>
</body>
</html>

View File

@ -5,6 +5,32 @@
request handlers.
*/
var inWorker = false;
try {
inWorker = !(self instanceof Window);
} catch (e) {
inWorker = true;
}
function is(got, expected, msg) {
var obj = {};
obj.type = "is";
obj.got = got;
obj.expected = expected;
obj.msg = msg;
self.postMessage(obj, "*");
}
function ok(bool, msg) {
var obj = {};
obj.type = "ok";
obj.bool = bool;
obj.msg = msg;
self.postMessage(obj, "*");
}
/**
* Generate and track results from a XMLHttpRequest with regards to timeouts.
*
@ -23,14 +49,15 @@
* @constructor
* @implements DOMEventListener
*/
function RequestTracker(id, timeLimit /*[, resetAfter, resetTo]*/) {
function RequestTracker(async, id, timeLimit /*[, resetAfter, resetTo]*/) {
this.async = async;
this.id = id;
this.timeLimit = timeLimit;
if (arguments.length > 2) {
if (arguments.length > 3) {
this.mustReset = true;
this.resetAfter = arguments[2];
this.resetTo = arguments[3];
this.resetAfter = arguments[3];
this.resetTo = arguments[4];
}
this.hasFired = false;
@ -42,7 +69,7 @@ RequestTracker.prototype = {
startXHR: function() {
var req = new XMLHttpRequest();
this.request = req;
req.open("GET", "file_XHR_timeout.sjs");
req.open("GET", "file_XHR_timeout.sjs", this.async);
req.onerror = this;
req.onload = this;
req.onabort = this;
@ -52,7 +79,7 @@ RequestTracker.prototype = {
if (this.mustReset) {
var resetTo = this.resetTo;
window.setTimeout(function() {
self.setTimeout(function() {
req.timeout = resetTo;
}, this.resetAfter);
}
@ -137,7 +164,7 @@ AbortedRequest.prototype = {
}
if (!this.shouldAbort) {
window.setTimeout(function() {
self.setTimeout(function() {
try {
_this.noEventsFired();
}
@ -154,7 +181,7 @@ AbortedRequest.prototype = {
abortReq();
}
else {
window.setTimeout(abortReq, this.abortDelay);
self.setTimeout(abortReq, this.abortDelay);
}
}
},
@ -229,22 +256,22 @@ var SyncRequestSettingTimeoutBeforeOpen = {
var TestRequests = [
// Simple timeouts.
new RequestTracker("no time out scheduled, load fires normally", 0),
new RequestTracker("load fires normally", 5000),
new RequestTracker("timeout hit before load", 2000),
new RequestTracker(true, "no time out scheduled, load fires normally", 0),
new RequestTracker(true, "load fires normally", 5000),
new RequestTracker(true, "timeout hit before load", 2000),
// Timeouts reset after a certain delay.
new RequestTracker("load fires normally with no timeout set, twice", 0, 2000, 0),
new RequestTracker("load fires normally with same timeout set twice", 5000, 2000, 5000),
new RequestTracker("timeout fires normally with same timeout set twice", 2000, 1000, 2000),
new RequestTracker(true, "load fires normally with no timeout set, twice", 0, 2000, 0),
new RequestTracker(true, "load fires normally with same timeout set twice", 5000, 2000, 5000),
new RequestTracker(true, "timeout fires normally with same timeout set twice", 2000, 1000, 2000),
new RequestTracker("timeout disabled after initially set", 5000, 2000, 0),
new RequestTracker("timeout overrides load after a delay", 5000, 1000, 2000),
new RequestTracker("timeout enabled after initially disabled", 0, 2000, 5000),
new RequestTracker(true, "timeout disabled after initially set", 5000, 2000, 0),
new RequestTracker(true, "timeout overrides load after a delay", 5000, 1000, 2000),
new RequestTracker(true, "timeout enabled after initially disabled", 0, 2000, 5000),
new RequestTracker("timeout set to expiring value after load fires", 5000, 4000, 1000),
new RequestTracker("timeout set to expired value before load fires", 5000, 2000, 1000),
new RequestTracker("timeout set to non-expiring value after timeout fires", 1000, 2000, 5000),
new RequestTracker(true, "timeout set to expiring value after load fires", 5000, 4000, 1000),
new RequestTracker(true, "timeout set to expired value before load fires", 5000, 2000, 1000),
new RequestTracker(true, "timeout set to non-expiring value after timeout fires", 1000, 2000, 5000),
// Aborted requests.
new AbortedRequest(false),
@ -252,17 +279,34 @@ var TestRequests = [
new AbortedRequest(true, 0),
new AbortedRequest(true, 1000),
new AbortedRequest(true, 5000),
];
var MainThreadTestRequests = [
// Synchronous requests.
SyncRequestSettingTimeoutAfterOpen,
SyncRequestSettingTimeoutBeforeOpen
];
var WorkerThreadTestRequests = [
// Simple timeouts.
new RequestTracker(false, "no time out scheduled, load fires normally", 0),
new RequestTracker(false, "load fires normally", 5000),
new RequestTracker(false, "timeout hit before load", 2000),
// Reset timeouts don't make much sense with a sync request ...
];
if (inWorker) {
TestRequests = TestRequests.concat(WorkerThreadTestRequests);
} else {
TestRequests = TestRequests.concat(MainThreadTestRequests);
}
// This code controls moving from one test to another.
var TestCounter = {
testComplete: function() {
// Allow for the possibility there are other events coming.
window.setTimeout(function() {
self.setTimeout(function() {
TestCounter.next();
}, 5000);
},
@ -274,17 +318,13 @@ var TestCounter = {
test.startXHR();
}
else {
SimpleTest.finish();
self.postMessage("done", "*");
}
}
};
// Final test harness setup and launch.
(function() {
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(TestRequests.length);
var msg = "This test will take approximately " + (TestRequests.length * 10)
msg += " seconds to complete, at most.";
document.getElementById("content").firstChild.nodeValue = msg;
TestCounter.next();
})();
self.addEventListener("message", function (event) {
if (event.data == "start") {
TestCounter.next();
}
});

View File

@ -102,7 +102,7 @@ public:
static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
static PLDHashNumber HashKey(KeyTypePointer key)
{
return (NS_PTR_TO_INT32(key->mImage) ^ NS_PTR_TO_INT32(key->mCanvas)) >> 2;
return HashGeneric(key->mImage, key->mCanvas);
}
enum { ALLOW_MEMMOVE = true };

View File

@ -49,7 +49,6 @@
#include "nsIURI.h"
#include "nsIWeakReferenceUtils.h"
#include "nsPIDOMWindow.h"
#include "nsUnicharUtils.h"
#include "nsThreadUtils.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
@ -57,39 +56,6 @@
class nsFormControlList;
class nsIMutableArray;
/**
* hashkey wrapper using nsAString KeyType
*
* @see nsTHashtable::EntryType for specification
*/
class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
{
public:
typedef const nsAString& KeyType;
typedef const nsAString* KeyTypePointer;
nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
~nsStringCaseInsensitiveHashKey() { }
KeyType GetKey() const { return mStr; }
bool KeyEquals(const KeyTypePointer aKey) const
{
return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
}
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(const KeyTypePointer aKey)
{
nsAutoString tmKey(*aKey);
ToLowerCase(tmKey);
return HashString(tmKey);
}
enum { ALLOW_MEMMOVE = true };
private:
const nsString mStr;
};
class nsHTMLFormElement : public nsGenericHTMLElement,
public nsIDOMHTMLFormElement,
public nsIWebProgressListener,

View File

@ -44,6 +44,9 @@
#include "txKey.h"
#include "txXSLTPatterns.h"
#include "txNamespaceMap.h"
#include "mozilla/HashFunctions.h"
using namespace mozilla;
/*
* txKeyFunctionCall
@ -163,10 +166,13 @@ txKeyValueHashEntry::KeyEquals(KeyTypePointer aKey) const
PLDHashNumber
txKeyValueHashEntry::HashKey(KeyTypePointer aKey)
{
return aKey->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier ^
HashString(aKey->mKeyValue);
const txKeyValueHashKey* key =
static_cast<const txKeyValueHashKey*>(aKey);
return AddToHash(HashString(key->mKeyValue),
key->mKeyName.mNamespaceID,
key->mRootIdentifier,
key->mKeyName.mLocalName.get());
}
bool
@ -179,9 +185,11 @@ txIndexedKeyHashEntry::KeyEquals(KeyTypePointer aKey) const
PLDHashNumber
txIndexedKeyHashEntry::HashKey(KeyTypePointer aKey)
{
return aKey->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier;
const txIndexedKeyHashKey* key =
static_cast<const txIndexedKeyHashKey*>(aKey);
return HashGeneric(key->mKeyName.mNamespaceID,
key->mRootIdentifier,
key->mKeyName.mLocalName.get());
}
/*

View File

@ -109,9 +109,8 @@ public:
return "nsRDFConInstanceTestNode::Element"; }
virtual PLHashNumber Hash() const {
return (PLHashNumber(NS_PTR_TO_INT32(mContainer.get())) >> 4) ^
PLHashNumber(mContainerTest) ^
(PLHashNumber(mEmptyTest) << 4); }
return mozilla::HashGeneric(mContainerTest, mEmptyTest, mContainer.get());
}
virtual bool Equals(const MemoryElement& aElement) const {
if (aElement.Type() == Type()) {

View File

@ -124,9 +124,8 @@ public:
return "nsRDFPropertyTestNode::Element"; }
virtual PLHashNumber Hash() const {
return PLHashNumber(NS_PTR_TO_INT32(mSource.get())) ^
(PLHashNumber(NS_PTR_TO_INT32(mProperty.get())) >> 4) ^
(PLHashNumber(NS_PTR_TO_INT32(mTarget.get())) >> 12); }
return mozilla::HashGeneric(mSource.get(), mProperty.get(), mTarget.get());
}
virtual bool Equals(const MemoryElement& aElement) const {
if (aElement.Type() == Type()) {

View File

@ -69,11 +69,9 @@ DIRS = \
interfaces/smil \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
DIRS += \
interfaces/apps \
$(NULL)
endif
DIRS += \
base \

View File

@ -59,7 +59,6 @@ EXTRA_PP_COMPONENTS = \
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
EXTRA_COMPONENTS = \
Webapps.js \
Webapps.manifest \
@ -67,7 +66,6 @@ EXTRA_COMPONENTS = \
EXTRA_JS_MODULES += Webapps.jsm \
$(NULL)
endif
EXTRA_JS_MODULES += DOMRequestHelper.jsm \
$(NULL)

View File

@ -26,14 +26,16 @@ let DOMApplicationRegistry = {
webapps: { },
init: function() {
let messages = ["Webapps:Install", "Webapps:Uninstall",
this.messages = ["Webapps:Install", "Webapps:Uninstall",
"Webapps:GetSelf", "Webapps:GetInstalled",
"Webapps:Launch", "Webapps:GetAll"];
messages.forEach((function(msgName) {
this.messages.forEach((function(msgName) {
ppmm.addMessageListener(msgName, this);
}).bind(this));
Services.obs.addObserver(this, "xpcom-shutdown", false);
let appsDir = FileUtils.getDir("ProfD", ["webapps"], true, true);
this.appsFile = FileUtils.getFile("ProfD", ["webapps", "webapps.json"], true);
@ -51,6 +53,16 @@ let DOMApplicationRegistry = {
} catch(e) { }
},
observe: function(aSubject, aTopic, aData) {
if (aTopic == "xpcom-shutdown") {
this.messages.forEach((function(msgName) {
ppmm.removeMessageListener(msgName, this);
}).bind(this));
Services.obs.removeObserver(this, "xpcom-shutdown");
ppmm = null;
}
},
_loadJSONAsync: function(aFile, aCallback) {
try {
let channel = NetUtil.newChannel(aFile);

View File

@ -125,10 +125,6 @@ static PRLogModuleInfo* gJSDiagnostics;
#undef CompareString
#endif
// The amount of time we wait between a request to GC (due to leaving
// a page) and doing the actual GC.
#define NS_GC_DELAY 4000 // ms
#define NS_SHRINK_GC_BUFFERS_DELAY 4000 // ms
// The amount of time we wait from the first request to GC to actually
@ -739,8 +735,11 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
NS_ENSURE_TRUE(prompt, JS_FALSE);
// Check if we should offer the option to debug
JSStackFrame* fp = ::JS_GetScriptedCaller(cx, NULL);
bool debugPossible = fp && js::CanCallContextDebugHandler(cx);
JSScript *script;
unsigned lineno;
JSBool hasFrame = ::JS_DescribeScriptedCaller(cx, &script, &lineno);
bool debugPossible = hasFrame && js::CanCallContextDebugHandler(cx);
#ifdef MOZ_JSDEBUGGER
// Get the debugger service if necessary.
if (debugPossible) {
@ -805,7 +804,6 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
}
// Append file and line number information, if available
JSScript *script = fp ? ::JS_GetFrameScript(cx, fp) : nsnull;
if (script) {
const char *filename = ::JS_GetScriptFilename(cx, script);
if (filename) {
@ -820,17 +818,8 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
if (NS_SUCCEEDED(rv) && scriptLocation) {
msg.AppendLiteral("\n\n");
msg.Append(scriptLocation);
JSStackFrame *fp, *iterator = nsnull;
fp = ::JS_FrameIterator(cx, &iterator);
if (fp) {
jsbytecode *pc = ::JS_GetFramePC(cx, fp);
if (pc) {
PRUint32 lineno = ::JS_PCToLineNumber(cx, script, pc);
msg.Append(':');
msg.AppendInt(lineno);
}
}
msg.Append(':');
msg.AppendInt(lineno);
}
}
}
@ -867,22 +856,7 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
return JS_TRUE;
}
else if ((buttonPressed == 2) && debugPossible) {
// Debug the script
jsval rval;
switch (js::CallContextDebugHandler(cx, script, JS_GetFramePC(cx, fp), &rval)) {
case JSTRAP_RETURN:
JS_SetFrameReturnValue(cx, fp, rval);
return JS_TRUE;
case JSTRAP_ERROR:
JS_ClearPendingException(cx);
return JS_FALSE;
case JSTRAP_THROW:
JS_SetPendingException(cx, rval);
return JS_FALSE;
case JSTRAP_CONTINUE:
default:
return JS_TRUE;
}
return js_CallContextDebugHandler(cx);
}
JS_ClearPendingException(cx);

View File

@ -56,6 +56,10 @@ namespace mozilla {
template <class> class Maybe;
}
// The amount of time we wait between a request to GC (due to leaving
// a page) and doing the actual GC.
#define NS_GC_DELAY 4000 // ms
class nsJSContext : public nsIScriptContext,
public nsIXPCScriptNotify
{

View File

@ -60,6 +60,8 @@
#define NS_INTERFACE_PREFIX "nsI"
#define NS_DOM_INTERFACE_PREFIX "nsIDOM"
using namespace mozilla;
// Our extended PLDHashEntryHdr
class GlobalNameMapEntry : public PLDHashEntryHdr
{
@ -74,7 +76,6 @@ static PLDHashNumber
GlobalNameHashHashKey(PLDHashTable *table, const void *key)
{
const nsAString *str = static_cast<const nsAString *>(key);
return HashString(*str);
}

View File

@ -51,6 +51,7 @@
#include "IDBFactory.h"
#include "IndexedDatabaseManager.h"
using namespace mozilla;
USING_INDEXEDDB_NAMESPACE
namespace {

View File

@ -56,10 +56,12 @@
#include "prmem.h"
#include "nsIContent.h"
#include "nsIPluginInstanceOwner.h"
#include "mozilla/HashFunctions.h"
#define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
using namespace mozilla::plugins::parent;
using namespace mozilla;
#include "mozilla/plugins/PluginScriptableObjectParent.h"
using mozilla::plugins::PluginScriptableObjectParent;
@ -1022,8 +1024,7 @@ static PLDHashNumber
JSObjWrapperHash(PLDHashTable *table, const void *key)
{
const nsJSObjWrapperKey *e = static_cast<const nsJSObjWrapperKey *>(key);
return (PLDHashNumber)((PRWord)e->mJSObj ^ (PRWord)e->mNpp) >> 2;
return HashGeneric(e->mJSObj, e->mNpp);
}
static bool

View File

@ -491,13 +491,6 @@ nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window)
return NS_OK;
}
nsresult
nsNPAPIPluginInstance::NewStreamToPlugin(nsIPluginStreamListener** listener)
{
// This method can be removed at the next opportunity.
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsNPAPIPluginInstance::NewStreamFromPlugin(const char* type, const char* target,
nsIOutputStream* *result)
@ -648,18 +641,6 @@ nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP)
return NS_OK;
}
void
nsNPAPIPluginInstance::SetURI(nsIURI* uri)
{
mURI = uri;
}
nsIURI*
nsNPAPIPluginInstance::GetURI()
{
return mURI.get();
}
NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless)
{
mWindowless = aWindowless;

View File

@ -98,7 +98,6 @@ public:
nsresult Start();
nsresult Stop();
nsresult SetWindow(NPWindow* window);
nsresult NewStreamToPlugin(nsIPluginStreamListener** listener);
nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result);
nsresult Print(NPPrint* platformPrint);
#ifdef MOZ_WIDGET_ANDROID
@ -141,9 +140,6 @@ public:
nsresult GetNPP(NPP * aNPP);
void SetURI(nsIURI* uri);
nsIURI* GetURI();
NPError SetWindowless(bool aWindowless);
NPError SetTransparent(bool aTransparent);
@ -301,8 +297,6 @@ private:
// This is only valid when the plugin is actually stopped!
mozilla::TimeStamp mStopTime;
nsCOMPtr<nsIURI> mURI;
bool mUsePluginLayersPref;
#ifdef MOZ_WIDGET_ANDROID
void* mSurface;

View File

@ -3119,7 +3119,17 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
// Only set the Referer header for GET requests because IIS throws
// errors about malformed requests if we include it in POSTs. See
// bug 724465.
rv = httpChannel->SetReferrer(doc->GetDocumentURI());
nsCOMPtr<nsIURI> referer;
nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(element);
if (olc)
olc->GetSrcURI(getter_AddRefs(referer));
if (!referer)
referer = doc->GetDocumentURI();
rv = httpChannel->SetReferrer(referer);
NS_ENSURE_SUCCESS(rv,rv);
}

View File

@ -9,11 +9,12 @@
<p id="display"></p>
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
<embed id="plugin2" type="application/x-test" src="loremipsum.xtest" width="200" height="200"></embed>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var pending = 2;
var pending = 3;
function testDone() {
--pending;
if (0 == pending)
@ -22,6 +23,7 @@
function runTests() {
var p = document.getElementById('plugin1');
var p2 = document.getElementById('plugin2');
ok(p.streamTest('plugin-stream-referer.sjs', false, null, null,
function(r, t) {
@ -37,6 +39,16 @@
is(t, "No Referer found", "POST Referer absent");
testDone();
}, null, true), "referer POST");
ok(p2.streamTest('plugin-stream-referer.sjs', false, null, null,
function(r, t) {
is(r, 0, "GET plugin-stream-referer.sjs (2)");
var expectedreferer = String(window.location).replace("test_pluginstream_referer.html", "loremipsum.xtest");
is(t, "Referer found: " + expectedreferer,
"GET Referer correct with plugin src");
testDone();
}, null, true), "referer GET (2)");
}
</script>

View File

@ -45,7 +45,7 @@
interface nsIDOMMozSmsFilter;
[scriptable, uuid(86b3b538-359d-40b0-acdf-8dfd698ff117)]
[scriptable, uuid(74d6ff05-818a-4179-a745-6258e1c3cd08)]
interface nsISmsDatabaseService : nsISupports
{
// Takes some information required to save the message and returns its id.
@ -57,6 +57,6 @@ interface nsISmsDatabaseService : nsISupports
void deleteMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
void createMessageList(in nsIDOMMozSmsFilter filter, in boolean reverse, in long requestId, [optional] in unsigned long long processId);
void getNextMessageInList(in long listId, in long requestId, in unsigned long long processId);
void getNextMessageInList(in long listId, in long requestId, [optional] in unsigned long long processId);
void clearMessageList(in long listId);
};

View File

@ -435,6 +435,8 @@ ListenerManager::DispatchEvent(JSContext* aCx, JSObject* aTarget,
static const char sHandleEventChars[] = "handleEvent";
JSObject* thisObj = aTarget;
JSBool hasHandleEvent;
if (!JS_HasProperty(aCx, listenerObj, sHandleEventChars, &hasHandleEvent)) {
if (!JS_ReportPendingException(aCx)) {
@ -450,11 +452,13 @@ ListenerManager::DispatchEvent(JSContext* aCx, JSObject* aTarget,
}
continue;
}
thisObj = listenerObj;
}
jsval argv[] = { OBJECT_TO_JSVAL(aEvent) };
jsval rval = JSVAL_VOID;
if (!JS_CallFunctionValue(aCx, aTarget, listenerVal, ArrayLength(argv),
if (!JS_CallFunctionValue(aCx, thisObj, listenerVal, ArrayLength(argv),
argv, &rval)) {
if (!JS_ReportPendingException(aCx)) {
return false;

View File

@ -2528,13 +2528,8 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
// We're being created outside of a window. Need to figure out the script
// that is creating us in order for us to use relative URIs later on.
JSStackFrame* frame = JS_GetScriptedCaller(aCx, nsnull);
if (frame) {
JSScript* script = JS_GetFrameScript(aCx, frame);
if (!script) {
JS_ReportError(aCx, "Could not get frame script!");
return nsnull;
}
JSScript *script;
if (JS_DescribeScriptedCaller(aCx, &script, nsnull)) {
if (NS_FAILED(NS_NewURI(getter_AddRefs(baseURI),
JS_GetScriptFilename(aCx, script)))) {
JS_ReportError(aCx, "Failed to construct base URI!");

View File

@ -75,6 +75,7 @@ class XMLHttpRequestUpload : public events::EventTarget
STRING_onloadstart,
STRING_onprogress,
STRING_onloadend,
STRING_ontimeout,
STRING_COUNT
};
@ -239,6 +240,8 @@ JSPropertySpec XMLHttpRequestUpload::sProperties[] = {
GetEventListener, SetEventListener },
{ sEventStrings[STRING_onloadend], STRING_onloadend, PROPERTY_FLAGS,
GetEventListener, SetEventListener },
{ sEventStrings[STRING_ontimeout], STRING_ontimeout, PROPERTY_FLAGS,
GetEventListener, SetEventListener },
{ 0, 0, 0, NULL, NULL }
};
@ -248,7 +251,8 @@ const char* const XMLHttpRequestUpload::sEventStrings[STRING_COUNT] = {
"onload",
"onloadstart",
"onprogress",
"onloadend"
"onloadend",
"ontimeout"
};
class XMLHttpRequest
@ -271,6 +275,7 @@ class XMLHttpRequest
SLOT_withCredentials,
SLOT_upload,
SLOT_responseType,
SLOT_timeout,
SLOT_COUNT
};
@ -292,6 +297,7 @@ class XMLHttpRequest
STRING_onloadstart,
STRING_onprogress,
STRING_onloadend,
STRING_ontimeout,
STRING_COUNT
};
@ -399,6 +405,7 @@ private:
JS_SetReservedSlot(obj, SLOT_withCredentials, JSVAL_FALSE);
JS_SetReservedSlot(obj, SLOT_upload, JSVAL_NULL);
JS_SetReservedSlot(obj, SLOT_responseType, STRING_TO_JSVAL(textStr));
JS_SetReservedSlot(obj, SLOT_timeout, zero);
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
XMLHttpRequestPrivate* priv = new XMLHttpRequestPrivate(obj, workerPrivate);
@ -528,6 +535,7 @@ private:
IMPL_SETTER(MozBackgroundRequest)
IMPL_SETTER(WithCredentials)
IMPL_SETTER(ResponseType)
IMPL_SETTER(Timeout)
#undef IMPL_SETTER
@ -798,6 +806,8 @@ JSPropertySpec XMLHttpRequest::sProperties[] = {
js_GetterOnlyPropertyStub },
{ "responseType", SLOT_responseType, PROPERTY_FLAGS, GetProperty,
SetResponseType },
{ "timeout", SLOT_timeout, PROPERTY_FLAGS, GetProperty,
SetTimeout },
{ sEventStrings[STRING_onreadystatechange], STRING_onreadystatechange,
PROPERTY_FLAGS, GetEventListener, SetEventListener },
{ sEventStrings[STRING_onabort], STRING_onabort, PROPERTY_FLAGS,
@ -812,6 +822,8 @@ JSPropertySpec XMLHttpRequest::sProperties[] = {
GetEventListener, SetEventListener },
{ sEventStrings[STRING_onloadend], STRING_onloadend, PROPERTY_FLAGS,
GetEventListener, SetEventListener },
{ sEventStrings[STRING_ontimeout], STRING_ontimeout, PROPERTY_FLAGS,
GetEventListener, SetEventListener },
#undef GENERIC_READONLY_PROPERTY
@ -846,7 +858,8 @@ const char* const XMLHttpRequest::sEventStrings[STRING_COUNT] = {
"onload",
"onloadstart",
"onprogress",
"onloadend"
"onloadend",
"ontimeout"
};
// static

View File

@ -59,6 +59,49 @@
#include "RuntimeService.h"
#include "XMLHttpRequest.h"
/**
* XMLHttpRequest in workers
*
* XHR in workers is implemented by proxying calls/events/etc between the
* worker thread and an nsXMLHttpRequest on the main thread. The glue
* object here is the Proxy, which lives on both threads. All other objects
* live on either the main thread (the nsXMLHttpRequest) or the worker thread
* (the worker and XHR private objects).
*
* The main thread XHR is always operated in async mode, even for sync XHR
* in workers. Calls made on the worker thread are proxied to the main thread
* synchronously (meaning the worker thread is blocked until the call
* returns). Each proxied call spins up a sync queue, which captures any
* synchronously dispatched events and ensures that they run synchronously
* on the worker as well. Asynchronously dispatched events are posted to the
* worker thread to run asynchronously. Some of the XHR state is mirrored on
* the worker thread to avoid needing a cross-thread call on every property
* access.
*
* The XHR private is stored in the private slot of the XHR JSObject on the
* worker thread. It is destroyed when that JSObject is GCd. The private
* roots its JSObject while network activity is in progress. It also
* adds itself as a feature to the worker to give itself a chance to clean up
* if the worker goes away during an XHR call. It is important that the
* rooting and feature registration (collectively called pinning) happens at
* the proper times. If we pin for too long we can cause memory leaks or even
* shutdown hangs. If we don't pin for long enough we introduce a GC hazard.
*
* The XHR is pinned from the time Send is called to roughly the time loadend
* is received. There are some complications involved with Abort and XHR
* reuse. We maintain a counter on the main thread of how many times Send was
* called on this XHR, and we decrement the counter everytime we receive a
* loadend event. When the counter reaches zero we dispatch a runnable to the
* worker thread to unpin the XHR. We only decrement the counter if the
* dispatch was successful, because the worker may no longer be accepting
* regular runnables. In the event that we reach Proxy::Teardown and there
* the outstanding Send count is still non-zero, we dispatch a control
* runnable which is guaranteed to run.
*
* NB: Some of this could probably be simplified now that we have the
* inner/outer channel ids.
*/
BEGIN_WORKERS_NAMESPACE
namespace xhr {
@ -72,9 +115,12 @@ public:
// Only touched on the main thread.
nsRefPtr<nsXMLHttpRequest> mXHR;
nsCOMPtr<nsIXMLHttpRequestUpload> mXHRUpload;
PRUint32 mInnerEventStreamId;
PRUint32 mInnerChannelId;
PRUint32 mOutstandingSendCount;
// Only touched on the worker thread.
PRUint32 mOuterEventStreamId;
PRUint32 mOuterChannelId;
PRUint64 mLastLoaded;
PRUint64 mLastTotal;
@ -92,6 +138,7 @@ public:
PRUint32 mSyncEventResponseSyncQueueKey;
bool mUploadEventListenersAttached;
bool mMainThreadSeenLoadStart;
bool mInOpen;
public:
NS_DECL_ISUPPORTS
@ -99,18 +146,22 @@ public:
Proxy(XMLHttpRequestPrivate* aXHRPrivate)
: mWorkerPrivate(nsnull), mXMLHttpRequestPrivate(aXHRPrivate),
mInnerChannelId(0), mOuterChannelId(0), mLastLoaded(0), mLastTotal(0),
mInnerEventStreamId(0), mInnerChannelId(0), mOutstandingSendCount(0),
mOuterEventStreamId(0), mOuterChannelId(0), mLastLoaded(0), mLastTotal(0),
mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
mLastLengthComputable(false), mLastUploadLengthComputable(false),
mSeenLoadStart(false), mSeenUploadLoadStart(false),
mSyncQueueKey(PR_UINT32_MAX), mSyncEventResponseSyncQueueKey(PR_UINT32_MAX),
mUploadEventListenersAttached(false), mMainThreadSeenLoadStart(false)
mSyncQueueKey(PR_UINT32_MAX),
mSyncEventResponseSyncQueueKey(PR_UINT32_MAX),
mUploadEventListenersAttached(false), mMainThreadSeenLoadStart(false),
mInOpen(false)
{ }
~Proxy()
{
NS_ASSERTION(!mXHR, "Still have an XHR object attached!");
NS_ASSERTION(!mXHRUpload, "Still have an XHR upload object attached!");
NS_ASSERTION(!mOutstandingSendCount, "We're dying too early!");
}
bool
@ -215,13 +266,14 @@ enum
STRING_load,
STRING_loadstart,
STRING_progress,
STRING_timeout,
STRING_readystatechange,
STRING_loadend,
STRING_COUNT,
STRING_LAST_XHR = STRING_loadend,
STRING_LAST_EVENTTARGET = STRING_progress
STRING_LAST_EVENTTARGET = STRING_timeout
};
JS_STATIC_ASSERT(STRING_LAST_XHR >= STRING_LAST_EVENTTARGET);
@ -234,6 +286,7 @@ const char* const sEventStrings[] = {
"load",
"loadstart",
"progress",
"timeout",
// nsIXMLHttpRequest event types, supported only by XHR.
"readystatechange",
@ -285,14 +338,48 @@ public:
{ }
};
class TeardownRunnable : public nsRunnable
class XHRUnpinRunnable : public WorkerControlRunnable
{
Proxy* mProxy;
XMLHttpRequestPrivate* mXMLHttpRequestPrivate;
public:
TeardownRunnable(nsRefPtr<Proxy>& aProxy)
XHRUnpinRunnable(WorkerPrivate* aWorkerPrivate,
XMLHttpRequestPrivate* aXHRPrivate)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mXMLHttpRequestPrivate(aXHRPrivate)
{ }
bool
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aProxy.forget(&mProxy);
AssertIsOnMainThread();
return true;
}
void
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aDispatchResult)
{
AssertIsOnMainThread();
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
mXMLHttpRequestPrivate->Unpin(aCx);
return true;
}
};
class AsyncTeardownRunnable : public nsRunnable
{
nsRefPtr<Proxy> mProxy;
public:
AsyncTeardownRunnable(Proxy* aProxy)
{
mProxy = aProxy;
NS_ASSERTION(mProxy, "Null proxy!");
}
@ -301,7 +388,7 @@ public:
AssertIsOnMainThread();
mProxy->Teardown();
NS_RELEASE(mProxy);
mProxy = nsnull;
return NS_OK;
}
@ -316,16 +403,19 @@ class LoadStartDetectionRunnable : public nsIRunnable,
XMLHttpRequestPrivate* mXMLHttpRequestPrivate;
nsString mEventType;
bool mReceivedLoadStart;
PRUint32 mChannelId;
class ProxyCompleteRunnable : public MainThreadProxyRunnable
{
XMLHttpRequestPrivate* mXMLHttpRequestPrivate;
PRUint32 mChannelId;
public:
ProxyCompleteRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
XMLHttpRequestPrivate* aXHRPrivate)
XMLHttpRequestPrivate* aXHRPrivate,
PRUint32 aChannelId)
: MainThreadProxyRunnable(aWorkerPrivate, RunWhenClearing, aProxy),
mXMLHttpRequestPrivate(aXHRPrivate)
mXMLHttpRequestPrivate(aXHRPrivate), mChannelId(aChannelId)
{ }
bool
@ -345,6 +435,11 @@ class LoadStartDetectionRunnable : public nsIRunnable,
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
if (mChannelId != mProxy->mOuterChannelId) {
// Threads raced, this event is now obsolete.
return true;
}
if (mSyncQueueKey != PR_UINT32_MAX) {
aWorkerPrivate->StopSyncLoop(mSyncQueueKey, true);
}
@ -360,7 +455,8 @@ public:
LoadStartDetectionRunnable(Proxy* aProxy, XMLHttpRequestPrivate* aXHRPrivate)
: mWorkerPrivate(aProxy->mWorkerPrivate), mProxy(aProxy), mXHR(aProxy->mXHR),
mXMLHttpRequestPrivate(aXHRPrivate), mReceivedLoadStart(false)
mXMLHttpRequestPrivate(aXHRPrivate), mReceivedLoadStart(false),
mChannelId(mProxy->mInnerChannelId)
{
AssertIsOnMainThread();
mEventType.AssignWithConversion(sEventStrings[STRING_loadstart]);
@ -394,16 +490,19 @@ public:
}
if (!mReceivedLoadStart) {
mProxy->Reset();
if (mProxy->mOutstandingSendCount > 1) {
mProxy->mOutstandingSendCount--;
} else if (mProxy->mOutstandingSendCount == 1) {
mProxy->Reset();
if (mProxy->mWorkerPrivate) {
nsRefPtr<ProxyCompleteRunnable> runnable =
new ProxyCompleteRunnable(mWorkerPrivate, mProxy,
mXMLHttpRequestPrivate);
if (!runnable->Dispatch(nsnull)) {
NS_WARNING("Failed to dispatch ProxyCompleteRunnable!");
mXMLHttpRequestPrivate,
mChannelId);
if (runnable->Dispatch(nsnull)) {
mProxy->mWorkerPrivate = nsnull;
mProxy->mOutstandingSendCount--;
}
mProxy->mWorkerPrivate = nsnull;
}
}
@ -447,7 +546,7 @@ class EventRunnable : public MainThreadProxyRunnable
nsCString mStatusText;
PRUint64 mLoaded;
PRUint64 mTotal;
PRUint32 mChannelId;
PRUint32 mEventStreamId;
PRUint32 mStatus;
PRUint16 mReadyState;
bool mUploadEvent;
@ -464,7 +563,7 @@ public:
bool aLengthComputable, PRUint64 aLoaded, PRUint64 aTotal)
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, SkipWhenClearing, aProxy),
mType(aType), mResponse(JSVAL_VOID), mLoaded(aLoaded), mTotal(aTotal),
mChannelId(aProxy->mInnerChannelId), mStatus(0), mReadyState(0),
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
mUploadEvent(aUploadEvent), mProgressEvent(true),
mLengthComputable(aLengthComputable), mResponseTextException(false),
mStatusException(false), mStatusTextException(false),
@ -474,7 +573,7 @@ public:
EventRunnable(Proxy* aProxy, bool aUploadEvent, const nsString& aType)
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, SkipWhenClearing, aProxy),
mType(aType), mResponse(JSVAL_VOID), mLoaded(0), mTotal(0),
mChannelId(aProxy->mInnerChannelId), mStatus(0), mReadyState(0),
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0),
mResponseTextException(false), mStatusException(false),
mStatusTextException(false), mReadyStateException(false),
@ -544,7 +643,7 @@ public:
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
if (mChannelId != mProxy->mOuterChannelId) {
if (mEventStreamId != mProxy->mOuterEventStreamId) {
// Threads raced, this event is now obsolete.
return true;
}
@ -808,6 +907,27 @@ public:
}
};
class SyncTeardownRunnable : public WorkerThreadProxySyncRunnable
{
public:
SyncTeardownRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
{
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aProxy);
}
virtual int
MainThreadRun()
{
AssertIsOnMainThread();
mProxy->Teardown();
return NS_OK;
}
};
class SetMultipartRunnable : public WorkerThreadProxySyncRunnable
{
bool mValue;
@ -889,6 +1009,24 @@ public:
}
};
class SetTimeoutRunnable : public WorkerThreadProxySyncRunnable
{
PRUint32 mTimeout;
public:
SetTimeoutRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
PRUint32 aTimeout)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
mTimeout(aTimeout)
{ }
int
MainThreadRun()
{
return GetDOMExceptionCodeFromResult(mProxy->mXHR->SetTimeout(mTimeout));
}
};
class AbortRunnable : public WorkerThreadProxySyncRunnable
{
public:
@ -899,7 +1037,7 @@ public:
int
MainThreadRun()
{
mProxy->mInnerChannelId++;
mProxy->mInnerEventStreamId++;
WorkerPrivate* oldWorker = mProxy->mWorkerPrivate;
mProxy->mWorkerPrivate = mWorkerPrivate;
@ -963,15 +1101,18 @@ class OpenRunnable : public WorkerThreadProxySyncRunnable
bool mMultipart;
bool mBackgroundRequest;
bool mWithCredentials;
PRUint32 mTimeout;
public:
OpenRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
const nsCString& aMethod, const nsCString& aURL,
const nsString& aUser, const nsString& aPassword,
bool aMultipart, bool aBackgroundRequest, bool aWithCredentials)
bool aMultipart, bool aBackgroundRequest, bool aWithCredentials,
PRUint32 aTimeout)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mMethod(aMethod),
mURL(aURL), mUser(aUser), mPassword(aPassword), mMultipart(aMultipart),
mBackgroundRequest(aBackgroundRequest), mWithCredentials(aWithCredentials)
mBackgroundRequest(aBackgroundRequest), mWithCredentials(aWithCredentials),
mTimeout(aTimeout)
{ }
int
@ -1016,13 +1157,27 @@ public:
}
}
mProxy->mInnerChannelId++;
if (mTimeout) {
rv = mProxy->mXHR->SetTimeout(mTimeout);
if (NS_FAILED(rv)) {
return GetDOMExceptionCodeFromResult(rv);
}
}
mProxy->mPreviousStatusText.Truncate();
NS_ASSERTION(!mProxy->mInOpen, "Reentrancy is bad!");
mProxy->mInOpen = true;
rv = mProxy->mXHR->Open(mMethod, mURL, true, mUser, mPassword, 1);
NS_ASSERTION(mProxy->mInOpen, "Reentrancy is bad!");
mProxy->mInOpen = false;
if (NS_SUCCEEDED(rv)) {
rv = mProxy->mXHR->SetResponseType(NS_LITERAL_STRING("text"));
}
return GetDOMExceptionCodeFromResult(rv);
}
};
@ -1087,12 +1242,18 @@ public:
}
}
mProxy->mInnerChannelId++;
nsresult rv = mProxy->mXHR->Send(variant);
if (NS_SUCCEEDED(rv) && !mHasUploadListeners) {
NS_ASSERTION(!mProxy->mUploadEventListenersAttached, "Huh?!");
if (!mProxy->AddRemoveEventListeners(true, true)) {
NS_ERROR("This should never fail!");
if (NS_SUCCEEDED(rv)) {
mProxy->mOutstandingSendCount++;
if (!mHasUploadListeners) {
NS_ASSERTION(!mProxy->mUploadEventListenersAttached, "Huh?!");
if (!mProxy->AddRemoveEventListeners(true, true)) {
NS_ERROR("This should never fail!");
}
}
}
@ -1215,9 +1376,22 @@ Proxy::Teardown()
if (mXHR) {
Reset();
// NB: We are intentionally dropping events coming from xhr.abort on the
// floor.
AddRemoveEventListeners(false, false);
mXHR->Abort();
if (mOutstandingSendCount) {
nsRefPtr<XHRUnpinRunnable> runnable =
new XHRUnpinRunnable(mWorkerPrivate, mXMLHttpRequestPrivate);
if (!runnable->Dispatch(nsnull)) {
NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
}
mWorkerPrivate = nsnull;
mOutstandingSendCount = 0;
}
mXHRUpload = nsnull;
mXHR = nsnull;
}
@ -1290,6 +1464,14 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
nsRefPtr<EventRunnable> runnable;
if (mInOpen && type.EqualsASCII(sEventStrings[STRING_readystatechange])) {
PRUint16 readyState = 0;
if (NS_SUCCEEDED(mXHR->GetReadyState(&readyState)) &&
readyState == nsIXMLHttpRequest::OPENED) {
mInnerEventStreamId++;
}
}
if (progressEvent) {
bool lengthComputable;
PRUint64 loaded, total;
@ -1334,8 +1516,8 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
XMLHttpRequestPrivate::XMLHttpRequestPrivate(JSObject* aObj,
WorkerPrivate* aWorkerPrivate)
: mJSObject(aObj), mUploadJSObject(nsnull), mWorkerPrivate(aWorkerPrivate),
mJSObjectRootCount(0), mMultipart(false), mBackgroundRequest(false),
mWithCredentials(false), mCanceled(false)
mJSObjectRooted(false), mMultipart(false), mBackgroundRequest(false),
mWithCredentials(false), mCanceled(false), mTimeout(0)
{
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_COUNT_CTOR(mozilla::dom::workers::xhr::XMLHttpRequestPrivate);
@ -1344,48 +1526,69 @@ XMLHttpRequestPrivate::XMLHttpRequestPrivate(JSObject* aObj,
XMLHttpRequestPrivate::~XMLHttpRequestPrivate()
{
mWorkerPrivate->AssertIsOnWorkerThread();
NS_ASSERTION(!mJSObjectRootCount, "Huh?!");
NS_ASSERTION(!mJSObjectRooted, "Huh?!");
MOZ_COUNT_DTOR(mozilla::dom::workers::xhr::XMLHttpRequestPrivate);
}
void
XMLHttpRequestPrivate::ReleaseProxy()
XMLHttpRequestPrivate::ReleaseProxy(ReleaseType aType)
{
// Can't assert that we're on the worker thread here because mWorkerPrivate
// may be gone.
if (mProxy) {
// Don't let any more events run.
mProxy->mOuterChannelId++;
if (aType == XHRIsGoingAway) {
// We're in a GC finalizer, so we can't do a sync call here (and we don't
// need to).
nsRefPtr<AsyncTeardownRunnable> runnable =
new AsyncTeardownRunnable(mProxy);
mProxy = nsnull;
nsCOMPtr<nsIRunnable> runnable = new TeardownRunnable(mProxy);
NS_ASSERTION(!mProxy, "Should have swapped!");
if (NS_DispatchToMainThread(runnable)) {
NS_ERROR("Failed to dispatch teardown runnable!");
}
} else {
// This isn't necessary if the worker is going away or the XHR is going
// away.
if (aType == Default) {
// Don't let any more events run.
mProxy->mOuterEventStreamId++;
}
if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) {
NS_ERROR("Failed to dispatch teardown runnable!");
// We need to make a sync call here.
nsRefPtr<SyncTeardownRunnable> runnable =
new SyncTeardownRunnable(mWorkerPrivate, mProxy);
mProxy = nsnull;
if (!runnable->Dispatch(nsnull)) {
NS_ERROR("Failed to dispatch teardown runnable!");
}
}
}
}
bool
XMLHttpRequestPrivate::Pin(JSContext* aCx)
XMLHttpRequestPrivate::MaybePin(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mJSObjectRootCount) {
if (!JS_AddNamedObjectRoot(aCx, &mJSObject,
"XMLHttpRequestPrivate mJSObject")) {
return false;
}
if (!mWorkerPrivate->AddFeature(aCx, this)) {
if (!JS_RemoveObjectRoot(aCx, &mJSObject)) {
NS_ERROR("JS_RemoveObjectRoot failed!");
}
return false;
}
if (mJSObjectRooted) {
return true;
}
mJSObjectRootCount++;
if (!JS_AddNamedObjectRoot(aCx, &mJSObject,
"XMLHttpRequestPrivate mJSObject")) {
return false;
}
if (!mWorkerPrivate->AddFeature(aCx, this)) {
if (!JS_RemoveObjectRoot(aCx, &mJSObject)) {
NS_ERROR("JS_RemoveObjectRoot failed!");
}
return false;
}
mJSObjectRooted = true;
return true;
}
@ -1394,18 +1597,15 @@ XMLHttpRequestPrivate::Unpin(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
NS_ASSERTION(mJSObjectRootCount, "Mismatched calls to Unpin!");
mJSObjectRootCount--;
if (mJSObjectRootCount) {
return;
}
NS_ASSERTION(mJSObjectRooted, "Mismatched calls to Unpin!");
if (!JS_RemoveObjectRoot(aCx, &mJSObject)) {
NS_ERROR("JS_RemoveObjectRoot failed!");
}
mWorkerPrivate->RemoveFeature(aCx, this);
mJSObjectRooted = false;
}
bool
@ -1415,7 +1615,7 @@ XMLHttpRequestPrivate::Notify(JSContext* aCx, Status aStatus)
if (aStatus >= Canceling && !mCanceled) {
mCanceled = true;
ReleaseProxy();
ReleaseProxy(WorkerIsGoingAway);
}
return true;
@ -1575,6 +1775,33 @@ XMLHttpRequestPrivate::SetResponseType(JSContext* aCx, jsval aOldVal,
return true;
}
bool
XMLHttpRequestPrivate::SetTimeout(JSContext* aCx, jsval aOldVal, jsval *aVp)
{
mWorkerPrivate->AssertIsOnWorkerThread();
uint32_t timeout;
if (!JS_ValueToECMAUint32(aCx, *aVp, &timeout)) {
return false;
}
mTimeout = timeout;
if (!mProxy) {
// Open may not have been called yet, in which case we'll handle the
// timeout in OpenRunnable.
return true;
}
nsRefPtr<SetTimeoutRunnable> runnable =
new SetTimeoutRunnable(mWorkerPrivate, mProxy, timeout);
if (!runnable->Dispatch(aCx)) {
return false;
}
return true;
}
bool
XMLHttpRequestPrivate::Abort(JSContext* aCx)
{
@ -1593,7 +1820,7 @@ XMLHttpRequestPrivate::Abort(JSContext* aCx)
return true;
}
mProxy->mOuterChannelId++;
mProxy->mOuterEventStreamId++;
nsRefPtr<AbortRunnable> runnable = new AbortRunnable(mWorkerPrivate, mProxy);
return runnable->Dispatch(aCx);
@ -1679,12 +1906,12 @@ XMLHttpRequestPrivate::Open(JSContext* aCx, JSString* aMethod, JSString* aURL,
mProxy = new Proxy(this);
}
mProxy->mOuterChannelId++;
mProxy->mOuterEventStreamId++;
nsRefPtr<OpenRunnable> runnable =
new OpenRunnable(mWorkerPrivate, mProxy, NS_ConvertUTF16toUTF8(method),
NS_ConvertUTF16toUTF8(url), user, password, mMultipart,
mBackgroundRequest, mWithCredentials);
mBackgroundRequest, mWithCredentials, mTimeout);
// These were only useful before we had a proxy. From here on out changing
// those values makes no difference.
@ -1738,7 +1965,7 @@ XMLHttpRequestPrivate::Send(JSContext* aCx, bool aHasBody, jsval aBody)
hasUploadListeners = target->HasListeners();
}
if (!Pin(aCx)) {
if (!MaybePin(aCx)) {
return false;
}
@ -1749,6 +1976,8 @@ XMLHttpRequestPrivate::Send(JSContext* aCx, bool aHasBody, jsval aBody)
syncQueueKey = mWorkerPrivate->CreateNewSyncLoop();
}
mProxy->mOuterChannelId++;
nsRefPtr<SendRunnable> runnable =
new SendRunnable(mWorkerPrivate, mProxy, buffer, syncQueueKey,
hasUploadListeners);
@ -1795,7 +2024,7 @@ XMLHttpRequestPrivate::SendAsBinary(JSContext* aCx, JSString* aBody)
hasUploadListeners = target->HasListeners();
}
if (!Pin(aCx)) {
if (!MaybePin(aCx)) {
return false;
}
@ -1893,12 +2122,6 @@ XMLHttpRequestPrivate::MaybeDispatchPrematureAbortEvents(JSContext* aCx)
false, false, false, false, false
};
// If we never saw loadstart, we must Unpin ourselves or we will hang at
// shutdown. Do that here before any early returns.
if (!mProxy->mSeenLoadStart && mProxy->mWorkerPrivate) {
Unpin(aCx);
}
if (mProxy->mSeenUploadLoadStart) {
JSObject* target = mProxy->mXMLHttpRequestPrivate->GetUploadJSObject();
NS_ASSERTION(target, "Must have a target!");

View File

@ -61,12 +61,13 @@ class XMLHttpRequestPrivate : public events::EventTarget,
JSObject* mUploadJSObject;
WorkerPrivate* mWorkerPrivate;
nsRefPtr<Proxy> mProxy;
PRUint32 mJSObjectRootCount;
bool mJSObjectRooted;
bool mMultipart;
bool mBackgroundRequest;
bool mWithCredentials;
bool mCanceled;
PRUint32 mTimeout;
public:
XMLHttpRequestPrivate(JSObject* aObj, WorkerPrivate* aWorkerPrivate);
@ -75,7 +76,7 @@ public:
void
FinalizeInstance(JSContext* aCx)
{
ReleaseProxy();
ReleaseProxy(XHRIsGoingAway);
events::EventTarget::FinalizeInstance(aCx);
}
@ -122,6 +123,9 @@ public:
bool
SetResponseType(JSContext* aCx, jsval aOldVal, jsval *aVp);
bool
SetTimeout(JSContext* aCx, jsval aOldVal, jsval *aVp);
bool
Abort(JSContext* aCx);
@ -148,11 +152,13 @@ public:
OverrideMimeType(JSContext* aCx, JSString* aMimeType);
private:
enum ReleaseType { Default, XHRIsGoingAway, WorkerIsGoingAway };
void
ReleaseProxy();
ReleaseProxy(ReleaseType aType = Default);
bool
Pin(JSContext* aCx);
MaybePin(JSContext* aCx);
bool
MaybeDispatchPrematureAbortEvents(JSContext* aCx);
@ -164,7 +170,7 @@ private:
bool
SendInProgress() const
{
return mJSObjectRootCount != 0;
return mJSObjectRooted;
}
};

View File

@ -122,6 +122,7 @@ _TEST_FILES = \
workersDisabled_worker.js \
test_xhr_implicit_cancel.html \
xhr_implicit_cancel_worker.js \
test_xhr_timeout.html \
$(NULL)
_SUBDIR_TEST_FILES = \

View File

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=498998
-->
<head>
<title>Test for Bug 498998</title>
<script type="application/javascript"
src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet"
type="text/css"
href="/tests/SimpleTest/test.css">
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=498998"
>Mozilla Bug 498998 (Worker XMLHttpRequest timeout)</a>
<p id="display"></p>
<div id="content">
This test takes over 1 minute to run, probably over 2 minutes.
</div>
<pre id="test">
<script type="text/javascript">
var worker = new Worker("../../../content/base/test/test_XHR_timeout.js");
worker.addEventListener("message", function (event) {
if (event.data == "done") {
SimpleTest.finish();
return;
}
if (event.data == "start") {
return;
}
if (event.data.type == "is") {
SimpleTest.is(event.data.got, event.data.expected, event.data.msg);
return;
}
if (event.data.type == "ok") {
SimpleTest.ok(event.data.bool, event.data.msg);
return;
}
});
// Final test harness setup and launch.
(function() {
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(20);
var msg = "This test will take approximately " + (20 * 10)
msg += " seconds to complete, at most.";
document.getElementById("content").firstChild.nodeValue = msg;
worker.postMessage("start");
})();
</script>
</pre>
</body>
</html>

View File

@ -114,7 +114,8 @@ public class GeckoAppShell
public static native void callObserver(String observerKey, String topic, String data);
public static native void removeObserver(String observerKey);
public static native void loadGeckoLibsNative(String apkName);
public static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
public static native void loadSQLiteLibsNative(String apkName);
public static native void loadNSSLibsNative(String apkName);
public static native void onChangeNetworkLinkStatus(String status);
public static native void reportJavaCrash(String stack);
@ -397,7 +398,8 @@ public class GeckoAppShell
}
}
}
loadSQLiteLibsNative(apkName, extractLibs);
loadSQLiteLibsNative(apkName);
loadNSSLibsNative(apkName);
loadGeckoLibsNative(apkName);
}

View File

@ -41,7 +41,9 @@
#include "nsCRT.h"
#include "nsCommandParams.h"
#include "mozilla/HashFunctions.h"
using namespace mozilla;
PLDHashTableOps nsCommandParams::sHashOps =
{
@ -356,7 +358,7 @@ nsCommandParams::GetOrMakeEntry(const char * name, PRUint8 entryType, HashEntry*
PLDHashNumber
nsCommandParams::HashKey(PLDHashTable *table, const void *key)
{
return nsCRT::HashCode((const char *)key);
return HashString((const char *)key);
}
bool

View File

@ -23,6 +23,7 @@
* Vladimir Vukicevic <vladimir@pobox.com>
* Mark Steele <mwsteele@gmail.com>
* Bas Schouten <bschouten@mozilla.com>
* Jeff Gilbert <jgilbert@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
@ -517,23 +518,6 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
mMaxTextureImageSize = mMaxTextureSize;
mSupport_ES_ReadPixels_BGRA_UByte = false;
if (mIsGLES2) {
if (IsExtensionSupported(gl::GLContext::EXT_bgra)) {
mSupport_ES_ReadPixels_BGRA_UByte = true;
} else if (IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
IsExtensionSupported(gl::GLContext::IMG_read_format)) {
GLint auxFormat = 0;
GLint auxType = 0;
fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &auxFormat);
fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &auxType);
if (auxFormat == LOCAL_GL_BGRA && auxType == LOCAL_GL_UNSIGNED_BYTE)
mSupport_ES_ReadPixels_BGRA_UByte = true;
}
}
UpdateActualFormat();
}
@ -556,6 +540,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
else {
// if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
mSymbols.Zero();
NS_WARNING("InitWithPrefix failed!");
}
return mInitialized;
@ -1167,8 +1152,8 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
// save a few things for later restoring
curBoundFramebufferDraw = GetBoundDrawFBO();
curBoundFramebufferRead = GetBoundReadFBO();
curBoundFramebufferDraw = GetUserBoundDrawFBO();
curBoundFramebufferRead = GetUserBoundReadFBO();
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer);
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
@ -1336,7 +1321,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
}
// Now assemble the FBO
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO); // If we're not using a separate draw FBO, this will be the read FBO
BindInternalFBO(newOffscreenDrawFBO); // If we're not using a separate draw FBO, this will be the read FBO
if (useDrawMSFBO) {
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
@ -1370,7 +1355,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
}
if (aUseReadFBO) {
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
BindInternalFBO(newOffscreenReadFBO);
fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_TEXTURE_2D,
@ -1382,7 +1367,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
GLenum status;
bool framebuffersComplete = true;
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO);
BindInternalFBO(newOffscreenDrawFBO);
status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
NS_WARNING("DrawFBO: Incomplete");
@ -1392,7 +1377,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
framebuffersComplete = false;
}
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
BindInternalFBO(newOffscreenReadFBO);
status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
NS_WARNING("ReadFBO: Incomplete");
@ -1413,8 +1398,8 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
fDeleteRenderbuffers(1, &newOffscreenDepthRB);
fDeleteRenderbuffers(1, &newOffscreenStencilRB);
BindReadFBO(curBoundFramebufferRead);
BindDrawFBO(curBoundFramebufferDraw);
BindUserDrawFBO(curBoundFramebufferDraw);
BindUserReadFBO(curBoundFramebufferRead);
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
@ -1467,19 +1452,19 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
}
#endif
// Make sure we know that the buffers are new and thus dirty:
ForceDirtyFBOs();
// We're good, and the framebuffer is already attached.
// Now restore the GL state back to what it was before the resize took place.
// If the user was using fb 0, this will bind the offscreen framebuffer we
// just created.
BindDrawFBO(curBoundFramebufferDraw);
BindReadFBO(curBoundFramebufferRead);
BindUserDrawFBO(curBoundFramebufferDraw);
BindUserReadFBO(curBoundFramebufferRead);
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Make sure we know that the buffers are new and thus dirty:
ForceDirtyFBOs();
return true;
}
@ -1815,6 +1800,35 @@ GLContext::ReadTextureImage(GLuint aTexture,
return isurf.forget();
}
static void
GetOptimalReadFormats(GLContext* gl, GLenum& format, GLenum& type) {
if (gl->IsGLES2()) {
bool has_BGRA_UByte = false;
if (gl->IsExtensionSupported(gl::GLContext::EXT_bgra)) {
has_BGRA_UByte = true;
} else if (gl->IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
gl->IsExtensionSupported(gl::GLContext::IMG_read_format)) {
// Note that these extensions are not required to query this value.
// However, we should never get back BGRA unless one of these is supported.
GLint auxFormat = 0;
GLint auxType = 0;
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &auxFormat);
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &auxType);
if (auxFormat == LOCAL_GL_BGRA && auxType == LOCAL_GL_UNSIGNED_BYTE)
has_BGRA_UByte = true;
}
format = has_BGRA_UByte ? LOCAL_GL_BGRA : LOCAL_GL_RGBA;
type = LOCAL_GL_UNSIGNED_BYTE;
} else {
// defaults for desktop
format = LOCAL_GL_BGRA;
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
}
}
void
GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
GLsizei aWidth, GLsizei aHeight,
@ -1839,29 +1853,21 @@ GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
GLint currentPackAlignment = 0;
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
// defaults for desktop
GLenum format = LOCAL_GL_BGRA;
GLenum datatype = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
bool swap = false;
if (currentPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
if (IsGLES2()) {
datatype = LOCAL_GL_UNSIGNED_BYTE;
GLenum format;
GLenum datatype;
if (mSupport_ES_ReadPixels_BGRA_UByte) {
format = LOCAL_GL_BGRA;
} else {
format = LOCAL_GL_RGBA;
swap = true;
}
}
GetOptimalReadFormats(this, format, datatype);
fReadPixels(0, 0, aWidth, aHeight,
format, datatype,
aDest->Data());
if (swap) {
// Output should be in BGRA, so swap if RGBA
if (format == LOCAL_GL_RGBA) {
// swap B and R bytes
for (int j = 0; j < aHeight; ++j) {
PRUint32 *row = (PRUint32*) (aDest->Data() + aDest->Stride() * j);
@ -1872,7 +1878,8 @@ GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
}
}
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
if (currentPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
}
void

View File

@ -23,6 +23,7 @@
* Vladimir Vukicevic <vladimir@pobox.com>
* Mark Steele <mwsteele@gmail.com>
* Bas Schouten <bschouten@mozilla.com>
* Jeff Gilbert <jgilbert@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
@ -545,6 +546,10 @@ public:
mUserBoundReadFBO(0),
mInternalBoundDrawFBO(0),
mInternalBoundReadFBO(0),
#ifdef DEBUG
mInInternalBindingMode_DrawFBO(true),
mInInternalBindingMode_ReadFBO(true),
#endif
mOffscreenFBOsDirty(false),
mInitialized(false),
mIsOffscreen(aIsOffscreen),
@ -933,7 +938,13 @@ public:
}
}
GLuint GetBoundDrawFBO() {
#ifdef DEBUG
// See comment near BindInternalDrawFBO()
bool mInInternalBindingMode_DrawFBO;
bool mInInternalBindingMode_ReadFBO;
#endif
GLuint GetUserBoundDrawFBO() {
#ifdef DEBUG
GLint ret = 0;
// Don't need a branch here, because:
@ -942,17 +953,29 @@ public:
// the driver thinks.
raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
if (mInternalBoundDrawFBO != (GLuint)ret) {
printf_stderr("!!! Draw FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
NS_ABORT();
bool abort = false;
if (mInInternalBindingMode_DrawFBO) {
NS_ERROR("Draw FBO still bound internally!");
printf_stderr("Current internal draw FBO: %d, user: %d)\n", ret, mUserBoundDrawFBO);
abort = true;
}
if (mInternalBoundDrawFBO != (GLuint)ret) {
NS_ERROR("Draw FBO binding misprediction!");
printf_stderr("Bound draw FBO was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
abort = true;
}
if (abort)
NS_ABORT();
#endif
// We only ever expose the user's bound FBOs
return mUserBoundDrawFBO;
}
GLuint GetBoundReadFBO() {
GLuint GetUserBoundReadFBO() {
#ifdef DEBUG
GLint ret = 0;
// We use raw_ here because this is debug code and we need to see what
@ -962,55 +985,100 @@ public:
else
raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
if (mInternalBoundReadFBO != (GLuint)ret) {
printf_stderr("!!! Read FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
NS_ABORT();
bool abort = false;
if (mInInternalBindingMode_ReadFBO) {
NS_ERROR("Read FBO still bound internally!");
printf_stderr("Current internal read FBO: %d, user: %d)\n", ret, mUserBoundReadFBO);
abort = true;
}
if (mInternalBoundReadFBO != (GLuint)ret) {
NS_ERROR("Read FBO binding misprediction!");
printf_stderr("Bound read FBO was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
abort = true;
}
if (abort)
NS_ABORT();
#endif
// We only ever expose the user's bound FBOs
return mUserBoundReadFBO;
}
void BindDrawFBO(GLuint name) {
void BindUserDrawFBO(GLuint name) {
if (SupportsOffscreenSplit())
fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
else
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
#ifdef DEBUG
mInInternalBindingMode_DrawFBO = false;
#endif
}
void BindReadFBO(GLuint name) {
void BindUserReadFBO(GLuint name) {
if (SupportsOffscreenSplit())
fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
else
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
#ifdef DEBUG
mInInternalBindingMode_ReadFBO = false;
#endif
}
GLuint SwapBoundDrawFBO(GLuint name) {
GLuint prev = GetBoundDrawFBO();
BindDrawFBO(name);
// BindInternalDraw/ReadFBO() switch us over into 'internal binding mode'
// for the corresponding Draw or Read binding.
// To exit internal binding mode, use BindUserDraw/ReadFBO().
// While in internal binding mode for Draw/Read, the corresponding
// GetBoundUserDraw/ReadFBO() is undefined, and will trigger ABORT in DEBUG builds.
void BindInternalDrawFBO(GLuint name) {
#ifdef DEBUG
mInInternalBindingMode_DrawFBO = true;
#endif
if (SupportsOffscreenSplit())
raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
else
raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
mInternalBoundDrawFBO = name;
}
void BindInternalReadFBO(GLuint name) {
#ifdef DEBUG
mInInternalBindingMode_ReadFBO = true;
#endif
if (SupportsOffscreenSplit())
raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
else
raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
mInternalBoundReadFBO = name;
}
void BindInternalFBO(GLuint name) {
BindInternalDrawFBO(name);
BindInternalReadFBO(name);
}
void InitFramebuffers() {
MakeCurrent();
BindUserDrawFBO(0);
BindUserReadFBO(0);
}
GLuint SwapUserDrawFBO(GLuint name) {
GLuint prev = GetUserBoundDrawFBO();
BindUserDrawFBO(name);
return prev;
}
GLuint SwapBoundReadFBO(GLuint name) {
GLuint prev = GetBoundReadFBO();
BindReadFBO(name);
GLuint SwapUserReadFBO(GLuint name) {
GLuint prev = GetUserBoundReadFBO();
BindUserReadFBO(name);
return prev;
}
void BindOffscreenDrawBuffer() {
BindDrawFBO(mOffscreenDrawFBO);
}
void BindOffscreenReadBuffer() {
BindReadFBO(mOffscreenReadFBO);
}
void BindOffscreenBuffers() {
BindOffscreenDrawBuffer();
BindOffscreenReadBuffer();
}
private:
bool mOffscreenFBOsDirty;
@ -1070,9 +1138,16 @@ private:
if (scissor)
fDisable(LOCAL_GL_SCISSOR_TEST);
// flip read/draw for blitting
GLuint prevDraw = SwapBoundDrawFBO(mOffscreenReadFBO);
GLuint prevRead = SwapBoundReadFBO(mOffscreenDrawFBO);
// Store current bindings for restoring later
GLuint prevDraw = GetUserBoundDrawFBO();
GLuint prevRead = GetUserBoundReadFBO();
NS_ABORT_IF_FALSE(SupportsOffscreenSplit(), "Doesn't support offscreen split?");
// Manually setting internal bindings, entering internal mode
// Flip read/draw for blitting
BindInternalDrawFBO(mOffscreenReadFBO);
BindInternalReadFBO(mOffscreenDrawFBO);
GLint width = mOffscreenActualSize.width;
GLint height = mOffscreenActualSize.height;
@ -1081,8 +1156,9 @@ private:
LOCAL_GL_COLOR_BUFFER_BIT,
LOCAL_GL_NEAREST);
BindDrawFBO(prevDraw);
BindReadFBO(prevRead);
// Reset to emulated user binding, exiting internal mode
BindUserDrawFBO(prevDraw);
BindUserReadFBO(prevRead);
if (scissor)
fEnable(LOCAL_GL_SCISSOR_TEST);
@ -1137,23 +1213,23 @@ public:
}
void ForceDirtyFBOs() {
GLuint draw = SwapBoundReadFBO(mOffscreenDrawFBO);
GLuint draw = SwapUserDrawFBO(0);
BeforeGLDrawCall();
// no-op; just pretend we did something
AfterGLDrawCall();
BindDrawFBO(draw);
BindUserDrawFBO(draw);
}
void BlitDirtyFBOs() {
GLuint read = SwapBoundReadFBO(mOffscreenReadFBO);
GLuint read = SwapUserReadFBO(0);
BeforeGLReadCall();
// no-op; we just want to make sure the Read FBO is updated if it needs to be
AfterGLReadCall();
BindReadFBO(read);
BindUserReadFBO(read);
}
void fFinish() {
@ -1543,16 +1619,26 @@ protected:
if (ResizeOffscreenFBO(aSize, aUseReadFBO, false))
return true;
if (!mCreationFormat.samples)
if (!mCreationFormat.samples) {
NS_WARNING("ResizeOffscreenFBO failed to resize non-AA context!");
return false;
} else {
NS_WARNING("ResizeOffscreenFBO failed to resize AA context! Falling back to no AA...");
}
if (DebugMode()) {
printf_stderr("Requested level of multisampling is unavailable, continuing without multisampling\n");
}
return ResizeOffscreenFBO(aSize, aUseReadFBO, true);
if (ResizeOffscreenFBO(aSize, aUseReadFBO, true))
return true;
NS_WARNING("ResizeOffscreenFBO failed to resize AA context even without AA!");
return false;
}
void DeleteOffscreenFBO();
GLuint mOffscreenDrawFBO;
GLuint mOffscreenReadFBO;
GLuint mOffscreenColorRB;
@ -1605,7 +1691,6 @@ protected:
GLint mMaxTextureSize;
GLint mMaxTextureImageSize;
GLint mMaxRenderbufferSize;
bool mSupport_ES_ReadPixels_BGRA_UByte;
public:
@ -2057,11 +2142,11 @@ public:
// LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two
// cases.
case LOCAL_GL_FRAMEBUFFER_BINDING:
*params = GetBoundDrawFBO();
*params = GetUserBoundDrawFBO();
break;
case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
*params = GetBoundReadFBO();
*params = GetUserBoundReadFBO();
break;
default:

View File

@ -153,7 +153,11 @@ public:
bool Init()
{
MakeCurrent();
return InitWithPrefix("gl", true);
if (!InitWithPrefix("gl", true))
return false;
InitFramebuffers();
return true;
}
void *GetNativeData(NativeDataType aType)
@ -456,7 +460,7 @@ GLContextProviderCGL::CreateForWindow(nsIWidget *aWidget)
context);
if (!glContext->Init()) {
return nsnull;
}
}
return glContext.forget();
}
@ -554,6 +558,7 @@ CreateOffscreenPBufferContext(const gfxIntSize& aSize,
[pbFormat release];
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, pb);
return glContext.forget();
}
@ -579,6 +584,7 @@ CreateOffscreenFBOContext(const ContextFormat& aFormat,
}
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, true);
return glContext.forget();
}

View File

@ -39,11 +39,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Preferences.h"
#include "mozilla/Util.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
// please add new includes below Qt, otherwise it break Qt build due malloc wrapper conflicts
#if defined(XP_UNIX)
@ -92,7 +89,6 @@ typedef void *EGLNativeWindowType;
#elif defined(XP_WIN)
#include "mozilla/Preferences.h"
#include "nsILocalFile.h"
#ifndef WIN32_LEAN_AND_MEAN
@ -151,6 +147,9 @@ public:
#endif
#include "mozilla/Preferences.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
#include "gfxUtils.h"
#include "gfxFailure.h"
#include "gfxASurface.h"
@ -1100,6 +1099,9 @@ public:
}
#endif
if (ok)
InitFramebuffers();
return ok;
}
@ -1317,9 +1319,6 @@ public:
}
void *GetD3DShareHandle() {
if (!mPBufferCanBindToTexture)
return nsnull;
if (!sEGLLibrary.HasANGLESurfaceD3DTexture2DShareHandle()) {
return nsnull;
}
@ -2393,7 +2392,7 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
// if we're running under ANGLE, we can't set BIND_TO_TEXTURE --
// it's not supported, and we have dx interop pbuffers anyway
if (sEGLLibrary.IsANGLE())
if (sEGLLibrary.IsANGLE() || bufferUnused)
configCanBindToTexture = false;
nsTArray<EGLint> attribs(32);
@ -2433,6 +2432,7 @@ TRY_ATTRIBS_AGAIN:
}
// no configs? no pbuffers!
NS_WARNING("Failed to select acceptable config for PBuffer creation!");
return nsnull;
}
@ -2451,8 +2451,10 @@ TRY_ATTRIBS_AGAIN:
: LOCAL_EGL_TEXTURE_RGB)
: LOCAL_EGL_NONE,
pbsize);
if (!surface)
if (!surface) {
NS_WARNING("Failed to create PBuffer for context!");
return nsnull;
}
sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API);
@ -2464,7 +2466,7 @@ TRY_ATTRIBS_AGAIN:
sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
: gContextAttribs);
if (!context) {
NS_WARNING("Failed to create context");
NS_WARNING("Failed to create GLContext from PBuffer");
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull;
}
@ -2474,13 +2476,15 @@ TRY_ATTRIBS_AGAIN:
true);
if (!glContext->Init()) {
NS_WARNING("Failed to initialize GLContext!");
return nsnull;
}
if (!bufferUnused) {
glContext->mPBufferCanBindToTexture = configCanBindToTexture;
if (!bufferUnused) { // We *are* using the buffer
glContext->SetOffscreenSize(aSize, pbsize);
glContext->mIsPBuffer = true;
glContext->mPBufferCanBindToTexture = configCanBindToTexture;
}
return glContext.forget();
@ -2641,13 +2645,20 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
}
#if defined(ANDROID) || defined(XP_WIN)
bool usePBuffers = false; // Generally, prefer FBOs to PBuffers
if (sEGLLibrary.IsANGLE())
usePBuffers = true; // For d3d share handle, we need an EGL surface
gfxIntSize pbufferSize = usePBuffers ? aSize : gfxIntSize(16, 16);
nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateEGLPBufferOffscreenContext(gfxIntSize(16, 16), aFormat, true);
GLContextEGL::CreateEGLPBufferOffscreenContext(pbufferSize, aFormat, !usePBuffers);
if (!glContext)
return nsnull;
if (!glContext->ResizeOffscreenFBO(aSize, true))
gfxIntSize fboSize = usePBuffers ? glContext->OffscreenActualSize() : aSize;
if (!glContext->ResizeOffscreenFBO(fboSize, !usePBuffers))
return nsnull;
return glContext.forget();

View File

@ -776,7 +776,12 @@ TRY_AGAIN_NO_SHARING:
return false;
}
return IsExtensionSupported("GL_EXT_framebuffer_object");
if (!IsExtensionSupported("GL_EXT_framebuffer_object"))
return false;
InitFramebuffers();
return true;
}
bool MakeCurrentImpl(bool aForce = false)
@ -1161,6 +1166,7 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
vinfo,
shareContext,
false);
return glContext.forget();
}

View File

@ -325,7 +325,11 @@ public:
MakeCurrent();
SetupLookupFunction();
return InitWithPrefix("gl", true);
if (!InitWithPrefix("gl", true))
return false;
InitFramebuffers();
return true;
}
bool MakeCurrentImpl(bool aForce = false)

View File

@ -581,6 +581,12 @@ private:
*/
class THEBES_API ImageLayer : public Layer {
public:
enum ScaleMode {
SCALE_NONE,
SCALE_STRETCH // Unimplemented on GL layers and e10s
// Unimplemented - SCALE_PRESERVE_ASPECT_RATIO_CONTAIN
};
/**
* CONSTRUCTION PHASE ONLY
* Set the ImageContainer. aContainer must have the same layer manager
@ -596,6 +602,17 @@ public:
*/
void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
/**
* CONSTRUCTION PHASE ONLY
* Set the size to scale the image to and the mode at which to scale.
*/
void SetScaleToSize(const gfxIntSize &aSize, ScaleMode aMode)
{
mScaleToSize = aSize;
mScaleMode = aMode;
}
ImageContainer* GetContainer() { return mContainer; }
gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
@ -620,12 +637,16 @@ public:
protected:
ImageLayer(LayerManager* aManager, void* aImplData)
: Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {}
: Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD)
, mScaleMode(SCALE_NONE) {}
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
nsRefPtr<ImageContainer> mContainer;
gfxPattern::GraphicsFilter mFilter;
gfxIntSize mScaleToSize;
ScaleMode mScaleMode;
};
/****** Image subtypes for the different formats ******/

View File

@ -926,7 +926,7 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
nsRefPtr<gfxASurface> surface;
AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
Image *image = autoLock.GetImage();
mSize = autoLock.GetSize();
gfxIntSize size = mSize = autoLock.GetSize();
if (!surface || surface->CairoStatus()) {
return nsnull;
@ -938,6 +938,15 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
}
pat->SetFilter(mFilter);
gfxIntSize sourceSize = surface->GetSize();
if (mScaleMode != SCALE_NONE) {
NS_ASSERTION(mScaleMode == SCALE_STRETCH,
"No other scalemodes than stretch and none supported yet.");
gfxMatrix mat = pat->GetMatrix();
mat.Scale(float(sourceSize.width) / mScaleToSize.width, float(sourceSize.height) / mScaleToSize.height);
pat->SetMatrix(mat);
size = mScaleToSize;
}
// The visible region can extend outside the image. If we're not
// tiling, we don't want to draw into that area, so just draw within
@ -945,7 +954,7 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
const nsIntRect* tileSrcRect = GetTileSourceRect();
AutoSetOperator setOperator(aContext, GetOperator());
PaintContext(pat,
tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
tileSrcRect,
aOpacity, aContext);

View File

@ -130,6 +130,8 @@ ImageLayerD3D10::RenderLayer()
return;
}
gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
SetEffectTransformAndOpacity();
ID3D10EffectTechnique *technique;
@ -137,7 +139,6 @@ ImageLayerD3D10::RenderLayer()
if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
{
bool hasAlpha = false;
gfxIntSize size;
if (image->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
@ -154,7 +155,6 @@ ImageLayerD3D10::RenderLayer()
}
hasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
size = remoteImage->mSize;
} else {
CairoImage *cairoImage =
static_cast<CairoImage*>(image);
@ -174,7 +174,6 @@ ImageLayerD3D10::RenderLayer()
}
hasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
size = cairoImage->mSize;
}
TextureD3D10BackendData *data =
@ -286,8 +285,8 @@ ImageLayerD3D10::RenderLayer()
ShaderConstantRectD3D10(
(float)0,
(float)0,
(float)yuvImage->mSize.width,
(float)yuvImage->mSize.height)
(float)size.width,
(float)size.height)
);
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(

View File

@ -325,10 +325,11 @@ ImageLayerD3D9::RenderLayer()
SetShaderTransformAndOpacity();
gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
{
bool hasAlpha = false;
gfxIntSize size;
if (image->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
@ -343,7 +344,6 @@ ImageLayerD3D9::RenderLayer()
}
hasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
size = remoteImage->mSize;
} else {
CairoImage *cairoImage =
static_cast<CairoImage*>(image);
@ -361,7 +361,6 @@ ImageLayerD3D9::RenderLayer()
}
hasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
size = cairoImage->mSize;
}
TextureD3D9BackendData *data =
@ -433,8 +432,8 @@ ImageLayerD3D9::RenderLayer()
device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(0,
0,
yuvImage->mSize.width,
yuvImage->mSize.height),
size.width,
size.height),
1);
device()->SetVertexShaderConstantF(CBvTextureCoords,

View File

@ -230,6 +230,8 @@ ImageLayerOGL::RenderLayer(int,
NS_ASSERTION(image->GetFormat() != Image::REMOTE_IMAGE_BITMAP,
"Remote images aren't handled yet in OGL layers!");
NS_ASSERTION(mScaleMode == SCALE_NONE,
"Scale modes other than none not handled yet in OGL layers!");
if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImage *yuvImage =

View File

@ -1043,39 +1043,10 @@ LayerManagerOGL::CopyToTarget(gfxContext *aTarget)
}
#endif
GLenum format = LOCAL_GL_RGBA;
if (mHasBGRA)
format = LOCAL_GL_BGRA;
NS_ASSERTION(imageSurface->Stride() == width * 4,
"Image Surfaces being created with weird stride!");
PRUint32 currentPackAlignment = 0;
mGLContext->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
if (currentPackAlignment != 4) {
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
}
mGLContext->fReadPixels(0, 0,
width, height,
format,
LOCAL_GL_UNSIGNED_BYTE,
imageSurface->Data());
if (currentPackAlignment != 4) {
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
}
if (!mHasBGRA) {
// need to swap B and R bytes
for (int j = 0; j < height; ++j) {
PRUint32 *row = (PRUint32*) (imageSurface->Data() + imageSurface->Stride() * j);
for (int i = 0; i < width; ++i) {
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
row++;
}
}
}
mGLContext->ReadPixelsIntoImageSurface(0, 0, width, height, imageSurface);
aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
aTarget->Scale(1.0, -1.0);

Some files were not shown because too many files have changed in this diff Show More