mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Merge last green PGO from inbound to central
This commit is contained in:
commit
720c67a69d
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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>
|
||||
|
@ -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"/>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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":
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -53,6 +53,7 @@ EXTRA_JS_MODULES = \
|
||||
offlineAppCache.jsm \
|
||||
TelemetryTimestamps.jsm \
|
||||
KeywordURLResetPrompter.jsm \
|
||||
webappsUI.jsm \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
|
133
browser/modules/webappsUI.jsm
Normal file
133
browser/modules/webappsUI.jsm
Normal 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) });
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
BIN
browser/themes/gnomestripe/webapps-16.png
Normal file
BIN
browser/themes/gnomestripe/webapps-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 366 B |
BIN
browser/themes/gnomestripe/webapps-64.png
Normal file
BIN
browser/themes/gnomestripe/webapps-64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -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@
|
||||
|
@ -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
|
||||
|
BIN
browser/themes/pinstripe/webapps-16.png
Normal file
BIN
browser/themes/pinstripe/webapps-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 366 B |
BIN
browser/themes/pinstripe/webapps-64.png
Normal file
BIN
browser/themes/pinstripe/webapps-64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
BIN
browser/themes/winstripe/webapps-16.png
Normal file
BIN
browser/themes/winstripe/webapps-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 366 B |
BIN
browser/themes/winstripe/webapps-64.png
Normal file
BIN
browser/themes/winstripe/webapps-64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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/"
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -69,11 +69,9 @@ DIRS = \
|
||||
interfaces/smil \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
DIRS += \
|
||||
interfaces/apps \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DIRS += \
|
||||
base \
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "IDBFactory.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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!");
|
||||
|
@ -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
|
||||
|
@ -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!");
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 = \
|
||||
|
58
dom/workers/test/test_xhr_timeout.html
Normal file
58
dom/workers/test/test_xhr_timeout.html
Normal 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>
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, ¤tPackAlignment);
|
||||
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
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 ******/
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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*)¤tPackAlignment);
|
||||
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
Loading…
Reference in New Issue
Block a user