author | David Anderson <danderson@mozilla.com> |
Thu, 06 Sep 2012 18:28:59 -0700 | |
changeset 106826 | d16c4404e8c4d7f843f58d98c6282fa4bb1ef058 |
parent 106825 | 666bf90824f84abf2a7b92b83ea7646cc23671ae (current diff) |
parent 104600 | 233441ff53affd70178ed330d0fea4a5a511826c (diff) |
child 106827 | 54711415fb53b3060cf78ff501dc6e16d958e4da |
push id | 14706 |
push user | eakhgari@mozilla.com |
push date | Tue, 11 Sep 2012 20:39:52 +0000 |
treeherder | mozilla-inbound@d50bf1edaabe [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/src/atk/AccessibleWrap.cpp +++ b/accessible/src/atk/AccessibleWrap.cpp @@ -6,16 +6,17 @@ #include "AccessibleWrap.h" #include "Accessible-inl.h" #include "ApplicationAccessibleWrap.h" #include "InterfaceInitFuncs.h" #include "nsAccUtils.h" #include "nsIAccessibleRelation.h" +#include "nsIAccessibleTable.h" #include "RootAccessible.h" #include "nsIAccessibleValue.h" #include "nsMai.h" #include "nsMaiHyperlink.h" #include "nsString.h" #include "nsAutoPtr.h" #include "prprf.h" #include "nsStateMap.h"
--- a/accessible/src/base/FocusManager.cpp +++ b/accessible/src/base/FocusManager.cpp @@ -55,17 +55,17 @@ FocusManager::IsFocused(const Accessible // accessible creation for temporary about:blank document. Without this // peculiarity we would end up with plain implementation based on // FocusedAccessible() method call. Make sure this issue is fixed in // bug 638465. if (focusedNode->OwnerDoc() == aAccessible->GetNode()->OwnerDoc()) { DocAccessible* doc = GetAccService()->GetDocAccessible(focusedNode->OwnerDoc()); return aAccessible == - (doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr); + (doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr); } } return false; } bool FocusManager::IsFocusWithin(const Accessible* aContainer) const {
--- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -18,17 +18,17 @@ #include "nsIMutableArray.h" #include "nsIDOMXULContainerElement.h" #include "nsIDOMXULSelectCntrlEl.h" #include "nsIDOMXULSelectCntrlItemEl.h" #include "nsWhitespaceTokenizer.h" #include "nsComponentManagerUtils.h" -namespace dom = mozilla::dom; +using namespace mozilla; using namespace mozilla::a11y; void nsAccUtils::GetAccAttr(nsIPersistentProperties *aAttributes, nsIAtom *aAttrName, nsAString& aAttrValue) { aAttrValue.Truncate(); @@ -475,66 +475,8 @@ nsAccUtils::MustPrune(Accessible* aAcces role == roles::FLAT_EQUATION || role == roles::PASSWORD_TEXT || role == roles::TOGGLE_BUTTON || role == roles::GRAPHIC || role == roles::SLIDER || role == roles::PROGRESSBAR || role == roles::SEPARATOR; } - -nsresult -nsAccUtils::GetHeaderCellsFor(nsIAccessibleTable *aTable, - nsIAccessibleTableCell *aCell, - int32_t aRowOrColHeaderCells, nsIArray **aCells) -{ - nsresult rv = NS_OK; - nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t rowIdx = -1; - rv = aCell->GetRowIndex(&rowIdx); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t colIdx = -1; - rv = aCell->GetColumnIndex(&colIdx); - NS_ENSURE_SUCCESS(rv, rv); - - bool moveToLeft = aRowOrColHeaderCells == eRowHeaderCells; - - // Move to the left or top to find row header cells or column header cells. - int32_t index = (moveToLeft ? colIdx : rowIdx) - 1; - for (; index >= 0; index--) { - int32_t curRowIdx = moveToLeft ? rowIdx : index; - int32_t curColIdx = moveToLeft ? index : colIdx; - - nsCOMPtr<nsIAccessible> cell; - rv = aTable->GetCellAt(curRowIdx, curColIdx, getter_AddRefs(cell)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIAccessibleTableCell> tableCellAcc = - do_QueryInterface(cell); - - // GetCellAt should always return an nsIAccessibleTableCell (XXX Bug 587529) - NS_ENSURE_STATE(tableCellAcc); - - int32_t origIdx = 1; - if (moveToLeft) - rv = tableCellAcc->GetColumnIndex(&origIdx); - else - rv = tableCellAcc->GetRowIndex(&origIdx); - NS_ENSURE_SUCCESS(rv, rv); - - if (origIdx == index) { - // Append original header cells only. - uint32_t role = Role(cell); - bool isHeader = moveToLeft ? - role == nsIAccessibleRole::ROLE_ROWHEADER : - role == nsIAccessibleRole::ROLE_COLUMNHEADER; - - if (isHeader) - cells->AppendElement(cell, false); - } - } - - NS_ADDREF(*aCells = cells); - return NS_OK; -}
--- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -4,17 +4,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsAccUtils_h_ #define nsAccUtils_h_ #include "nsIAccessible.h" #include "nsIAccessibleRole.h" #include "nsIAccessibleText.h" -#include "nsIAccessibleTable.h" #include "nsAccessibilityService.h" #include "nsCoreUtils.h" #include "mozilla/dom/Element.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDOMNode.h" @@ -288,37 +287,11 @@ public: *aState2 = static_cast<uint32_t>(aState64 >> 31); } /** * Return true if the given accessible can't have children. Used when exposing * to platform accessibility APIs, should the children be pruned off? */ static bool MustPrune(Accessible* aAccessible); - - /** - * Search hint enum constants. Used by GetHeaderCellsFor() method. - */ - enum { - // search for row header cells, left direction - eRowHeaderCells, - // search for column header cells, top direction - eColumnHeaderCells - }; - - /** - * Return an array of row or column header cells for the given cell. - * - * @param aTable [in] table accessible - * @param aCell [in] cell accessible within the given table to - * get header cells - * @param aRowOrColHeaderCells [in] specifies whether column or row header - * cells are returned (see enum constants - * above) - * @param aCells [out] array of header cell accessibles - */ - static nsresult GetHeaderCellsFor(nsIAccessibleTable *aTable, - nsIAccessibleTableCell *aCell, - int32_t aRowOrColHeaderCells, - nsIArray **aCells); }; #endif
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -1605,22 +1605,19 @@ nsAccessibilityService::CreateHTMLAccess return accessible; } Accessible* accessible = new HTMLLinkAccessible(aContent, aDoc); NS_IF_ADDREF(accessible); return accessible; } - if (tag == nsGkAtoms::dt || - (tag == nsGkAtoms::li && - aFrame->GetType() != nsGkAtoms::blockFrame)) { - // Normally for li, it is created by the list item frame (in nsBlockFrame) - // which knows about the bullet frame; however, in this case the list item - // must have been styled using display: foo + if (tag == nsGkAtoms::dt || tag == nsGkAtoms::li) { + // Create list item accessible unconditionally by tag name. nsBlockFrame + // creates the list item accessible for other elements styled as list items. Accessible* accessible = new HTMLLIAccessible(aContent, aDoc); NS_IF_ADDREF(accessible); return accessible; } if (tag == nsGkAtoms::abbr || tag == nsGkAtoms::acronym || tag == nsGkAtoms::blockquote ||
--- a/accessible/src/generic/ARIAGridAccessible.cpp +++ b/accessible/src/generic/ARIAGridAccessible.cpp @@ -540,151 +540,57 @@ ARIAGridCellAccessible:: NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridCellAccessible, HyperTextAccessible, nsIAccessibleTableCell) //////////////////////////////////////////////////////////////////////////////// // nsIAccessibleTableCell -NS_IMETHODIMP -ARIAGridCellAccessible::GetTable(nsIAccessibleTable** aTable) +TableAccessible* +ARIAGridCellAccessible::Table() const { - NS_ENSURE_ARG_POINTER(aTable); - *aTable = nullptr; - Accessible* table = TableFor(Row()); - if (table) - CallQueryInterface(table, aTable); - - return NS_OK; + return table ? table->AsTable() : nullptr; } -NS_IMETHODIMP -ARIAGridCellAccessible::GetColumnIndex(int32_t* aColumnIndex) +uint32_t +ARIAGridCellAccessible::ColIdx() const { - NS_ENSURE_ARG_POINTER(aColumnIndex); - *aColumnIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - Accessible* row = Parent(); + Accessible* row = Row(); if (!row) - return NS_OK; - - *aColumnIndex = 0; + return 0; int32_t indexInRow = IndexInParent(); + uint32_t colIdx = 0; for (int32_t idx = 0; idx < indexInRow; idx++) { Accessible* cell = row->GetChildAt(idx); roles::Role role = cell->Role(); if (role == roles::GRID_CELL || role == roles::ROWHEADER || role == roles::COLUMNHEADER) - (*aColumnIndex)++; + colIdx++; } - return NS_OK; -} - -NS_IMETHODIMP -ARIAGridCellAccessible::GetRowIndex(int32_t* aRowIndex) -{ - NS_ENSURE_ARG_POINTER(aRowIndex); - *aRowIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aRowIndex = RowIndexFor(Row()); - return NS_OK; -} - -NS_IMETHODIMP -ARIAGridCellAccessible::GetColumnExtent(int32_t* aExtentCount) -{ - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 0; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aExtentCount = 1; - return NS_OK; -} - -NS_IMETHODIMP -ARIAGridCellAccessible::GetRowExtent(int32_t* aExtentCount) -{ - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 0; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aExtentCount = 1; - return NS_OK; + return colIdx; } -NS_IMETHODIMP -ARIAGridCellAccessible::GetColumnHeaderCells(nsIArray** aHeaderCells) +uint32_t +ARIAGridCellAccessible::RowIdx() const { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); - if (!table) - return NS_OK; - - return nsAccUtils::GetHeaderCellsFor(table, this, - nsAccUtils::eColumnHeaderCells, - aHeaderCells); + return RowIndexFor(Row()); } -NS_IMETHODIMP -ARIAGridCellAccessible::GetRowHeaderCells(nsIArray** aHeaderCells) +bool +ARIAGridCellAccessible::Selected() { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); - if (!table) - return NS_OK; - - return nsAccUtils::GetHeaderCellsFor(table, this, - nsAccUtils::eRowHeaderCells, - aHeaderCells); -} + Accessible* row = Row(); + if (!row) + return false; -NS_IMETHODIMP -ARIAGridCellAccessible::IsSelected(bool* aIsSelected) -{ - NS_ENSURE_ARG_POINTER(aIsSelected); - *aIsSelected = false; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - Accessible* row = Parent(); - if (!row || row->Role() != roles::ROW) - return NS_OK; - - if (!nsAccUtils::IsARIASelected(row) && !nsAccUtils::IsARIASelected(this)) - return NS_OK; - - *aIsSelected = true; - return NS_OK; + return nsAccUtils::IsARIASelected(row) || nsAccUtils::IsARIASelected(this); } //////////////////////////////////////////////////////////////////////////////// // Accessible void ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const {
--- a/accessible/src/generic/ARIAGridAccessible.h +++ b/accessible/src/generic/ARIAGridAccessible.h @@ -53,16 +53,17 @@ public: virtual void SelectedCells(nsTArray<Accessible*>* aCells); virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells); virtual void SelectedColIndices(nsTArray<uint32_t>* aCols); virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows); virtual void SelectCol(uint32_t aColIdx); virtual void SelectRow(uint32_t aRowIdx); virtual void UnselectCol(uint32_t aColIdx); virtual void UnselectRow(uint32_t aRowIdx); + virtual Accessible* AsAccessible() { return this; } protected: /** * Return true if the given row index is valid. */ bool IsValidRow(int32_t aRow); @@ -104,19 +105,20 @@ class ARIAGridCellAccessible : public Hy { public: ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc); // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTableCell - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL + NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::) // Accessible + virtual TableCellAccessible* AsTableCell() { return this; } virtual void Shutdown(); virtual void ApplyARIAState(uint64_t* aState) const; virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); protected: /** * Return a containing row. @@ -131,14 +133,20 @@ protected: * Return a table for the given row. */ Accessible* TableFor(Accessible* aRow) const; /** * Return index of the given row. */ int32_t RowIndexFor(Accessible* aRow) const; + + // TableCellAccessible + virtual TableAccessible* Table() const MOZ_OVERRIDE; + virtual uint32_t ColIdx() const MOZ_OVERRIDE; + virtual uint32_t RowIdx() const MOZ_OVERRIDE; + virtual bool Selected() MOZ_OVERRIDE; }; } // namespace a11y } // namespace mozilla #endif
--- a/accessible/src/generic/Accessible.cpp +++ b/accessible/src/generic/Accessible.cpp @@ -2841,17 +2841,31 @@ bool Accessible::IsWidget() const { return false; } bool Accessible::IsActiveWidget() const { - return FocusMgr()->IsFocused(this); + if (FocusMgr()->HasDOMFocus(mContent)) + return true; + + // If text entry of combobox widget has a focus then the combobox widget is + // active. + if (mRoleMapEntry && mRoleMapEntry->Is(nsGkAtoms::combobox)) { + uint32_t childCount = ChildCount(); + for (uint32_t idx = 0; idx < childCount; idx++) { + Accessible* child = mChildren.ElementAt(idx); + if (child->Role() == roles::ENTRY) + return FocusMgr()->HasDOMFocus(child->GetContent()); + } + } + + return false; } bool Accessible::AreItemsOperable() const { return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant); }
--- a/accessible/src/generic/Accessible.h +++ b/accessible/src/generic/Accessible.h @@ -32,16 +32,17 @@ namespace mozilla { namespace a11y { class EmbeddedObjCollector; class HTMLImageMapAccessible; class HTMLLIAccessible; class ImageAccessible; class Relation; class TableAccessible; +class TableCellAccessible; class TextLeafAccessible; class XULTreeAccessible; /** * Name type flags. */ enum ENameValueFlag { /** @@ -509,16 +510,18 @@ public: inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; } inline bool IsRoot() const { return mFlags & eRootAccessible; } mozilla::a11y::RootAccessible* AsRoot(); virtual mozilla::a11y::TableAccessible* AsTable() { return nullptr; } + virtual mozilla::a11y::TableCellAccessible* AsTableCell() { return nullptr; } + inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; } mozilla::a11y::TextLeafAccessible* AsTextLeaf(); ////////////////////////////////////////////////////////////////////////////// // ActionAccessible /** * Return the number of actions that can be performed on this accessible.
--- a/accessible/src/generic/DocAccessible.cpp +++ b/accessible/src/generic/DocAccessible.cpp @@ -1216,21 +1216,21 @@ DocAccessible::ARIAAttributeChanged(nsIC aContent); return; } } void DocAccessible::ARIAActiveDescendantChanged(nsIContent* aElm) { - if (FocusMgr()->HasDOMFocus(aElm)) { + Accessible* widget = GetAccessible(aElm); + if (widget && widget->IsActiveWidget()) { nsAutoString id; if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) { - nsIDocument* DOMDoc = aElm->OwnerDoc(); - dom::Element* activeDescendantElm = DOMDoc->GetElementById(id); + dom::Element* activeDescendantElm = aElm->OwnerDoc()->GetElementById(id); if (activeDescendantElm) { Accessible* activeDescendant = GetAccessible(activeDescendantElm); if (activeDescendant) { FocusMgr()->ActiveItemChanged(activeDescendant, false); A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("ARIA activedescedant changed", activeDescendant) } }
--- a/accessible/src/generic/Makefile.in +++ b/accessible/src/generic/Makefile.in @@ -20,16 +20,17 @@ CPPSRCS = \ ARIAGridAccessible.cpp \ BaseAccessibles.cpp \ DocAccessible.cpp \ FormControlAccessible.cpp \ HyperTextAccessible.cpp \ ImageAccessible.cpp \ OuterDocAccessible.cpp \ RootAccessible.cpp \ + TableCellAccessible.cpp \ TextLeafAccessible.cpp \ $(NULL) EXPORTS_NAMESPACES = mozilla/a11y EXPORTS_mozilla/a11y = \ Accessible.h \ DocAccessible.h \
--- a/accessible/src/generic/TableAccessible.h +++ b/accessible/src/generic/TableAccessible.h @@ -170,14 +170,19 @@ public: * Unselect the given row leaving other selected rows selected. */ virtual void UnselectRow(uint32_t aRowIdx) {} /** * Return true if the table is probably for layout. */ virtual bool IsProbablyLayoutTable() { return false; } + + /** + * Convert the table to an Accessible*. + */ + virtual Accessible* AsAccessible() = 0; }; } // namespace a11y } // namespace mozilla #endif
new file mode 100644 --- /dev/null +++ b/accessible/src/generic/TableCellAccessible.cpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "TableCellAccessible.h" + +#include "Accessible-inl.h" +#include "TableAccessible.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +void +TableCellAccessible::RowHeaderCells(nsTArray<Accessible*>* aCells) +{ + uint32_t rowIdx = RowIdx(), colIdx = ColIdx(); + TableAccessible* table = Table(); + if (!table) + return; + + // Move to the left to find row header cells + for (uint32_t curColIdx = colIdx - 1; curColIdx < colIdx; curColIdx--) { + Accessible* cell = table->CellAt(rowIdx, curColIdx); + if (!cell) + continue; + + // CellAt should always return a TableCellAccessible (XXX Bug 587529) + TableCellAccessible* tableCell = cell->AsTableCell(); + NS_ASSERTION(tableCell, "cell should be a table cell!"); + if (!tableCell) + continue; + + // Avoid addding cells multiple times, if this cell spans more columns + // we'll get it later. + if (tableCell->ColIdx() == curColIdx && cell->Role() == roles::ROWHEADER) + aCells->AppendElement(cell); + } +} + +void +TableCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells) +{ + uint32_t rowIdx = RowIdx(), colIdx = ColIdx(); + TableAccessible* table = Table(); + if (!table) + return; + + // Move to the left to find row header cells + for (uint32_t curRowIdx = rowIdx - 1; curRowIdx < rowIdx; curRowIdx--) { + Accessible* cell = table->CellAt(curRowIdx, colIdx); + if (!cell) + continue; + + // CellAt should always return a TableCellAccessible (XXX Bug 587529) + TableCellAccessible* tableCell = cell->AsTableCell(); + NS_ASSERTION(tableCell, "cell should be a table cell!"); + if (!tableCell) + continue; + + // Avoid addding cells multiple times, if this cell spans more rows + // we'll get it later. + if (tableCell->RowIdx() == curRowIdx && cell->Role() == roles::COLUMNHEADER) + aCells->AppendElement(cell); + } +}
--- a/accessible/src/generic/TableCellAccessible.h +++ b/accessible/src/generic/TableCellAccessible.h @@ -10,62 +10,62 @@ #include "nsTArray.h" #include "mozilla/StandardInteger.h" class Accessible; namespace mozilla { namespace a11y { - class TableAccessible; +class TableAccessible; /** - * abstract interface implemented by table cell accessibles. + * Abstract interface implemented by table cell accessibles. */ class TableCellAccessible { public: /** * Return the table this cell is in. */ - virtual TableAccessible* Table() { return nullptr; } + virtual TableAccessible* Table() const = 0; /** - * Return the Column of the table this cell is in. + * Return the column of the table this cell is in. */ - virtual uint32_t ColIdx() { return 0; } + virtual uint32_t ColIdx() const = 0; /** - * Return the the row of the table this cell is in. + * Return the row of the table this cell is in. */ - virtual uint32_t RowIdx() { return 0; } + virtual uint32_t RowIdx() const = 0; /** * Return the column extent of this cell. */ - virtual uint32_t ColExtent() { return 0; } + virtual uint32_t ColExtent() const { return 1; } /** * Return the row extent of this cell. */ - virtual uint32_t RowExtent() { return 0; } + virtual uint32_t RowExtent() const { return 1; } /** * Return the column header cells for this cell. */ - virtual void ColHeaderCells(nsTArray<Accessible*>* aCells) { } + virtual void ColHeaderCells(nsTArray<Accessible*>* aCells); /** * Return the row header cells for this cell. */ - virtual void RowHeaderCells(nsTArray<Accessible*>* aCells) { } + virtual void RowHeaderCells(nsTArray<Accessible*>* aCells); /** * Returns true if this cell is selected. */ - virtual bool Selected() { return false; } + virtual bool Selected() = 0; }; -} -} +} // namespace a11y +} // namespace mozilla #endif // mozilla_a11y_TableCellAccessible_h__
--- a/accessible/src/html/HTMLTableAccessible.cpp +++ b/accessible/src/html/HTMLTableAccessible.cpp @@ -55,18 +55,18 @@ HTMLTableCellAccessible:: NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableCellAccessible, HyperTextAccessible, nsIAccessibleTableCell) //////////////////////////////////////////////////////////////////////////////// // HTMLTableCellAccessible: Accessible implementation - void - HTMLTableCellAccessible::Shutdown() +void +HTMLTableCellAccessible::Shutdown() { mTableCell = nullptr; HyperTextAccessibleWrap::Shutdown(); } role HTMLTableCellAccessible::NativeRole() { @@ -98,30 +98,26 @@ HTMLTableCellAccessible::GetAttributesIn { if (IsDefunct()) return NS_ERROR_FAILURE; nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes); NS_ENSURE_SUCCESS(rv, rv); // table-cell-index attribute - nsCOMPtr<nsIAccessibleTable> tableAcc(GetTableAccessible()); - if (!tableAcc) + TableAccessible* table = Table(); + if (!table) return NS_OK; int32_t rowIdx = -1, colIdx = -1; rv = GetCellIndexes(rowIdx, colIdx); NS_ENSURE_SUCCESS(rv, rv); - int32_t idx = -1; - rv = tableAcc->GetCellIndexAt(rowIdx, colIdx, &idx); - NS_ENSURE_SUCCESS(rv, rv); - nsAutoString stringIdx; - stringIdx.AppendInt(idx); + stringIdx.AppendInt(table->CellIndexAt(rowIdx, colIdx)); nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx); // abbr attribute // Pick up object attribute from abbr DOM element (a child of the cell) or // from abbr DOM attribute. nsAutoString abbrText; if (ChildCount() == 1) { @@ -145,213 +141,133 @@ HTMLTableCellAccessible::GetAttributesIn nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::axis, axisText); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // HTMLTableCellAccessible: nsIAccessibleTableCell implementation -NS_IMETHODIMP -HTMLTableCellAccessible::GetTable(nsIAccessibleTable** aTable) +TableAccessible* +HTMLTableCellAccessible::Table() const { - NS_ENSURE_ARG_POINTER(aTable); - *aTable = nullptr; + Accessible* parent = const_cast<HTMLTableCellAccessible*>(this); + while ((parent = parent->Parent())) { + roles::Role role = parent->Role(); + if (role == roles::TABLE || role == roles::TREE_TABLE) + return parent->AsTable(); + } - if (IsDefunct()) - return NS_OK; - - nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible(); - table.swap(*aTable); - - return NS_OK; + return nullptr; } -NS_IMETHODIMP -HTMLTableCellAccessible::GetColumnIndex(int32_t* aColumnIndex) +uint32_t +HTMLTableCellAccessible::ColIdx() const { - NS_ENSURE_ARG_POINTER(aColumnIndex); - *aColumnIndex = -1; + nsITableCellLayout* cellLayout = GetCellLayout(); + NS_ENSURE_TRUE(cellLayout, 0); - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsITableCellLayout* cellLayout = GetCellLayout(); - NS_ENSURE_STATE(cellLayout); - - return cellLayout->GetColIndex(*aColumnIndex); + int32_t colIdx = 0; + cellLayout->GetColIndex(colIdx); + return colIdx > 0 ? static_cast<uint32_t>(colIdx) : 0; } -NS_IMETHODIMP -HTMLTableCellAccessible::GetRowIndex(int32_t* aRowIndex) +uint32_t +HTMLTableCellAccessible::RowIdx() const { - NS_ENSURE_ARG_POINTER(aRowIndex); - *aRowIndex = -1; + nsITableCellLayout* cellLayout = GetCellLayout(); + NS_ENSURE_TRUE(cellLayout, 0); - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsITableCellLayout* cellLayout = GetCellLayout(); - NS_ENSURE_STATE(cellLayout); - - return cellLayout->GetRowIndex(*aRowIndex); + int32_t rowIdx = 0; + cellLayout->GetRowIndex(rowIdx); + return rowIdx > 0 ? static_cast<uint32_t>(rowIdx) : 0; } -NS_IMETHODIMP -HTMLTableCellAccessible::GetColumnExtent(int32_t* aExtentCount) +uint32_t +HTMLTableCellAccessible::ColExtent() const { - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 1; - int32_t rowIdx = -1, colIdx = -1; GetCellIndexes(rowIdx, colIdx); - nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible(); - NS_ENSURE_STATE(table); + TableAccessible* table = Table(); + NS_ASSERTION(table, "cell not in a table!"); + if (!table) + return 0; - return table->GetColumnExtentAt(rowIdx, colIdx, aExtentCount); + return table->ColExtentAt(rowIdx, colIdx); } -NS_IMETHODIMP -HTMLTableCellAccessible::GetRowExtent(int32_t* aExtentCount) +uint32_t +HTMLTableCellAccessible::RowExtent() const { - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 1; - int32_t rowIdx = -1, colIdx = -1; GetCellIndexes(rowIdx, colIdx); - nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible(); - NS_ENSURE_STATE(table); - - return table->GetRowExtentAt(rowIdx, colIdx, aExtentCount); -} + TableAccessible* table = Table(); + NS_ASSERTION(table, "cell not in atable!"); + if (!table) + return 0; -NS_IMETHODIMP -HTMLTableCellAccessible::GetColumnHeaderCells(nsIArray** aHeaderCells) -{ - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - return GetHeaderCells(nsAccUtils::eColumnHeaderCells, aHeaderCells); + return table->RowExtentAt(rowIdx, colIdx); } -NS_IMETHODIMP -HTMLTableCellAccessible::GetRowHeaderCells(nsIArray** aHeaderCells) +void +HTMLTableCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells) { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; + IDRefsIterator itr(mDoc, mContent, nsGkAtoms::headers); + while (Accessible* cell = itr.Next()) + if (cell->Role() == roles::COLUMNHEADER) + aCells->AppendElement(cell); - if (IsDefunct()) - return NS_ERROR_FAILURE; - - return GetHeaderCells(nsAccUtils::eRowHeaderCells, aHeaderCells); + if (aCells->IsEmpty()) + TableCellAccessible::ColHeaderCells(aCells); } -NS_IMETHODIMP -HTMLTableCellAccessible::IsSelected(bool* aIsSelected) +void +HTMLTableCellAccessible::RowHeaderCells(nsTArray<Accessible*>* aCells) { - NS_ENSURE_ARG_POINTER(aIsSelected); - *aIsSelected = false; + IDRefsIterator itr(mDoc, mContent, nsGkAtoms::headers); + while (Accessible* cell = itr.Next()) + if (cell->Role() == roles::ROWHEADER) + aCells->AppendElement(cell); - if (IsDefunct()) - return NS_ERROR_FAILURE; + if (aCells->IsEmpty()) + TableCellAccessible::RowHeaderCells(aCells); +} +bool +HTMLTableCellAccessible::Selected() +{ int32_t rowIdx = -1, colIdx = -1; GetCellIndexes(rowIdx, colIdx); - nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible(); - NS_ENSURE_STATE(table); + TableAccessible* table = Table(); + NS_ENSURE_TRUE(table, false); - return table->IsCellSelected(rowIdx, colIdx, aIsSelected); + return table->IsCellSelected(rowIdx, colIdx); } //////////////////////////////////////////////////////////////////////////////// // HTMLTableCellAccessible: protected implementation -already_AddRefed<nsIAccessibleTable> -HTMLTableCellAccessible::GetTableAccessible() +nsITableCellLayout* +HTMLTableCellAccessible::GetCellLayout() const { - Accessible* parent = this; - while ((parent = parent->Parent())) { - roles::Role role = parent->Role(); - if (role == roles::TABLE || role == roles::TREE_TABLE) { - nsIAccessibleTable* tableAcc = nullptr; - CallQueryInterface(parent, &tableAcc); - return tableAcc; - } - } - - return nullptr; -} - -nsITableCellLayout* -HTMLTableCellAccessible::GetCellLayout() -{ - nsIFrame *frame = mContent->GetPrimaryFrame(); - NS_ASSERTION(frame, "The frame cannot be obtaied for HTML table cell."); - if (!frame) - return nullptr; - - nsITableCellLayout *cellLayout = do_QueryFrame(frame); - return cellLayout; + return do_QueryFrame(mContent->GetPrimaryFrame()); } nsresult -HTMLTableCellAccessible::GetCellIndexes(int32_t& aRowIndex, int32_t& aColIndex) +HTMLTableCellAccessible::GetCellIndexes(int32_t& aRowIdx, int32_t& aColIdx) const { nsITableCellLayout *cellLayout = GetCellLayout(); NS_ENSURE_STATE(cellLayout); - return cellLayout->GetCellIndexes(aRowIndex, aColIndex); + return cellLayout->GetCellIndexes(aRowIdx, aColIdx); } -nsresult -HTMLTableCellAccessible::GetHeaderCells(int32_t aRowOrColumnHeaderCell, - nsIArray** aHeaderCells) -{ - // Get header cells from @header attribute. - IDRefsIterator iter(mDoc, mContent, nsGkAtoms::headers); - nsIContent* headerCellElm = iter.NextElem(); - if (headerCellElm) { - nsresult rv = NS_OK; - nsCOMPtr<nsIMutableArray> headerCells = - do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - roles::Role desiredRole = static_cast<roles::Role>(-1) ; - if (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells) - desiredRole = roles::ROWHEADER; - else if (aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells) - desiredRole = roles::COLUMNHEADER; - - do { - Accessible* headerCell = mDoc->GetAccessible(headerCellElm); - - if (headerCell && headerCell->Role() == desiredRole) - headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell), - false); - } while ((headerCellElm = iter.NextElem())); - - NS_ADDREF(*aHeaderCells = headerCells); - return NS_OK; - } - - // Otherwise calculate header cells from hierarchy (see 11.4.3 "Algorithm to - // find heading information" of w3c HTML 4.01). - nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible(); - if (table) { - return nsAccUtils::GetHeaderCellsFor(table, this, aRowOrColumnHeaderCell, - aHeaderCells); - } - - return NS_OK; -} //////////////////////////////////////////////////////////////////////////////// // HTMLTableHeaderCellAccessible //////////////////////////////////////////////////////////////////////////////// HTMLTableHeaderCellAccessible:: HTMLTableHeaderCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : HTMLTableCellAccessible(aContent, aDoc)
--- a/accessible/src/html/HTMLTableAccessible.h +++ b/accessible/src/html/HTMLTableAccessible.h @@ -29,46 +29,51 @@ class HTMLTableCellAccessible : public H { public: HTMLTableCellAccessible(nsIContent* aContent, DocAccessible* aDoc); // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTableCell - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL + NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::) // Accessible + virtual TableCellAccessible* AsTableCell() { return this; } virtual void Shutdown(); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual uint64_t NativeInteractiveState() const; virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); + // TableCellAccessible + virtual TableAccessible* Table() const MOZ_OVERRIDE; + virtual uint32_t ColIdx() const MOZ_OVERRIDE; + virtual uint32_t RowIdx() const MOZ_OVERRIDE; + virtual uint32_t ColExtent() const MOZ_OVERRIDE; + virtual uint32_t RowExtent() const MOZ_OVERRIDE; + virtual void ColHeaderCells(nsTArray<Accessible*>* aCells) MOZ_OVERRIDE; + virtual void RowHeaderCells(nsTArray<Accessible*>* aCells) MOZ_OVERRIDE; + virtual bool Selected() MOZ_OVERRIDE; + protected: /** * Return host table accessible. */ already_AddRefed<nsIAccessibleTable> GetTableAccessible(); /** * Return nsITableCellLayout of the table cell frame. */ - nsITableCellLayout* GetCellLayout(); + nsITableCellLayout* GetCellLayout() const; /** * Return row and column indices of the cell. */ - nsresult GetCellIndexes(int32_t& aRowIdx, int32_t& aColIdx); - - /** - * Return an array of row or column header cells. - */ - nsresult GetHeaderCells(int32_t aRowOrColumnHeaderCell, - nsIArray **aHeaderCells); + nsresult GetCellIndexes(int32_t& aRowIdx, int32_t& aColIdx) const; }; /** * HTML table row/column header accessible (html:th or html:td@scope). */ class HTMLTableHeaderCellAccessible : public HTMLTableCellAccessible { @@ -125,16 +130,17 @@ public: virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells); virtual void SelectedColIndices(nsTArray<uint32_t>* aCols); virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows); virtual void SelectCol(uint32_t aColIdx); virtual void SelectRow(uint32_t aRowIdx); virtual void UnselectCol(uint32_t aColIdx); virtual void UnselectRow(uint32_t aRowIdx); virtual bool IsProbablyLayoutTable(); + virtual Accessible* AsAccessible() { return this; } // nsAccessNode virtual void Shutdown(); // Accessible virtual TableAccessible* AsTable() { return this; } virtual void Description(nsString& aDescription); virtual nsresult GetNameInternal(nsAString& aName);
--- a/accessible/src/msaa/TextLeafAccessibleWrap.cpp +++ b/accessible/src/msaa/TextLeafAccessibleWrap.cpp @@ -132,19 +132,19 @@ TextLeafAccessibleWrap::get_unclippedSub /* [out] */ int __RPC_FAR *aHeight) { __try { *aX = *aY = *aWidth = *aHeight = 0; if (IsDefunct()) return E_FAIL; - if (NS_FAILED(GetCharacterExtents(aStartIndex, aEndIndex, - aX, aY, aWidth, aHeight))) { - return NS_ERROR_FAILURE; + if (FAILED(GetCharacterExtents(aStartIndex, aEndIndex, + aX, aY, aWidth, aHeight))) { + return E_FAIL; } } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } return S_OK; } STDMETHODIMP TextLeafAccessibleWrap::scrollToSubstring( @@ -186,33 +186,33 @@ TextLeafAccessibleWrap::GetPointFromOffs textFrame->GetPointFromOffset(aOffset, &aOutPoint); return textFrame; } /* * Given an offset, the x, y, width, and height values are filled appropriately. */ -nsresult +HRESULT TextLeafAccessibleWrap::GetCharacterExtents(int32_t aStartOffset, int32_t aEndOffset, int32_t* aX, int32_t* aY, int32_t* aWidth, int32_t* aHeight) { *aX = *aY = *aWidth = *aHeight = 0; if (IsDefunct()) return CO_E_OBJNOTCONNECTED; nsPresContext* presContext = mDoc->PresContext(); nsIFrame *frame = GetFrame(); - NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(frame, E_FAIL); nsPoint startPoint, endPoint; nsIFrame *startFrame = GetPointFromOffset(frame, aStartOffset, true, startPoint); nsIFrame *endFrame = GetPointFromOffset(frame, aEndOffset, false, endPoint); if (!startFrame || !endFrame) { return E_FAIL; } @@ -229,17 +229,17 @@ TextLeafAccessibleWrap::GetCharacterExte sum.UnionRect(sum, rect); } *aX = sum.x; *aY = sum.y; *aWidth = sum.width; *aHeight = sum.height; - return NS_OK; + return S_OK; } STDMETHODIMP TextLeafAccessibleWrap::get_fontFamily( /* [retval][out] */ BSTR __RPC_FAR *aFontFamily) { __try { *aFontFamily = NULL;
--- a/accessible/src/msaa/TextLeafAccessibleWrap.h +++ b/accessible/src/msaa/TextLeafAccessibleWrap.h @@ -50,19 +50,19 @@ public: virtual HRESULT STDMETHODCALLTYPE scrollToSubstring( /* [in] */ unsigned int startIndex, /* [in] */ unsigned int endIndex); virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_fontFamily( /* [retval][out] */ BSTR __RPC_FAR *fontFamily); protected: - nsresult GetCharacterExtents(int32_t aStartOffset, int32_t aEndOffset, - int32_t* aX, int32_t* aY, - int32_t* aWidth, int32_t* aHeight); + HRESULT GetCharacterExtents(int32_t aStartOffset, int32_t aEndOffset, + int32_t* aX, int32_t* aY, + int32_t* aWidth, int32_t* aHeight); // Return child frame containing offset on success nsIFrame* GetPointFromOffset(nsIFrame *aContainingFrame, int32_t aOffset, bool aPreferNext, nsPoint& aOutPoint); }; } // namespace a11y } // namespace mozilla
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp +++ b/accessible/src/msaa/nsAccessNodeWrap.cpp @@ -51,17 +51,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNod //----------------------------------------------------- // nsIWinAccessNode methods //----------------------------------------------------- NS_IMETHODIMP nsAccessNodeWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr) { - return QueryInterface(aIID, aInstancePtr); + // XXX Wrong for E_NOINTERFACE + return static_cast<nsresult>(QueryInterface(aIID, aInstancePtr)); } //----------------------------------------------------- // IUnknown interface methods - see iunknown.h for documentation //----------------------------------------------------- STDMETHODIMP nsAccessNodeWrap::QueryInterface(REFIID iid, void** ppv) {
--- a/accessible/src/xpcom/Makefile.in +++ b/accessible/src/xpcom/Makefile.in @@ -13,16 +13,17 @@ include $(DEPTH)/config/autoconf.mk MODULE = accessibility LIBRARY_NAME = accessibility_xpcom_s LIBXUL_LIBRARY = 1 CPPSRCS = \ nsAccEvent.cpp \ nsAccessibleRelation.cpp \ xpcAccessibleTable.cpp \ + xpcAccessibleTableCell.cpp \ $(NULL) # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \
new file mode 100644 --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTableCell.cpp @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "xpcAccessibleTableCell.h" + +#include "Accessible.h" +#include "TableAccessible.h" +#include "TableCellAccessible.h" + +#include "nsIAccessibleTable.h" + +#include "nsComponentManagerUtils.h" +#include "nsIMutableArray.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +nsresult +xpcAccessibleTableCell::GetTable(nsIAccessibleTable** aTable) +{ + NS_ENSURE_ARG_POINTER(aTable); + *aTable = nullptr; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + TableAccessible* table = mTableCell->Table(); + if (!table) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsIAccessibleTable> xpcTable = + do_QueryInterface(static_cast<nsIAccessible*>(table->AsAccessible())); + xpcTable.forget(aTable); + + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetColumnIndex(int32_t* aColIdx) +{ + NS_ENSURE_ARG_POINTER(aColIdx); + *aColIdx = -1; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + *aColIdx = mTableCell->ColIdx(); + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetRowIndex(int32_t* aRowIdx) +{ + NS_ENSURE_ARG_POINTER(aRowIdx); + *aRowIdx = -1; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + *aRowIdx = mTableCell->RowIdx(); + + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetColumnExtent(int32_t* aExtent) +{ + NS_ENSURE_ARG_POINTER(aExtent); + *aExtent = -1; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + *aExtent = mTableCell->ColExtent(); + + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetRowExtent(int32_t* aExtent) +{ + NS_ENSURE_ARG_POINTER(aExtent); + *aExtent = -1; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + *aExtent = mTableCell->RowExtent(); + + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetColumnHeaderCells(nsIArray** aHeaderCells) +{ + NS_ENSURE_ARG_POINTER(aHeaderCells); + *aHeaderCells = nullptr; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + nsAutoTArray<Accessible*, 10> headerCells; + mTableCell->ColHeaderCells(&headerCells); + + nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID); + NS_ENSURE_TRUE(cells, NS_ERROR_FAILURE); + + for (uint32_t idx = 0; idx < headerCells.Length(); idx++) { + cells-> + AppendElement(static_cast<nsIAccessible*>(headerCells.ElementAt(idx)), + false); + } + + NS_ADDREF(*aHeaderCells = cells); + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::GetRowHeaderCells(nsIArray** aHeaderCells) +{ + NS_ENSURE_ARG_POINTER(aHeaderCells); + *aHeaderCells = nullptr; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + nsAutoTArray<Accessible*, 10> headerCells; + mTableCell->RowHeaderCells(&headerCells); + + nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID); + NS_ENSURE_TRUE(cells, NS_ERROR_FAILURE); + + for (uint32_t idx = 0; idx < headerCells.Length(); idx++) { + cells-> + AppendElement(static_cast<nsIAccessible*>(headerCells.ElementAt(idx)), + false); + } + + NS_ADDREF(*aHeaderCells = cells); + return NS_OK; +} + +nsresult +xpcAccessibleTableCell::IsSelected(bool* aSelected) +{ + NS_ENSURE_ARG_POINTER(aSelected); + *aSelected = false; + + if (!mTableCell) + return NS_ERROR_FAILURE; + + *aSelected = mTableCell->Selected(); + + return NS_OK; +}
--- a/accessible/src/xpcom/xpcAccessibleTableCell.h +++ b/accessible/src/xpcom/xpcAccessibleTableCell.h @@ -1,37 +1,46 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* 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/. */ -#ifndef MOZILLA_A11Y_XPCOM_XPACESSIBLETABLECELL_H_ -#define MOZILLA_A11Y_XPCOM_XPACESSIBLETABLECELL_H_ +#ifndef mozilla_a11y_xpcom_xpcAccessibletableCell_h_ +#define mozilla_a11y_xpcom_xpcAccessibletableCell_h_ + +#include "nscore.h" + +class nsIAccessibleTable; +class nsIArray; namespace mozilla { namespace a11y { + class TableAccessible; class TableCellAccessible; -} -} +/** + * This class provides an implementation of the nsIAccessibleTableCell + * interface's methods. + */ class xpcAccessibleTableCell { public: xpcAccessibleTableCell(mozilla::a11y::TableCellAccessible* aTableCell) : mTableCell(aTableCell) { } + nsresult GetTable(nsIAccessibleTable** aTable); + nsresult GetColumnIndex(int32_t* aColIdx); + nsresult GetRowIndex(int32_t* aRowIdx); + nsresult GetColumnExtent(int32_t* aExtent); + nsresult GetRowExtent(int32_t* aExtent); + nsresult GetColumnHeaderCells(nsIArray** aHeaderCells); + nsresult GetRowHeaderCells(nsIArray** aHeaderCells); + nsresult IsSelected(bool* aSelected); + protected: mozilla::a11y::TableCellAccessible* mTableCell; }; +} // namespace a11y +} // namespace mozilla -#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL \ - NS_IMETHOD GetTable(nsIAccessibleTable * *aTable); \ - NS_IMETHOD GetColumnIndex(int32_t *aColumnIndex); \ - NS_IMETHOD GetRowIndex(int32_t *aRowIndex); \ - NS_IMETHOD GetColumnExtent(int32_t *aColumnExtent); \ - NS_IMETHOD GetRowExtent(int32_t *aRowExtent); \ - NS_IMETHOD GetColumnHeaderCells(nsIArray * *aColumnHeaderCells); \ - NS_IMETHOD GetRowHeaderCells(nsIArray * *aRowHeaderCells); \ - NS_IMETHOD IsSelected(bool *_retval ); - -#endif // MOZILLA_A11Y_XPCOM_XPACESSIBLETABLECELL_H_ +#endif // mozilla_a11y_xpcom_xpcAccessibletableCell_h_
--- a/accessible/src/xul/XULListboxAccessible.cpp +++ b/accessible/src/xul/XULListboxAccessible.cpp @@ -737,204 +737,112 @@ XULListCellAccessible:: NS_IMPL_ISUPPORTS_INHERITED1(XULListCellAccessible, HyperTextAccessible, nsIAccessibleTableCell) //////////////////////////////////////////////////////////////////////////////// // XULListCellAccessible: nsIAccessibleTableCell implementation -NS_IMETHODIMP -XULListCellAccessible::GetTable(nsIAccessibleTable** aTable) +TableAccessible* +XULListCellAccessible::Table() const { - NS_ENSURE_ARG_POINTER(aTable); - *aTable = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - Accessible* thisRow = Parent(); if (!thisRow || thisRow->Role() != roles::ROW) - return NS_OK; + return nullptr; Accessible* table = thisRow->Parent(); if (!table || table->Role() != roles::TABLE) - return NS_OK; + return nullptr; - CallQueryInterface(table, aTable); - return NS_OK; + return table->AsTable(); } -NS_IMETHODIMP -XULListCellAccessible::GetColumnIndex(int32_t* aColumnIndex) +uint32_t +XULListCellAccessible::ColIdx() const { - NS_ENSURE_ARG_POINTER(aColumnIndex); - *aColumnIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - Accessible* row = Parent(); if (!row) - return NS_OK; - - *aColumnIndex = 0; + return 0; int32_t indexInRow = IndexInParent(); + uint32_t colIdx = 0; for (int32_t idx = 0; idx < indexInRow; idx++) { Accessible* cell = row->GetChildAt(idx); roles::Role role = cell->Role(); if (role == roles::CELL || role == roles::GRID_CELL || role == roles::ROWHEADER || role == roles::COLUMNHEADER) - (*aColumnIndex)++; + colIdx++; } - return NS_OK; + return colIdx; } -NS_IMETHODIMP -XULListCellAccessible::GetRowIndex(int32_t* aRowIndex) +uint32_t +XULListCellAccessible::RowIdx() const { - NS_ENSURE_ARG_POINTER(aRowIndex); - *aRowIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - Accessible* row = Parent(); if (!row) - return NS_OK; + return 0; Accessible* table = row->Parent(); if (!table) - return NS_OK; - - *aRowIndex = 0; + return 0; int32_t indexInTable = row->IndexInParent(); + uint32_t rowIdx = 0; for (int32_t idx = 0; idx < indexInTable; idx++) { row = table->GetChildAt(idx); if (row->Role() == roles::ROW) - (*aRowIndex)++; + rowIdx++; } - return NS_OK; -} - -NS_IMETHODIMP -XULListCellAccessible::GetColumnExtent(int32_t* aExtentCount) -{ - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 0; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aExtentCount = 1; - return NS_OK; + return rowIdx; } -NS_IMETHODIMP -XULListCellAccessible::GetRowExtent(int32_t* aExtentCount) +void +XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells) { - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 0; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aExtentCount = 1; - return NS_OK; -} - -NS_IMETHODIMP -XULListCellAccessible::GetColumnHeaderCells(nsIArray** aHeaderCells) -{ - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); - NS_ENSURE_STATE(table); // we expect to be in a listbox (table) + TableAccessible* table = Table(); + NS_ASSERTION(table, "cell not in a table!"); + if (!table) + return; // Get column header cell from XUL listhead. Accessible* list = nullptr; - nsRefPtr<Accessible> tableAcc(do_QueryObject(table)); + Accessible* tableAcc = table->AsAccessible(); uint32_t tableChildCount = tableAcc->ChildCount(); for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) { Accessible* child = tableAcc->GetChildAt(childIdx); if (child->Role() == roles::LIST) { list = child; break; } } if (list) { - int32_t colIdx = -1; - GetColumnIndex(&colIdx); - - nsIAccessible *headerCell = list->GetChildAt(colIdx); + Accessible* headerCell = list->GetChildAt(ColIdx()); if (headerCell) { - nsresult rv = NS_OK; - nsCOMPtr<nsIMutableArray> headerCells = - do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - headerCells->AppendElement(headerCell, false); - NS_ADDREF(*aHeaderCells = headerCells); - return NS_OK; + aCells->AppendElement(headerCell); + return; } } // No column header cell from XUL markup, try to get it from ARIA markup. - return nsAccUtils::GetHeaderCellsFor(table, this, - nsAccUtils::eColumnHeaderCells, - aHeaderCells); + TableCellAccessible::ColHeaderCells(aCells); } -NS_IMETHODIMP -XULListCellAccessible::GetRowHeaderCells(nsIArray** aHeaderCells) +bool +XULListCellAccessible::Selected() { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); - NS_ENSURE_STATE(table); // we expect to be in a listbox (table) + TableAccessible* table = Table(); + NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table) - // Calculate row header cells from ARIA markup. - return nsAccUtils::GetHeaderCellsFor(table, this, - nsAccUtils::eRowHeaderCells, - aHeaderCells); -} - -NS_IMETHODIMP -XULListCellAccessible::IsSelected(bool* aIsSelected) -{ - NS_ENSURE_ARG_POINTER(aIsSelected); - *aIsSelected = false; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); - NS_ENSURE_STATE(table); // we expect to be in a listbox (table) - - int32_t rowIdx = -1; - GetRowIndex(&rowIdx); - - return table->IsRowSelected(rowIdx, aIsSelected); + return table->IsRowSelected(RowIdx()); } //////////////////////////////////////////////////////////////////////////////// // XULListCellAccessible. Accessible implementation void XULListCellAccessible::Shutdown() { @@ -952,27 +860,18 @@ nsresult XULListCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes) { NS_ENSURE_ARG_POINTER(aAttributes); if (IsDefunct()) return NS_ERROR_FAILURE; // "table-cell-index" attribute - nsCOMPtr<nsIAccessibleTable> table; - GetTable(getter_AddRefs(table)); + TableAccessible* table = Table(); NS_ENSURE_STATE(table); // we expect to be in a listbox (table) - int32_t rowIdx = -1; - GetRowIndex(&rowIdx); - int32_t colIdx = -1; - GetColumnIndex(&colIdx); - - int32_t cellIdx = -1; - table->GetCellIndexAt(rowIdx, colIdx, &cellIdx); - nsAutoString stringIdx; - stringIdx.AppendInt(cellIdx); + stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx())); nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx); return NS_OK; }
--- a/accessible/src/xul/XULListboxAccessible.h +++ b/accessible/src/xul/XULListboxAccessible.h @@ -85,16 +85,17 @@ public: virtual uint32_t SelectedColCount(); virtual uint32_t SelectedRowCount(); virtual void SelectedCells(nsTArray<Accessible*>* aCells); virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells); virtual void SelectedColIndices(nsTArray<uint32_t>* aCols); virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows); virtual void SelectRow(uint32_t aRowIdx); virtual void UnselectRow(uint32_t aRowIdx); + virtual Accessible* AsAccessible() { return this; } // nsAccessNode virtual void Shutdown(); // Accessible virtual void Value(nsString& aValue); virtual TableAccessible* AsTable() { return this; } virtual a11y::role NativeRole(); @@ -159,20 +160,28 @@ class XULListCellAccessible : public Hyp { public: XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc); // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTableCell - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL + NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::) // Accessible + virtual TableCellAccessible* AsTableCell() { return this; } virtual void Shutdown(); virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); virtual a11y::role NativeRole(); + + // TableCellAccessible + virtual TableAccessible* Table() const MOZ_OVERRIDE; + virtual uint32_t ColIdx() const MOZ_OVERRIDE; + virtual uint32_t RowIdx() const MOZ_OVERRIDE; + virtual void ColHeaderCells(nsTArray<Accessible*>* aHeaderCells) MOZ_OVERRIDE; + virtual bool Selected() MOZ_OVERRIDE; }; } // namespace a11y } // namespace mozilla #endif
--- a/accessible/src/xul/XULTreeGridAccessible.cpp +++ b/accessible/src/xul/XULTreeGridAccessible.cpp @@ -495,18 +495,18 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION XULTreeGridCellAccessible) NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible) NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible) NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible) //////////////////////////////////////////////////////////////////////////////// // XULTreeGridCellAccessible: nsIAccessible implementation - void - XULTreeGridCellAccessible::Shutdown() +void +XULTreeGridCellAccessible::Shutdown() { mTableCell = nullptr; LeafAccessible::Shutdown(); } Accessible* XULTreeGridCellAccessible::FocusedChild() { @@ -650,136 +650,65 @@ XULTreeGridCellAccessible::DoAction(uint } return NS_ERROR_INVALID_ARG; } //////////////////////////////////////////////////////////////////////////////// // XULTreeGridCellAccessible: nsIAccessibleTableCell implementation -NS_IMETHODIMP -XULTreeGridCellAccessible::GetTable(nsIAccessibleTable** aTable) +TableAccessible* +XULTreeGridCellAccessible::Table() const { - NS_ENSURE_ARG_POINTER(aTable); - *aTable = nullptr; - - if (IsDefunct()) - return NS_OK; - Accessible* grandParent = mParent->Parent(); if (grandParent) - CallQueryInterface(grandParent, aTable); - - return NS_OK; -} + return grandParent->AsTable(); -NS_IMETHODIMP -XULTreeGridCellAccessible::GetColumnIndex(int32_t* aColumnIndex) -{ - NS_ENSURE_ARG_POINTER(aColumnIndex); - *aColumnIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - *aColumnIndex = GetColumnIndex(); - return NS_OK; + return nullptr; } -NS_IMETHODIMP -XULTreeGridCellAccessible::GetRowIndex(int32_t* aRowIndex) +uint32_t +XULTreeGridCellAccessible::ColIdx() const { - NS_ENSURE_ARG_POINTER(aRowIndex); - *aRowIndex = -1; - - if (IsDefunct()) - return NS_ERROR_FAILURE; + uint32_t colIdx = 0; + nsCOMPtr<nsITreeColumn> column = mColumn; + while ((column = nsCoreUtils::GetPreviousSensibleColumn(column))) + colIdx++; - *aRowIndex = mRow; - return NS_OK; -} - -NS_IMETHODIMP -XULTreeGridCellAccessible::GetColumnExtent(int32_t* aExtentCount) -{ - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 1; - - return NS_OK; + return colIdx; } -NS_IMETHODIMP -XULTreeGridCellAccessible::GetRowExtent(int32_t* aExtentCount) +uint32_t +XULTreeGridCellAccessible::RowIdx() const { - NS_ENSURE_ARG_POINTER(aExtentCount); - *aExtentCount = 1; - - return NS_OK; + return mRow; } -NS_IMETHODIMP -XULTreeGridCellAccessible::GetColumnHeaderCells(nsIArray** aHeaderCells) +void +XULTreeGridCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aHeaderCells) { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct() || !mDoc) - return NS_ERROR_FAILURE; - - nsresult rv = NS_OK; - nsCOMPtr<nsIMutableArray> headerCells = - do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsIDOMElement> columnElm; mColumn->GetElement(getter_AddRefs(columnElm)); nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm)); Accessible* headerCell = mDoc->GetAccessible(columnContent); - if (headerCell) - headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell), - false); - - NS_ADDREF(*aHeaderCells = headerCells); - return NS_OK; + aHeaderCells->AppendElement(headerCell); } -NS_IMETHODIMP -XULTreeGridCellAccessible::GetRowHeaderCells(nsIArray** aHeaderCells) +bool +XULTreeGridCellAccessible::Selected() { - NS_ENSURE_ARG_POINTER(aHeaderCells); - *aHeaderCells = nullptr; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsresult rv = NS_OK; - nsCOMPtr<nsIMutableArray> headerCells = - do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ADDREF(*aHeaderCells = headerCells); - return NS_OK; -} - -NS_IMETHODIMP -XULTreeGridCellAccessible::IsSelected(bool* aIsSelected) -{ - NS_ENSURE_ARG_POINTER(aIsSelected); - *aIsSelected = false; - - if (IsDefunct() || !mTreeView) - return NS_ERROR_FAILURE; - nsCOMPtr<nsITreeSelection> selection; nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection)); - NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_SUCCESS(rv, false); - return selection->IsSelected(mRow, aIsSelected); + bool selected = false; + selection->IsSelected(mRow, &selected); + return selected; } //////////////////////////////////////////////////////////////////////////////// // XULTreeGridCellAccessible: nsAccessNode implementation void XULTreeGridCellAccessible::Init() { @@ -802,35 +731,23 @@ nsresult XULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes) { NS_ENSURE_ARG_POINTER(aAttributes); if (IsDefunct()) return NS_ERROR_FAILURE; // "table-cell-index" attribute - Accessible* grandParent = mParent->Parent(); - if (!grandParent) - return NS_OK; - - nsCOMPtr<nsIAccessibleTable> tableAccessible = do_QueryObject(grandParent); - - // XXX - temp fix for crash bug 516047 - if (!tableAccessible) + TableAccessible* table = Table(); + if (!table) return NS_ERROR_FAILURE; - int32_t colIdx = GetColumnIndex(); - - int32_t cellIdx = -1; - tableAccessible->GetCellIndexAt(mRow, colIdx, &cellIdx); - nsAutoString stringIdx; - stringIdx.AppendInt(cellIdx); - nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, - stringIdx); + stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx())); + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx); // "cycles" attribute bool isCycler = false; nsresult rv = mColumn->GetCycler(&isCycler); if (NS_SUCCEEDED(rv) && isCycler) nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::cycles, NS_LITERAL_STRING("true")); @@ -879,43 +796,28 @@ uint64_t XULTreeGridCellAccessible::NativeInteractiveState() const { return states::SELECTABLE; } int32_t XULTreeGridCellAccessible::IndexInParent() const { - return GetColumnIndex(); + return ColIdx(); } Relation XULTreeGridCellAccessible::RelationByType(uint32_t aType) { return Relation(); } //////////////////////////////////////////////////////////////////////////////// // XULTreeGridCellAccessible: public implementation -int32_t -XULTreeGridCellAccessible::GetColumnIndex() const -{ - int32_t index = 0; - nsCOMPtr<nsITreeColumn> column = mColumn; - while (true) { - column = nsCoreUtils::GetPreviousSensibleColumn(column); - if (!column) - break; - index++; - } - - return index; -} - void XULTreeGridCellAccessible::CellInvalidated() { if (!mTreeView) return; nsAutoString textEquiv;
--- a/accessible/src/xul/XULTreeGridAccessible.h +++ b/accessible/src/xul/XULTreeGridAccessible.h @@ -44,16 +44,17 @@ public: virtual uint32_t SelectedColCount(); virtual uint32_t SelectedRowCount(); virtual void SelectedCells(nsTArray<Accessible*>* aCells); virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells); virtual void SelectedColIndices(nsTArray<uint32_t>* aCols); virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows); virtual void SelectRow(uint32_t aRowIdx); virtual void UnselectRow(uint32_t aRowIdx); + virtual Accessible* AsAccessible() { return this; } // nsAccessNode virtual void Shutdown(); // Accessible virtual TableAccessible* AsTable() { return this; } virtual a11y::role NativeRole(); @@ -142,44 +143,48 @@ public: NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth, int32_t* aHeight); NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName); NS_IMETHOD DoAction(uint8_t aIndex); // nsIAccessibleTableCell - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL + NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::) // nsAccessNode virtual void Init(); // Accessible + virtual TableCellAccessible* AsTableCell() { return this; } virtual void Shutdown(); virtual ENameValueFlag Name(nsString& aName); virtual Accessible* FocusedChild(); virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes); virtual int32_t IndexInParent() const; virtual Relation RelationByType(uint32_t aType); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual uint64_t NativeInteractiveState() const; // ActionAccessible virtual uint8_t ActionCount(); + // TableCellAccessible + virtual TableAccessible* Table() const MOZ_OVERRIDE; + virtual uint32_t ColIdx() const MOZ_OVERRIDE; + virtual uint32_t RowIdx() const MOZ_OVERRIDE; + virtual void ColHeaderCells(nsTArray<Accessible*>* aHeaderCells) MOZ_OVERRIDE; + virtual void RowHeaderCells(nsTArray<Accessible*>* aCells) MOZ_OVERRIDE { } + virtual bool Selected() MOZ_OVERRIDE; + // XULTreeGridCellAccessible NS_DECLARE_STATIC_IID_ACCESSOR(XULTREEGRIDCELLACCESSIBLE_IMPL_CID) /** - * Return index of the column. - */ - int32_t GetColumnIndex() const; - - /** * Fire name or state change event if the accessible text or value has been * changed. */ void CellInvalidated(); protected: // Accessible virtual Accessible* GetSiblingAtOffset(int32_t aOffset,
--- a/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html +++ b/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html @@ -65,16 +65,20 @@ https://bugzilla.mozilla.org/show_bug.cg var gQueue = null; function doTest() { gQueue = new eventQueue(); gQueue.push(new synthFocus("container", new focusChecker("item1"))); gQueue.push(new changeARIAActiveDescendant("container", "item2")); + + gQueue.push(new synthFocus("combobox_entry", new focusChecker("combobox_entry"))); + gQueue.push(new changeARIAActiveDescendant("combobox", "combobox_option2")); + todo(false, "No focus for inserted element, bug 687011"); //gQueue.push(new insertItemNFocus("container", "item3")); gQueue.invoke(); // Will call SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); @@ -82,19 +86,32 @@ https://bugzilla.mozilla.org/show_bug.cg </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=429547" title="Support aria-activedescendant usage in nsIAccesible::TakeFocus()"> Mozilla Bug 429547 </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=761102" + title="Focus may be missed when ARIA active-descendant is changed on active composite widget"> + Mozilla Bug 761102 + </a> <p id="display"></p> <div id="content" style="display: none"></div> <pre id="test"> </pre> <div role="listbox" aria-activedescendant="item1" id="container" tabindex="1"> <div role="listitem" id="item1">item1</div> <div role="listitem" id="item2">item2</div> </div> + + <div role="combobox" id="combobox"> + <input id="combobox_entry"> + <ul> + <li role="option" id="combobox_option1">option1</li> + <li role="option" id="combobox_option2">option2</li> + </ul> + </div> </body> </html>
--- a/accessible/tests/mochitest/tree/test_list.html +++ b/accessible/tests/mochitest/tree/test_list.html @@ -118,31 +118,63 @@ { TEXT_LEAF: [] } ] } ] } ] } ] }; testAccessibleTree("list6", tree); + // li having no display:list-item style + var tree = + { LIST: [ // ul + { LISTITEM: [ // li + { TEXT_LEAF: [] }, + ] }, + { TEXT_LEAF: [] }, + { LISTITEM: [ // li + { TEXT_LEAF: [] } + ] } + ] }; + testAccessibleTree("list7", tree); + + var tree = + { LIST: [ // ul + { LISTITEM: [ // li + { TEXT_LEAF: [] }, + ] }, + { LISTITEM: [ // li + { TEXT_LEAF: [] } + ] } + ] }; + testAccessibleTree("list8", tree); + + // span having display:list-item style + testAccessibleTree("list9", discAccTree); + SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> <body> <a target="_blank" title="Fix O(n^2) access to all the children of a container" href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045"> Mozilla Bug 342045 </a> <a target="_blank" + title="Wrong accessible is created for HTML:li having block display style" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=507555"> + Mozilla Bug 507555 + </a> + <a target="_blank" title="Bullets of nested not ordered lists have one and the same character." href="https://bugzilla.mozilla.org/show_bug.cgi?id=604587"> Mozilla Bug 604587 </a> <a target="_blank" title="Fix list bullets for DL list (crash [@ nsBulletFrame::GetListItemText])" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629114"> Mozilla Bug 629114 @@ -188,10 +220,28 @@ <ol id="list6"> <li> <dl id="dl"> <dt>item1</dt><dd>description</dd> </dl> </li> </ol> + + <!-- display style different than list-item --> + <ul id="list7"> + <li id="l7_li1" style="display:inline-block;">Oranges</li> + <li id="l7_li2" style="display:inline-block;">Apples</li> + </ul> + + <ul id="list8"> + <li id="l8_li1" style="display:inline; float:right;">Oranges</li> + <li id="l8_li2" style="display:inline; float:right;">Apples</li> + </ul> + + <!-- list-item display style --> + <ul id="list9"> + <span id="l9_li1" style="display:list-item">Oranges</span> + <span id="l9_li2" style="display:list-item">Apples</span> + <span id="l9_li3" style="display:list-item">Bananas</span> + </ul> </body> </html>
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -39,19 +39,19 @@ pref("network.protocol-handler.warn-exte pref("network.protocol-handler.warn-external.vnd.youtube", false); /* http prefs */ pref("network.http.pipelining", true); pref("network.http.pipelining.ssl", true); pref("network.http.proxy.pipelining", true); pref("network.http.pipelining.maxrequests" , 6); pref("network.http.keep-alive.timeout", 600); -pref("network.http.max-connections", 6); -pref("network.http.max-persistent-connections-per-server", 4); -pref("network.http.max-persistent-connections-per-proxy", 4); +pref("network.http.max-connections", 20); +pref("network.http.max-persistent-connections-per-server", 6); +pref("network.http.max-persistent-connections-per-proxy", 20); // See bug 545869 for details on why these are set the way they are pref("network.buffer.cache.count", 24); pref("network.buffer.cache.size", 16384); /* session history */ pref("browser.sessionhistory.max_total_viewers", 1); pref("browser.sessionhistory.max_entries", 50); @@ -502,17 +502,17 @@ pref("ui.showHideScrollbars", 1); // Enable the ProcessPriorityManager, and give processes with no visible // documents a 1s grace period before they're eligible to be marked as // background. pref("dom.ipc.processPriorityManager.enabled", true); pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000); pref("hal.processPriorityManager.gonk.masterOomAdjust", 0); pref("hal.processPriorityManager.gonk.foregroundOomAdjust", 1); -pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 2); +pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 6); pref("hal.processPriorityManager.gonk.masterNice", -1); pref("hal.processPriorityManager.gonk.foregroundNice", 0); pref("hal.processPriorityManager.gonk.backgroundNice", 10); #ifndef DEBUG // Enable pre-launching content processes for improved startup time // (hiding latency). pref("dom.ipc.processPrelauch.enabled", true); @@ -520,8 +520,11 @@ pref("dom.ipc.processPrelauch.enabled", pref("dom.ipc.processPrelauch.delayMs", 1000); #endif // Ignore the "dialog=1" feature in window.open. pref("dom.disable_window_open_dialog_feature", true); // Screen reader support pref("accessibility.accessfu.activate", 2); + +// Disable native prompt +pref("browser.prompt.allowNative", false);
--- a/b2g/chrome/content/forms.js +++ b/b2g/chrome/content/forms.js @@ -113,23 +113,38 @@ let FormAssistant = { let json = msg.json; switch (msg.name) { case "Forms:Input:Value": target.value = json.value; break; case "Forms:Select:Choice": let options = target.options; + let valueChanged = false; if ("index" in json) { - options.item(json.index).selected = true; + if (options.selectedIndex != json.index) { + options.selectedIndex = json.index; + valueChanged = true; + } } else if ("indexes" in json) { for (let i = 0; i < options.length; i++) { - options.item(i).selected = (json.indexes.indexOf(i) != -1); + let newValue = (json.indexes.indexOf(i) != -1); + if (options.item(i).selected != newValue) { + options.item(i).selected = newValue; + valueChanged = true; + } } } + + // only fire onchange event if any selected option is changed + if (valueChanged) { + let event = content.document.createEvent('HTMLEvents'); + event.initEvent('change', true, true); + target.dispatchEvent(event); + } break; } }, observe: function fa_observe(subject, topic, data) { switch (topic) { case "ime-enabled-state-changed": let isOpen = this.isKeyboardOpened;
--- a/b2g/chrome/content/runapp.js +++ b/b2g/chrome/content/runapp.js @@ -67,17 +67,17 @@ window.addEventListener('load', function let app = findAppWithName(appname); if (!app) { dump('Could not find app: "' + appname + '". Maybe you meant one of:\n'); usageAndDie(true); return; } let setReq = - navigator.mozSettings.getLock().set({'lockscreen.enabled': false}); + navigator.mozSettings.createLock().set({'lockscreen.enabled': false}); setReq.onsuccess = function() { // give the event loop another turn to disable the lock screen window.setTimeout(function() { dump('--runapp launching app: ' + app.manifest.name + '\n'); app.launch(); }, 0); }; setReq.onerror = function() {
--- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -30,17 +30,17 @@ var SettingsListener = { window.setTimeout(function() { callback(defaultValue); }); return; } if (!callback || typeof callback !== 'function') { throw new Error('Callback is not a function'); } - var req = settings.getLock().get(name); + var req = settings.createLock().get(name); req.addEventListener('success', (function onsuccess() { callback(typeof(req.result[name]) != 'undefined' ? req.result[name] : defaultValue); })); this._callbacks[name] = callback; } };
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -504,16 +504,19 @@ var CustomEventManager = { break; case 'webapps-install-granted': case 'webapps-install-denied': WebappsHelper.handleEvent(detail); break; case 'select-choicechange': FormsHelper.handleEvent(detail); break; + case 'system-message-listener-ready': + Services.obs.notifyObservers(null, 'system-message-listener-ready', null); + break; } } } var AlertsHelper = { _listeners: {}, _count: 0,
new file mode 100644 --- /dev/null +++ b/b2g/config/mozconfigs/common @@ -0,0 +1,7 @@ +# 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/. + +# This file is included at the top of all b2g mozconfigs + +. "$topsrcdir/build/mozconfig.common"
new file mode 100644 --- /dev/null +++ b/b2g/config/mozconfigs/common.override @@ -0,0 +1,7 @@ +# 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/. + +# This file is included at the bottom of all b2g mozconfigs + +. "$topsrcdir/build/mozconfig.common.override"
--- a/b2g/config/mozconfigs/gb_armv7a_gecko/debug +++ b/b2g/config/mozconfigs/gb_armv7a_gecko/debug @@ -1,8 +1,10 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g mk_add_options MOZ_MAKE_FLAGS="-j8" ac_add_options --enable-application=b2g ac_add_options --target=arm-android-eabi ac_add_options --with-gonk="$topsrcdir/gonk-toolchain" @@ -10,8 +12,10 @@ ac_add_options --with-gonk-toolchain-pre ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-debug ac_add_options --with-ccache ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/gb_armv7a_gecko/nightly +++ b/b2g/config/mozconfigs/gb_armv7a_gecko/nightly @@ -1,8 +1,10 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g mk_add_options MOZ_MAKE_FLAGS="-j8" ac_add_options --enable-application=b2g ac_add_options --target=arm-android-eabi ac_add_options --with-gonk="$topsrcdir/gonk-toolchain" @@ -10,8 +12,10 @@ ac_add_options --with-gonk-toolchain-pre ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-profiling ac_add_options --with-ccache ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug @@ -13,8 +13,10 @@ ac_add_options --with-gonk-toolchain-pre ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-debug #ac_add_options --with-ccache ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h" + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly @@ -1,8 +1,10 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g mk_add_options MOZ_MAKE_FLAGS="-j8" ac_add_options --enable-application=b2g ac_add_options --enable-b2g-camera ac_add_options --target=arm-android-eabi @@ -13,8 +15,10 @@ ac_add_options --with-gonk-toolchain-pre ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-profiling #ac_add_options --with-ccache ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h" + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux32_gecko/nightly +++ b/b2g/config/mozconfigs/linux32_gecko/nightly @@ -1,8 +1,10 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" + ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-codesighs ac_add_options --enable-signmar # Nightlies only since this has a cost in performance #ac_add_options --enable-js-diagnostics @@ -31,8 +33,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4" # Use ccache ac_add_options --with-ccache=/usr/bin/ccache #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux64_gecko/nightly +++ b/b2g/config/mozconfigs/linux64_gecko/nightly @@ -33,8 +33,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4" # Use ccache ac_add_options --with-ccache=/usr/bin/ccache #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly +++ b/b2g/config/mozconfigs/macosx64_gecko/nightly @@ -1,9 +1,9 @@ -. $topsrcdir/build/macosx/common +. $topsrcdir/build/macosx/mozconfig.common ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-codesighs ac_add_options --enable-signmar # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics @@ -21,8 +21,10 @@ ac_add_options --enable-warnings-as-erro # B2G Stuff ac_add_options --enable-application=b2g ac_add_options --enable-debug-symbols ac_add_options --with-ccache ENABLE_MARIONETTE=1 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/win32_gecko/nightly +++ b/b2g/config/mozconfigs/win32_gecko/nightly @@ -1,8 +1,10 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" + # for pgo mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py' ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-jemalloc ac_add_options --enable-signmar @@ -22,8 +24,10 @@ else . $topsrcdir/build/win32/mozconfig.vs2010 fi # B2G Options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP + +. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -121,42 +121,42 @@ endif #} endif #} endif #} ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH))) libs:: cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX) -GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js) +GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js) endif endif #} LIBXUL_SDK ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) libs:: - $(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons - $(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png $(DIST)/bin/chrome/icons/default - $(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png $(DIST)/bin/chrome/icons/default - $(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png $(DIST)/bin/chrome/icons/default + $(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(FINAL_TARGET)/icons + $(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png $(FINAL_TARGET)/chrome/icons/default + $(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png $(FINAL_TARGET)/chrome/icons/default + $(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png $(FINAL_TARGET)/chrome/icons/default endif libs:: $(srcdir)/profile/prefs.js - $(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile + $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile ifndef LIBXUL_SDK # channel-prefs.js is handled separate from other prefs due to bug 756325 libs:: $(srcdir)/profile/channel-prefs.js - $(NSINSTALL) -D $(DIST)/bin/defaults/pref - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(ACDEFINES) $^ > $(DIST)/bin/defaults/pref/channel-prefs.js + $(NSINSTALL) -D $(FINAL_TARGET)/defaults/pref + $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(ACDEFINES) $^ > $(FINAL_TARGET)/defaults/pref/channel-prefs.js endif libs:: $(srcdir)/blocklist.xml - $(INSTALL) $(IFLAGS1) $^ $(DIST)/bin + $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET) ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) MAC_APP_NAME = $(MOZ_APP_DISPLAYNAME) ifdef MOZ_DEBUG MAC_APP_NAME := $(MAC_APP_NAME)Debug endif
--- a/browser/app/profile/extensions/Makefile.in +++ b/browser/app/profile/extensions/Makefile.in @@ -3,17 +3,17 @@ # 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/. DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -DISTROEXT = $(call core_abspath,$(DIST))/bin/distribution/extensions +DISTROEXT = $(call core_abspath,$(FINAL_TARGET))/distribution/extensions include $(DEPTH)/config/autoconf.mk DIRS = \ {972ce4c6-7e08-4474-a285-3208198ce6fd} \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in +++ b/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in @@ -12,14 +12,11 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk FILES := \ install.rdf \ $(NULL) libs:: $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/install.rdf.in > install.rdf - $(INSTALL) $(FILES) $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} + $(INSTALL) $(FILES) $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} -install:: - $(SYSINSTALL) $(IFLAGS1) $(FILES) $(DESTDIR)$(mozappdir)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} - GARBAGE += $(FILES)
--- a/browser/base/content/browser-tabPreviews.js +++ b/browser/base/content/browser-tabPreviews.js @@ -6,47 +6,58 @@ #endif */ /** * Tab previews utility, produces thumbnails */ var tabPreviews = { aspectRatio: 0.5625, // 16:9 + + get width() { + delete this.width; + return this.width = Math.ceil(screen.availWidth / 5.75); + }, + + get height() { + delete this.height; + return this.height = Math.round(this.width * this.aspectRatio); + }, + init: function tabPreviews_init() { if (this._selectedTab) return; this._selectedTab = gBrowser.selectedTab; - this.width = Math.ceil(screen.availWidth / 5.75); - this.height = Math.round(this.width * this.aspectRatio); - - window.addEventListener("unload", this, false); gBrowser.tabContainer.addEventListener("TabSelect", this, false); gBrowser.tabContainer.addEventListener("SSTabRestored", this, false); }, - uninit: function tabPreviews_uninit() { - window.removeEventListener("unload", this, false); - gBrowser.tabContainer.removeEventListener("TabSelect", this, false); - gBrowser.tabContainer.removeEventListener("SSTabRestored", this, false); - this._selectedTab = null; - }, + get: function tabPreviews_get(aTab) { - this.init(); + let uri = aTab.linkedBrowser.currentURI.spec; if (aTab.__thumbnail_lastURI && - aTab.__thumbnail_lastURI != aTab.linkedBrowser.currentURI.spec) { + aTab.__thumbnail_lastURI != uri) { aTab.__thumbnail = null; aTab.__thumbnail_lastURI = null; } - return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy")); + + if (aTab.__thumbnail) + return aTab.__thumbnail; + + if (aTab.getAttribute("pending") == "true") { + let img = new Image; + img.src = PageThumbs.getThumbnailURL(uri); + return img; + } + + return this.capture(aTab, !aTab.hasAttribute("busy")); }, + capture: function tabPreviews_capture(aTab, aStore) { - this.init(); - var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); thumbnail.mozOpaque = true; thumbnail.height = this.height; thumbnail.width = this.width; var ctx = thumbnail.getContext("2d"); var win = aTab.linkedBrowser.contentWindow; var snippetWidth = win.innerWidth * .6; @@ -56,16 +67,17 @@ var tabPreviews = { snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)"); if (aStore) { aTab.__thumbnail = thumbnail; aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec; } return thumbnail; }, + handleEvent: function tabPreviews_handleEvent(event) { switch (event.type) { case "TabSelect": if (this._selectedTab && this._selectedTab.parentNode && !this._pendingUpdate) { // Generate a thumbnail for the tab that was selected. // The timeout keeps the UI snappy and prevents us from generating thumbnails @@ -78,19 +90,16 @@ var tabPreviews = { self.capture(aTab, true); }, 2000, this, this._selectedTab); } this._selectedTab = event.target; break; case "SSTabRestored": this.capture(event.target, true); break; - case "unload": - this.uninit(); - break; } } }; var tabPreviewPanelHelper = { opening: function (host) { host.panel.hidden = false;
--- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -414,18 +414,18 @@ window[chromehidden~="toolbar"] toolbar: display: none; } /* ::::: Keyboard UI Panel ::::: */ .KUI-panel-closebutton { -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image"); } -.ctrlTab-preview > html|canvas, -.allTabs-preview > html|canvas { +:-moz-any(.ctrlTab-preview, .allTabs-preview) > html|img, +:-moz-any(.ctrlTab-preview, .allTabs-preview) > html|canvas { min-width: inherit; max-width: inherit; min-height: inherit; max-height: inherit; } .ctrlTab-favicon-container, .allTabs-favicon-container {
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -141,24 +141,24 @@ XPCOMUtils.defineLazyGetter(this, "Socia }); XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs", "resource:///modules/PageThumbs.jsm"); #ifdef MOZ_SAFE_BROWSING XPCOMUtils.defineLazyGetter(this, "SafeBrowsing", function() { let tmp = {}; - Cu.import("resource://gre/modules/SafeBrowsing.jsm", tmp); + Cu.import("resource:///modules/SafeBrowsing.jsm", tmp); return tmp.SafeBrowsing; }); #endif XPCOMUtils.defineLazyGetter(this, "gBrowserNewTabPreloader", function () { let tmp = {}; - Cu.import("resource://gre/modules/BrowserNewTabPreloader.jsm", tmp); + Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", tmp); return new tmp.BrowserNewTabPreloader(); }); let gInitialPages = [ "about:blank", "about:newtab", "about:home", "about:privatebrowsing",
--- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -394,20 +394,16 @@ label="&identity.moreInfoLinkText;" onblur="gIdentityHandler.hideIdentityPopup();" oncommand="gIdentityHandler.handleMoreInfoClick(event);"/> </hbox> </vbox> </hbox> </panel> - <tooltip id="urlTooltip"> - <label crop="center" flex="1" class="tooltip-label"/> - </tooltip> - <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top"> <hbox> <button class="ctrlTab-preview" flex="1"/> <button class="ctrlTab-preview" flex="1"/> <button class="ctrlTab-preview" flex="1"/> <button class="ctrlTab-preview" flex="1"/> <button class="ctrlTab-preview" flex="1"/> <button class="ctrlTab-preview" flex="1"/>
--- a/browser/base/content/tabbrowser.css +++ b/browser/base/content/tabbrowser.css @@ -48,8 +48,18 @@ tabpanels { .closing-tabs-spacer { pointer-events: none; } .tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer { transition: width .15s ease-out; } + +/** + * Optimization for tabs that are restored lazily. We can save a good amount of + * memory that to-be-restored tabs would otherwise consume simply by setting + * their browsers to 'display: none' as that will prevent them from having to + * create a presentation and the like. + */ +browser[pending] { + display: none; +}
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -3642,32 +3642,32 @@ this._dragTime = Date.now(); if (Date.now() >= this._dragTime + this._dragOverDelay) this.selectedItem = tab; ind.collapsed = true; return; } } - var newIndex = this._getDropIndex(event); var scrollRect = tabStrip.scrollClientRect; var rect = tabStrip.getBoundingClientRect(); var minMargin = scrollRect.left - rect.left; var maxMargin = Math.min(minMargin + scrollRect.width, scrollRect.right); if (!ltr) [minMargin, maxMargin] = [this.clientWidth - maxMargin, this.clientWidth - minMargin]; var newMargin; if (pixelsToScroll) { // if we are scrolling, put the drop indicator at the edge // so that it doesn't jump while scrolling newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin; } else { + let newIndex = this._getDropIndex(event); if (newIndex == this.childNodes.length) { let tabRect = this.childNodes[newIndex-1].getBoundingClientRect(); if (ltr) newMargin = tabRect.right - rect.left; else newMargin = rect.right - tabRect.left; } else {
--- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -53,18 +53,16 @@ this._prefs.addObserver("", this, false); this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll"); this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll"); this.completeDefaultIndex = this._prefs.getBoolPref("autoFill"); this.timeout = this._prefs.getIntPref("delay"); this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled"); this._mayTrimURLs = this._prefs.getBoolPref("trimURLs"); - this._urlTooltip = document.getElementById("urlTooltip"); - this.inputField.controllers.insertControllerAt(0, this._copyCutController); this.inputField.addEventListener("mousedown", this, false); this.inputField.addEventListener("mousemove", this, false); this.inputField.addEventListener("mouseout", this, false); this.inputField.addEventListener("overflow", this, false); this.inputField.addEventListener("underflow", this, false); const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; @@ -405,36 +403,23 @@ </method> <field name="_contentIsCropped">false</field> <method name="_initURLTooltip"> <body><![CDATA[ if (this.focused || !this._contentIsCropped) return; - if (this._tooltipTimer) - clearTimeout(this._tooltipTimer); - this._tooltipTimer = setTimeout(function (self) { - self._tooltipTimer = 0; - var label = self._urlTooltip.firstChild; - label.value = self.value; - var bO = self.boxObject; - self._urlTooltip.maxWidth = bO.width; - self._urlTooltip.showPopup(self, bO.screenX, bO.screenY + bO.height, "tooltip"); - }, 700, this); + this.inputField.setAttribute("tooltiptext", this.value); ]]></body> </method> <method name="_hideURLTooltip"> <body><![CDATA[ - if (this._tooltipTimer) { - clearTimeout(this._tooltipTimer); - this._tooltipTimer = 0; - } - this._urlTooltip.hidePopup(); + this.inputField.removeAttribute("tooltiptext"); ]]></body> </method> <method name="onDragOver"> <parameter name="aEvent"/> <body> var types = aEvent.dataTransfer.types; if (types.contains("application/x-moz-file") ||
--- a/browser/components/feeds/src/nsFeedSniffer.cpp +++ b/browser/components/feeds/src/nsFeedSniffer.cpp @@ -341,17 +341,17 @@ nsFeedSniffer::AppendSegmentToString(nsI nsCString* decodedData = static_cast<nsCString*>(closure); decodedData->Append(rawSegment, count); *writeCount = count; return NS_OK; } NS_IMETHODIMP nsFeedSniffer::OnDataAvailable(nsIRequest* request, nsISupports* context, - nsIInputStream* stream, uint32_t offset, + nsIInputStream* stream, uint64_t offset, uint32_t count) { uint32_t read; return stream->ReadSegments(AppendSegmentToString, &mDecodedData, count, &read); } NS_IMETHODIMP
--- a/browser/components/safebrowsing/Makefile.in +++ b/browser/components/safebrowsing/Makefile.in @@ -1,14 +1,14 @@ # 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/. -DEPTH = ../../.. +DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk TEST_DIRS += content/test
--- a/browser/components/safebrowsing/content/test/Makefile.in +++ b/browser/components/safebrowsing/content/test/Makefile.in @@ -1,18 +1,18 @@ # # 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/. -DEPTH = ../../../../.. +DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -relativesrcdir = browser/components/safebrowsing/content/test +relativesrcdir = @relativesrcdir@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk # The browser chrome test for bug 415846 doesn't run on Mac because of its # bizarre special-and-unique snowflake of a help menu. ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT)) _NON_MAC_BROWSER_TESTS = browser_bug415846.js
--- a/browser/components/sessionstore/src/SessionStore.jsm +++ b/browser/components/sessionstore/src/SessionStore.jsm @@ -2982,16 +2982,17 @@ let SessionStoreInternal = { this.xulAttributes[name] = true; browser.__SS_tabStillLoading = true; // keep the data around to prevent dataloss in case // a tab gets closed before it's been properly restored browser.__SS_data = tabData; browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE; + browser.setAttribute("pending", "true"); tab.setAttribute("pending", "true"); // Make sure that set/getTabValue will set/read the correct data by // wiping out any current value in tab.__SS_extdata. delete tab.__SS_extdata; if (!tabData.entries || tabData.entries.length == 0) { // make sure to blank out this tab's content @@ -3166,16 +3167,17 @@ let SessionStoreInternal = { // Make sure that this tab is removed from _tabsToRestore this._removeTabFromTabsToRestore(aTab); // Increase our internal count. this._tabsRestoringCount++; // Set this tab's state to restoring browser.__SS_restoreState = TAB_STATE_RESTORING; + browser.removeAttribute("pending"); aTab.removeAttribute("pending"); // Remove the history listener, since we no longer need it once we start restoring this._removeSHistoryListener(aTab); let activeIndex = (tabData.index || tabData.entries.length) - 1; if (activeIndex >= tabData.entries.length) activeIndex = tabData.entries.length - 1; @@ -4330,16 +4332,19 @@ let SessionStoreInternal = { let browser = aTab.linkedBrowser; // Keep the tab's previous state for later in this method let previousState = browser.__SS_restoreState; // The browser is no longer in any sort of restoring state. delete browser.__SS_restoreState; + aTab.removeAttribute("pending"); + browser.removeAttribute("pending"); + // We want to decrement window.__SS_tabsToRestore here so that we always // decrement it AFTER a tab is done restoring or when a tab gets "reset". window.__SS_tabsToRestore--; // Remove the progress listener if we should. this._removeTabsProgressListener(window); if (previousState == TAB_STATE_RESTORING) {
--- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -608,17 +608,17 @@ nsWindowsShellService::SetDefaultBrowser info.pcszClass = NULL; info.oaifInFlags = OAIF_FORCE_REGISTRATION | OAIF_URL_PROTOCOL | OAIF_REGISTER_EXT; nsresult rv = DynSHOpenWithDialog(NULL, &info); NS_ENSURE_SUCCESS(rv, rv); bool isDefaultBrowser = false; rv = NS_SUCCEEDED(IsDefaultBrowser(&isDefaultBrowser)) && - isDefaultBrowser ? S_OK : NS_ERROR_FAILURE; + isDefaultBrowser ? NS_OK : NS_ERROR_FAILURE; } return rv; } NS_IMETHODIMP nsWindowsShellService::GetShouldCheckDefaultBrowser(bool* aResult) { NS_ENSURE_ARG_POINTER(aResult);
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/common @@ -0,0 +1,7 @@ +# 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/. + +# This file is included by all browser mozconfigs + +. "$topsrcdir/build/mozconfig.common"
--- a/browser/config/mozconfigs/linux32/debug +++ b/browser/config/mozconfigs/linux32/debug @@ -17,8 +17,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4" #Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/debug-asan +++ b/browser/config/mozconfigs/linux32/debug-asan @@ -11,8 +11,10 @@ ac_add_options --enable-valgrind # Avoid dependency on libstdc++ 4.5 ac_add_options --enable-stdcxx-compat # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/l10n-mozconfig +++ b/browser/config/mozconfigs/linux32/l10n-mozconfig @@ -1,7 +1,9 @@ ac_add_options --with-l10n-base=../../l10n-central ac_add_options --enable-official-branding ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging . $topsrcdir/build/unix/mozconfig.linux + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/nightly +++ b/browser/config/mozconfigs/linux32/nightly @@ -31,8 +31,10 @@ ac_add_options --enable-warnings-as-erro # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/nightly-asan +++ b/browser/config/mozconfigs/linux32/nightly-asan @@ -13,8 +13,10 @@ ac_add_options --enable-codesighs # Avoid dependency on libstdc++ 4.5 ac_add_options --enable-stdcxx-compat # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/qt +++ b/browser/config/mozconfigs/linux32/qt @@ -21,8 +21,10 @@ ac_add_options --with-ccache=/usr/bin/cc # QT Options export PKG_CONFIG_PATH=/tools/qt-4.6.3/qt/lib/pkgconfig ac_add_options --with-qtdir=/tools/qt-4.6.3/qt ac_add_options --enable-default-toolkit=cairo-qt ac_add_options --disable-crashreporter # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/release +++ b/browser/config/mozconfigs/linux32/release @@ -19,8 +19,10 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/rpm +++ b/browser/config/mozconfigs/linux32/rpm @@ -24,8 +24,10 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" #Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/debug +++ b/browser/config/mozconfigs/linux64/debug @@ -17,8 +17,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4" # Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/debug-asan +++ b/browser/config/mozconfigs/linux64/debug-asan @@ -11,8 +11,10 @@ ac_add_options --enable-valgrind # Avoid dependency on libstdc++ 4.5 ac_add_options --enable-stdcxx-compat # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/l10n-mozconfig +++ b/browser/config/mozconfigs/linux64/l10n-mozconfig @@ -1,7 +1,9 @@ ac_add_options --with-l10n-base=../../l10n-central ac_add_options --enable-official-branding ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging . $topsrcdir/build/unix/mozconfig.linux + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/nightly +++ b/browser/config/mozconfigs/linux64/nightly @@ -31,8 +31,10 @@ ac_add_options --enable-warnings-as-erro # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/nightly-asan +++ b/browser/config/mozconfigs/linux64/nightly-asan @@ -13,8 +13,10 @@ ac_add_options --enable-codesighs # Avoid dependency on libstdc++ 4.5 ac_add_options --enable-stdcxx-compat # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/release +++ b/browser/config/mozconfigs/linux64/release @@ -19,8 +19,10 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/rpm +++ b/browser/config/mozconfigs/linux64/rpm @@ -24,8 +24,10 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" #Use ccache ac_add_options --with-ccache=/usr/bin/ccache # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/nightly +++ b/browser/config/mozconfigs/macosx-universal/nightly @@ -21,8 +21,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j12" ac_add_options --with-macbundlename-prefix=Firefox # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/release +++ b/browser/config/mozconfigs/macosx-universal/release @@ -15,8 +15,10 @@ export MOZ_TELEMETRY_REPORTING=1 # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j4" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/shark +++ b/browser/config/mozconfigs/macosx-universal/shark @@ -19,8 +19,10 @@ ac_add_options --enable-shark ac_add_options --enable-dtrace # Need this to prevent name conflicts with the normal nightly build packages export MOZ_PKG_SPECIAL="shark" # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors ac_add_options --with-ccache + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx32/debug +++ b/browser/config/mozconfigs/macosx32/debug @@ -1,16 +1,19 @@ . $topsrcdir/build/macosx/mozconfig.leopard + ac_add_options --enable-debug ac_add_options --enable-trace-malloc ac_add_options --enable-signmar ENABLE_MARIONETTE=1 # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j12" # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 ac_add_options --with-macbundlename-prefix=Firefox # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/debug +++ b/browser/config/mozconfigs/macosx64/debug @@ -1,9 +1,9 @@ -. $topsrcdir/build/macosx/common +. $topsrcdir/build/macosx/mozconfig.common ac_add_options --enable-debug ac_add_options --enable-trace-malloc ac_add_options --enable-accessibility ac_add_options --enable-signmar ENABLE_MARIONETTE=1 # Enable parallel compiling @@ -14,8 +14,10 @@ export MOZILLA_OFFICIAL=1 ac_add_options --with-macbundlename-prefix=Firefox # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/debug-asan +++ b/browser/config/mozconfigs/macosx64/debug-asan @@ -7,8 +7,10 @@ ac_add_options --enable-accessibility # Enable parallel compiling mk_add_options MOZ_MAKE_FLAGS="-j12" # Package js shell. export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-macbundlename-prefix=Firefox + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/l10n-mozconfig +++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig @@ -1,5 +1,9 @@ +. "$topsrcdir/browser/config/mozconfigs/common" + ac_add_options --with-l10n-base=../../l10n-central ac_add_options --enable-official-branding ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --with-ccache + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/debug +++ b/browser/config/mozconfigs/win32/debug @@ -1,8 +1,10 @@ +. "$topsrcdir/browser/config/mozconfigs/common" + ac_add_options --enable-debug ac_add_options --enable-trace-malloc ac_add_options --enable-signmar ENABLE_MARIONETTE=1 # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 @@ -15,8 +17,10 @@ fi if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then . $topsrcdir/build/win32/mozconfig.vs2010-win64 else . $topsrcdir/build/win32/mozconfig.vs2010 fi # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/l10n-mozconfig +++ b/browser/config/mozconfigs/win32/l10n-mozconfig @@ -1,10 +1,14 @@ +. "$topsrcdir/browser/config/mozconfigs/common" + ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-official-branding ac_add_options --with-l10n-base=../../l10n-central if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then . $topsrcdir/build/win32/mozconfig.vs2010-win64 else . $topsrcdir/build/win32/mozconfig.vs2010 fi + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/nightly +++ b/browser/config/mozconfigs/win32/nightly @@ -1,8 +1,10 @@ +. "$topsrcdir/browser/config/mozconfigs/common" + # for pgo mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py' ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-jemalloc ac_add_options --enable-signmar ac_add_options --enable-profiling @@ -24,8 +26,10 @@ fi if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then . $topsrcdir/build/win32/mozconfig.vs2010-win64 else . $topsrcdir/build/win32/mozconfig.vs2010 fi # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/release +++ b/browser/config/mozconfigs/win32/release @@ -1,8 +1,10 @@ +. "$topsrcdir/browser/config/mozconfigs/common" + # for pgo mk_add_options MOZ_PGO=1 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py' ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-jemalloc ac_add_options --enable-official-branding @@ -21,8 +23,10 @@ fi if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then . $topsrcdir/build/win32/mozconfig.vs2010-win64 else . $topsrcdir/build/win32/mozconfig.vs2010 fi # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/debug +++ b/browser/config/mozconfigs/win64/debug @@ -10,8 +10,10 @@ ENABLE_MARIONETTE=1 export MOZILLA_OFFICIAL=1 mk_add_options MOZ_MAKE_FLAGS=-j1 # Package js shell. export MOZ_PACKAGE_JSSHELL=1 . $topsrcdir/build/win64/mozconfig.vs2010 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/nightly +++ b/browser/config/mozconfigs/win64/nightly @@ -19,8 +19,10 @@ export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 mk_add_options MOZ_MAKE_FLAGS=-j1 # Package js shell. export MOZ_PACKAGE_JSSHELL=1 . $topsrcdir/build/win64/mozconfig.vs2010 + +. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/devtools/commandline/CmdCmd.jsm +++ b/browser/devtools/commandline/CmdCmd.jsm @@ -13,17 +13,17 @@ let prefSvc = "@mozilla.org/preferences- XPCOMUtils.defineLazyGetter(this, "prefBranch", function() { let prefService = Cc[prefSvc].getService(Ci.nsIPrefService); return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2); }); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource:///modules/devtools/Console.jsm"); + "resource://gre/modules/devtools/Console.jsm"); const PREF_DIR = "devtools.commands.dir"; /** * A place to store the names of the commands that we have added as a result of * calling refreshAutoCommands(). Used by refreshAutoCommands to remove the * added commands. */
--- a/browser/devtools/commandline/CmdCookie.jsm +++ b/browser/devtools/commandline/CmdCookie.jsm @@ -5,17 +5,17 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components; let EXPORTED_SYMBOLS = [ ]; Cu.import("resource:///modules/devtools/gcli.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource:///modules/devtools/Console.jsm"); + "resource://gre/modules/devtools/Console.jsm"); // We should really be using nsICookieManager so we can read more than just the // key/value of cookies. The difficulty is filtering the cookies that are // relevant to the current page. See // https://github.com/firebug/firebug/blob/master/extension/content/firebug/cookies/cookieObserver.js#L123 // For details on how this is done with Firebug /**
--- a/browser/extensions/Makefile.in +++ b/browser/extensions/Makefile.in @@ -2,34 +2,34 @@ # 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/. DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -CHROMEDIR = $(call core_abspath,$(DIST))/bin/chrome +CHROMEDIR = $(call core_abspath,$(FINAL_TARGET))/chrome include $(DEPTH)/config/autoconf.mk TEST_DIRS += pdfjs/test include $(topsrcdir)/config/rules.mk exclude_files = \ test \ install.rdf \ bootstrap.js \ icon.png \ icon64.png \ $(NULL) -$(DIST)/bin/chrome/pdfjs.manifest: $(GLOBAL_DEPS) +$(FINAL_TARGET)/chrome/pdfjs.manifest: $(GLOBAL_DEPS) printf "manifest pdfjs/chrome.manifest" > $@ -libs:: $(DIST)/bin/chrome/pdfjs.manifest +libs:: $(FINAL_TARGET)/chrome/pdfjs.manifest $(PYTHON) $(topsrcdir)/config/nsinstall.py \ $(srcdir)/pdfjs \ $(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \ - $(DIST)/bin/chrome + $(FINAL_TARGET)/chrome $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \ - $(DIST)/bin/chrome.manifest "manifest chrome/pdfjs.manifest" + $(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest"
--- a/browser/locales/Makefile.in +++ b/browser/locales/Makefile.in @@ -193,27 +193,29 @@ langpack: langpack-$(AB_CD) # This is a generic target that will make a langpack, repack ZIP (+tarball) # builds, and repack an installer if applicable. It is called from the # tinderbox scripts. Alter it with caution. installers-%: clobber-% langpack-% repackage-win32-installer-% repackage-zip-% @echo "repackaging done" ifdef MOZ_UPDATER +# Note that we want updater.ini to be in the top directory, not the browser/ +# subdirectory, because that's where the updater is installed and runs. libs:: $(call MERGE_FILE,updater/updater.ini) ifeq ($(OS_ARCH),WINNT) cat $< $(srcdir)/../installer/windows/nsis/updater_append.ini | \ sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \ sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \ - $(FINAL_TARGET)/updater.ini + $(DIST)/bin/updater.ini else cat $< | \ sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \ sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \ - $(FINAL_TARGET)/updater.ini + $(DIST)/bin/updater.ini endif endif ifdef MOZ_CRASHREPORTER libs:: crashreporter-override.ini $(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET) endif
deleted file mode 100644 --- a/build/macosx/common +++ /dev/null @@ -1,12 +0,0 @@ -if [ -d "$topsrcdir/clang" ]; then - # mozilla-central based build - export CC=$topsrcdir/clang/bin/clang - export CXX=$topsrcdir/clang/bin/clang++ -elif [ -d "$topsrcdir/../clang" ]; then - # comm-central based build - export CC=$topsrcdir/../clang/bin/clang - export CXX=$topsrcdir/../clang/bin/clang++ -fi - -ac_add_options --enable-stdcxx-compat -ac_add_options --with-ccache
new file mode 100644 --- /dev/null +++ b/build/macosx/mozconfig.common @@ -0,0 +1,18 @@ +# 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/. + +. "$topsrcdir/build/mozconfig.common" + +if [ -d "$topsrcdir/clang" ]; then + # mozilla-central based build + export CC=$topsrcdir/clang/bin/clang + export CXX=$topsrcdir/clang/bin/clang++ +elif [ -d "$topsrcdir/../clang" ]; then + # comm-central based build + export CC=$topsrcdir/../clang/bin/clang + export CXX=$topsrcdir/../clang/bin/clang++ +fi + +ac_add_options --enable-stdcxx-compat +ac_add_options --with-ccache
--- a/build/macosx/mozconfig.leopard +++ b/build/macosx/mozconfig.leopard @@ -1,11 +1,11 @@ -. $topsrcdir/build/macosx/common +. $topsrcdir/build/macosx/mozconfig.common -# Mac builds don't nomally have to be handled as cross +# Mac builds don't normally have to be handled as cross # compilation, but some of the libraries on the bots # (IDL for example) are built only for one arch. HOST_CC=$CC HOST_CXX=$CXX # These must be set for cross builds, and don't hurt straight builds. RANLIB=ranlib
--- a/build/macosx/universal/mozconfig.common +++ b/build/macosx/universal/mozconfig.common @@ -7,17 +7,17 @@ mk_add_options MOZ_UNIFY_BDATE=1 mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk # Note, the version (10) is used by libffi's configure. ac_add_app_options i386 --target=i386-apple-darwin10 ac_add_app_options x86_64 --target=x86_64-apple-darwin10 ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk -. $topsrcdir/build/macosx/common +. $topsrcdir/build/macosx/mozconfig.common # $MOZ_BUILD_APP is only defined when sourced by configure. That's not a # problem, because the variables it affects only need to be set for # configure. if test -n "$MOZ_BUILD_APP" ; then if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then TARGET_CPU=$MOZ_BUILD_APP
new file mode 100644 --- /dev/null +++ b/build/mozconfig.common @@ -0,0 +1,11 @@ +# 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/. + +# Common mozconfig for all users +# +# Add options to this file that will be inherited by all in-tree mozconfigs. +# This is useful for eg try builds with nondefault options that apply to all +# architectures, though note that if you want to override options set in +# another mozconfig file, you'll need to use mozconfig.common.override instead +# of this file.
new file mode 100644 --- /dev/null +++ b/build/mozconfig.common.override @@ -0,0 +1,11 @@ +# 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/. + +# Common mozconfig for all users +# +# Add options to this file that will be inherited by all in-tree mozconfigs. +# This file is included at the *end* of the mozconfigs, and so may be used +# to override anything done previously. +# +# The common expected usage is for try builds with nondefault options.
--- a/build/pymake/pymake/functions.py +++ b/build/pymake/pymake/functions.py @@ -766,19 +766,18 @@ class ShellFunction(Function): __slots__ = Function.__slots__ def resolve(self, makefile, variables, fd, setting): #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() cline = self._arguments[0].resolvestr(makefile, variables, setting) log.debug("%s: running shell command '%s'" % (self.loc, cline)) - if msys: - cline = [shell, "-c", cline] - p = subprocess.Popen(cline, env=makefile.env, shell=not msys, + cline = [shell, "-c", cline] + p = subprocess.Popen(cline, env=makefile.env, shell=False, stdout=subprocess.PIPE, cwd=makefile.workdir) stdout, stderr = p.communicate() stdout = stdout.replace('\r\n', '\n') if stdout.endswith('\n'): stdout = stdout[:-1] stdout = stdout.replace('\n', ' ')
--- a/build/pymake/pymake/process.py +++ b/build/pymake/pymake/process.py @@ -83,18 +83,18 @@ def call(cline, env, cwd, loc, cb, conte else: argv = doglobbing(argv, cwd) if shellreason is not None: _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline) if msys: if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] - cline = [shell, "-c", cline] - context.call(cline, shell=not msys, env=env, cwd=cwd, cb=cb, echo=echo, + cline = [shell, "-c", cline] + context.call(cline, shell=False, env=env, cwd=cwd, cb=cb, echo=echo, justprint=justprint) return if not len(argv): cb(res=0) return if argv[0] == command.makepypath:
--- a/build/unix/mozconfig.linux +++ b/build/unix/mozconfig.linux @@ -1,2 +1,4 @@ +. "$topsrcdir/build/mozconfig.common" + CC=/tools/gcc-4.5-0moz3/bin/gcc CXX=/tools/gcc-4.5-0moz3/bin/g++
--- a/config/Makefile.in +++ b/config/Makefile.in @@ -15,25 +15,23 @@ include $(DEPTH)/config/autoconf.mk # headers, so that we can use it to set up the wrapped system headers. VISIBILITY_FLAGS = # STDCXX_COMPAT is not needed here, and will actually fail because # libstdc++-compat is not built yet. STDCXX_COMPAT = ifneq (WINNT,$(HOST_OS_ARCH)) -HOST_PROGRAM = nsinstall$(HOST_BIN_SUFFIX) +HOST_PROGRAM = nsinstall_real$(HOST_BIN_SUFFIX) HOST_CSRCS = nsinstall.c pathsub.c endif -TARGETS = $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) - ifndef CROSS_COMPILE ifdef USE_ELF_DYNSTR_GC -TARGETS += elf-dynstr-gc +export:: elf-dynstr-gc # Compiling the above will create dependency files. NEED_MDDEPDIR = 1 endif endif # IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have # a recursive rule for finding nsinstall and the Perl scripts. ifdef NSBUILDROOT @@ -44,35 +42,46 @@ ifdef GNU_CC MODULE_OPTIMIZE_FLAGS = -O3 endif include $(topsrcdir)/config/config.mk # Do not install util programs NO_INSTALL=1 +ifneq (WINNT,$(HOST_OS_ARCH)) +# Ensure nsinstall is atomically created +nsinstall$(HOST_BIN_SUFFIX): $(HOST_PROGRAM) + cp $^ $@.tmp + mv $@.tmp $@ + +NSINSTALL_FILES := nsinstall$(HOST_BIN_SUFFIX) +NSINSTALL_DEST := $(DIST)/bin +NSINSTALL_TARGET := export +INSTALL_TARGETS += NSINSTALL +endif + +HEADERS_FILES = \ + $(DEPTH)/mozilla-config.h \ + $(srcdir)/nsStaticComponents.h \ + $(NULL) +HEADERS_DEST := $(DIST)/include +HEADERS_TARGET := export +INSTALL_TARGETS += HEADERS + include $(topsrcdir)/config/rules.mk HOST_CFLAGS += -DUNICODE -D_UNICODE ifeq ($(OS_CONFIG),SunOS4.1) NSPR_CFLAGS += -I$(srcdir)/../nsprpub/pr/include/md endif -HEADERS = \ - $(DEPTH)/mozilla-config.h \ - $(srcdir)/nsStaticComponents.h \ - $(NULL) - -export:: $(TARGETS) $(HEADERS) - $(INSTALL) $(IFLAGS1) $(HEADERS) $(DIST)/include +export:: -$(RM) $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) -ifdef HOST_PROGRAM - $(INSTALL) $(HOST_PROGRAM) $(DIST)/bin -endif # Generate a new buildid every time we "export" in config... that's only # supposed to be once per-build! export:: ifdef MOZ_BUILD_DATE printf "%s" $(MOZ_BUILD_DATE) > buildid else $(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid > buildid
--- a/config/makefiles/target_export.mk +++ b/config/makefiles/target_export.mk @@ -22,17 +22,17 @@ export_tier_%: ################# ifdef PARALLEL_DIRS export:: $(PARALLEL_DIRS_export) $(PARALLEL_DIRS_export): %_export: %/Makefile +@$(call SUBMAKE,export,$*) endif -export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR)) +export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(LOOP_OVER_DIRS) $(LOOP_OVER_TOOL_DIRS) # # Rule to create list of libraries for final link # # todo: use pre-req deps rather than conditionals
--- a/config/makefiles/test/Makefile.in +++ b/config/makefiles/test/Makefile.in @@ -15,34 +15,31 @@ USE_AUTOTARGETS_MK = 1 MAKEUTILS_UNIT_TEST = 1 include $(topsrcdir)/config/makefiles/makeutils.mk dir-ts = .deps/test check-arglist = $(dir-ts)/arglist.ts check-autotargets = $(dir-ts)/autotargets_mk.ts check-export-targets = $(dir-ts)/export-targets-mk.ts check-XinY = $(dir-ts)/check_XinY_mk.ts -check-xpidl = $(dir-ts)/xpidl-mk.ts check-tests =\ $(check-arglist) \ $(check-autotargets) \ $(check-export-targets) \ $(check-XinY) \ - $(check-xpidl) \ $(NULL) ##------------------_## ##---] TARGETS [---## ##------------------_## all:: clean: $(RM) $(check-tests) - @$(MAKE) --no-print-directory -f $(srcdir)/check-xpidl.mk clean-xpidl topsrcdir=$(topsrcdir) ########################################################################### ## Logic processed at compile time so be selective about when to test ## $(MAKE) check VERBOSE=1 ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) # check-preqs =\ $(call mkdir_deps,$(dir-ts)) \ @@ -119,28 +116,9 @@ check-export-targets-preqs=\ # include then test checkup: $(eval include $(srcdir)/check-export-targets.mk) $(check-export-targets): $(check-export-targets-preqs) @$(TOUCH) $@ # </CHECK: export-targets.mk> -########################################################################### -##{ <CHECK: xpidl.mk> -check-xpidl-preqs=\ - $(call mkdir_deps,$(dir-ts)) \ - $(topsrcdir)/config/config.mk \ - $(topsrcdir)/config/makefiles/makeutils.mk \ - $(topsrcdir)/config/makefiles/xpidl.mk \ - $(srcdir)/check-xpidl.mk \ - $(NULL) - -check-xpidl-args =\ - "topsrcdir=$(topsrcdir)" \ - "srcdir=$(srcdir)" \ - $(NULL) -$(check-xpidl): $(check-xpidl-preqs) - $(MAKE) -f $(srcdir)/check-xpidl.mk check-xpidl $(check-xpidl-args) - @$(TOUCH) $@ -#} </check-xpidl.mk> - endif #} findstring MAKECMDGOAL
deleted file mode 100644 --- a/config/makefiles/test/check-xpidl.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -*- makefile -*- -# -# 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/. - -ifdef VERBOSE - $(warning loading test) -endif - -# Limit scope, we only need install_cmd= for testing -INCLUDED_AUTOCONF_MK = 1 -include $(topsrcdir)/config/config.mk - -USE_AUTOTARGETS_MK = 1 -include $(topsrcdir)/config/makefiles/makeutils.mk - -basedir = blah -DIST = $(basedir)/dist -DI = $(DIST)/include -IDL_DIR = $(basedir)/idl -INSTALL := cp - -XPIDLSRCS = $(srcdir)/check-xpidl.mk - -include $(topsrcdir)/config/makefiles/xpidl.mk - - -$(call requiredfunction,topsrcdir) -$(call requiredfunction,XPIDL_GEN_DIR) - -HIDE=@ -check-xpidl: xpidl-install-src xpidl-install-headers - $(HIDE)test -d $(DIST) || exit 90 - $(HIDE)test -f $(DI)/check-xpidl.mk || exit 91 - $(HIDE)test -f $(IDL_DIR)/check-xpidl.mk || exit 92 - -# Declare targets to avoid including rules.mk -$(DI) $(IDL_DIR): - mkdir -p $@ - -clean-xpidl: - $(RM) -r $(basedir)
deleted file mode 100644 --- a/config/makefiles/xpidl.mk +++ /dev/null @@ -1,60 +0,0 @@ -# -*- makefile -*- -# vim:set ts=8 sw=8 sts=8 noet: -# -# 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/. -# - -# Always declared, general use by: -# js/xpconnect/tests/idl/Makefile.in:libs -# toolkit/crashreporter/test/Makefile.in -XPIDL_GEN_DIR ?= _xpidlgen -GARBAGE_DIRS += $(XPIDL_GEN_DIR) - - -########################################################################### -## Conditional logic -########################################################################### -ifndef INCLUDED_XPIDL_MK #{ - INCLUDED_XPIDL_MK = 1 - - ifneq (,$(XPIDLSRCS)) #{ - - ifndef NO_DIST_INSTALL #{ - _xpidl-todo_ += xpidl-install-src - _xpidl-todo_ += xpidl-install-headers - endif #} - - endif #} XPIDLSRCS - - export:: $(_xpidl-todo_) - - $(call requiredfunction,mkdir_deps) -endif #} INCLUDED_XPIDL_MK - - -########################################################################### -## processing targets -########################################################################### -ifdef _xpidl-todo_ #{ - -$(call requiredfunction,install_cmd) - -## Logic batch #1 -xpidl-install-src-preqs=\ - $(XPIDLSRCS) \ - $(call mkdir_deps,$(IDL_DIR)) \ - $(NULL) - -xpidl-install-src: $(xpidl-install-src-preqs) - $(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val)))) - -xpidl-install-headers-preqs =\ - $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) \ - $(call mkdir_deps,$(DIST)/include) \ - $(NULL) -xpidl-install-headers: $(xpidl-install-headers-preqs) - $(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val)))) - -endif #} _xpidl-todo_
--- a/config/rules.mk +++ b/config/rules.mk @@ -21,20 +21,22 @@ endif ifndef INCLUDED_VERSION_MK include $(topsrcdir)/config/version.mk endif USE_AUTOTARGETS_MK = 1 include $(topsrcdir)/config/makefiles/makeutils.mk ifdef SDK_XPIDLSRCS -XPIDLSRCS += $(SDK_XPIDLSRCS) +_EXTRA_XPIDLSRCS := $(filter-out $(XPIDLSRCS),$(SDK_XPIDLSRCS)) +XPIDLSRCS += $(_EXTRA_XPIDLSRCS) endif ifdef SDK_HEADERS -EXPORTS += $(SDK_HEADERS) +_EXTRA_EXPORTS := $(filter-out $(EXPORTS),$(SDK_HEADERS)) +EXPORTS += $(_EXTRA_EXPORTS) endif REPORT_BUILD = $(info $(notdir $<)) ifeq ($(OS_ARCH),OS2) EXEC = else EXEC = exec @@ -983,23 +985,17 @@ endif $(CCOBJS): %.$(OBJ_SUFFIX): %.cc $(REPORT_BUILD) @$(MAKE_DEPS_AUTO_CXX) $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) $(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp $(REPORT_BUILD) @$(MAKE_DEPS_AUTO_CXX) -ifdef STRICT_CPLUSPLUS_SUFFIX - echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc - $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc - $(RM) t_$*.cc -else $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) -endif #STRICT_CPLUSPLUS_SUFFIX $(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(REPORT_BUILD) @$(MAKE_DEPS_AUTO_CXX) $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) $(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(REPORT_BUILD) @@ -1154,25 +1150,29 @@ ifneq ($(XPI_NAME),) $(FINAL_TARGET): $(NSINSTALL) -D $@ export:: $(FINAL_TARGET) endif ifndef NO_DIST_INSTALL ifneq (,$(EXPORTS)) -export:: $(EXPORTS) - $(call install_cmd,$(IFLAGS1) $^ $(DIST)/include) +EXPORTS_FILES := $(EXPORTS) +EXPORTS_DEST := $(DIST)/include +EXPORTS_TARGET := export +INSTALL_TARGETS += EXPORTS endif endif # NO_DIST_INSTALL define EXPORT_NAMESPACE_RULE ifndef NO_DIST_INSTALL -export:: $(EXPORTS_$(namespace)) - $(call install_cmd,$(IFLAGS1) $$^ $(DIST)/include/$(namespace)) +EXPORTS_$(namespace)_FILES := $$(EXPORTS_$(namespace)) +EXPORTS_$(namespace)_DEST := $$(DIST)/include/$(namespace) +EXPORTS_$(namespace)_TARGET := export +INSTALL_TARGETS += EXPORTS_$(namespace) endif # NO_DIST_INSTALL endef $(foreach namespace,$(EXPORTS_NAMESPACES),$(eval $(EXPORT_NAMESPACE_RULE))) ################################################################################ # Copy each element of PREF_JS_EXPORTS @@ -1198,24 +1198,22 @@ PREF_JS_EXPORTS_FLAGS := $(PREF_PPFLAGS) PP_TARGETS += PREF_JS_EXPORTS endif endif ################################################################################ # Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig ifneq ($(AUTOCFG_JS_EXPORTS),) -$(FINAL_TARGET)/defaults/autoconfig:: - $(NSINSTALL) -D $@ - ifndef NO_DIST_INSTALL -export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig - $(call install_cmd,$(IFLAGS1) $^) +AUTOCFG_JS_EXPORTS_FILES := $(AUTOCFG_JS_EXPORTS) +AUTOCFG_JS_EXPORTS_DEST := $(FINAL_TARGET)/defaults/autoconfig +AUTOCFG_JS_EXPORTS_TARGET := export +INSTALL_TARGETS += AUTOCFG_JS_EXPORTS endif - endif ################################################################################ # Export the elements of $(XPIDLSRCS) # generating .h and .xpt files and moving them to the appropriate places. ifneq ($(XPIDLSRCS),) #{ @@ -1266,66 +1264,59 @@ xpidl-preqs = \ $(LIBXUL_DIST)/sdk/bin/typelib.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ # no need to link together if XPIDLSRCS contains only XPIDL_MODULE ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS))) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS) $(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) endif # XPIDL_MODULE.xpt != XPIDLSRCS -libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt ifndef NO_DIST_INSTALL - $(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components) +XPIDL_MODULE_FILES := $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt +XPIDL_MODULE_DEST := $(FINAL_TARGET)/components +INSTALL_TARGETS += XPIDL_MODULE + ifndef NO_INTERFACES_MANIFEST libs:: $(call mkdir_deps,$(FINAL_TARGET)/components) @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt" @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest" endif endif GARBAGE_DIRS += $(XPIDL_GEN_DIR) -endif #} XPIDLSRCS - - -ifndef INCLUDED_XPIDL_MK - include $(topsrcdir)/config/makefiles/xpidl.mk -endif - - -# General rules for exporting idl files. -$(IDL_DIR): - $(NSINSTALL) -D $@ +ifndef NO_DIST_INSTALL +XPIDL_HEADERS_FILES := $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) +XPIDL_HEADERS_DEST := $(DIST)/include +XPIDL_HEADERS_TARGET := export +INSTALL_TARGETS += XPIDL_HEADERS -export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS) - -ifneq ($(XPIDLSRCS),) -ifndef NO_DIST_INSTALL -export-idl:: $(XPIDLSRCS) $(IDL_DIR) - $(call install_cmd,$(IFLAGS1) $^) +XPIDLSRCS_FILES := $(XPIDLSRCS) +XPIDLSRCS_DEST := $(IDL_DIR) +XPIDLSRCS_TARGET := export +INSTALL_TARGETS += XPIDLSRCS endif -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) +endif #} XPIDLSRCS ################################################################################ # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) ifndef NO_JS_MANIFEST $(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0) endif endif endif ifdef EXTRA_COMPONENTS libs:: $(EXTRA_COMPONENTS) ifndef NO_DIST_INSTALL - $(call install_cmd,$(IFLAGS1) $^ $(FINAL_TARGET)/components) +EXTRA_COMPONENTS_FILES := $(EXTRA_COMPONENTS) +EXTRA_COMPONENTS_DEST := $(FINAL_TARGET)/components +INSTALL_TARGETS += EXTRA_COMPONENTS endif endif ifdef EXTRA_PP_COMPONENTS ifndef NO_DIST_INSTALL EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components PP_TARGETS += EXTRA_PP_COMPONENTS @@ -1339,21 +1330,21 @@ libs:: $(call mkdir_deps,$(FINAL_TARGET) endif ################################################################################ # Copy each element of EXTRA_JS_MODULES to JS_MODULES_PATH, or # $(FINAL_TARGET)/modules if that isn't defined. JS_MODULES_PATH ?= $(FINAL_TARGET)/modules ifdef EXTRA_JS_MODULES -libs:: $(EXTRA_JS_MODULES) ifndef NO_DIST_INSTALL - $(call install_cmd,$(IFLAGS1) $^ $(JS_MODULES_PATH)) +EXTRA_JS_MODULES_FILES := $(EXTRA_JS_MODULES) +EXTRA_JS_MODULES_DEST := $(JS_MODULES_PATH) +INSTALL_TARGETS += EXTRA_JS_MODULES endif - endif ifdef EXTRA_PP_JS_MODULES ifndef NO_DIST_INSTALL EXTRA_PP_JS_MODULES_PATH := $(JS_MODULES_PATH) PP_TARGETS += EXTRA_PP_JS_MODULES endif endif @@ -1365,46 +1356,41 @@ endif # objdir/_tests/modules/. If TESTING_JS_MODULE_DIR is defined, that path # wlll be appended to the output directory. ifdef TESTING_JS_MODULES testmodulesdir = $(DEPTH)/_tests/modules/$(TESTING_JS_MODULE_DIR) GENERATED_DIRS += $(testmodulesdir) -libs:: $(TESTING_JS_MODULES) ifndef NO_DIST_INSTALL - $(call install_cmd,$(IFLAGS) $^ $(testmodulesdir)) +TESTING_JS_MODULES_FILES := $(TESTING_JS_MODULES) +TESTING_JS_MODULES_DEST := $(testmodulesdir) +INSTALL_TARGETS += TESTING_JS_MODULES endif endif ################################################################################ # SDK ifneq (,$(SDK_LIBRARY)) -$(SDK_LIB_DIR):: - $(NSINSTALL) -D $@ - ifndef NO_DIST_INSTALL -libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR) - $(call install_cmd,$(IFLAGS2) $^) +SDK_LIBRARY_FILES := $(SDK_LIBRARY) +SDK_LIBRARY_DEST := $(SDK_LIB_DIR) +INSTALL_TARGETS += SDK_LIBRARY endif - endif # SDK_LIBRARY ifneq (,$(strip $(SDK_BINARY))) -$(SDK_BIN_DIR):: - $(NSINSTALL) -D $@ - ifndef NO_DIST_INSTALL -libs:: $(SDK_BINARY) $(SDK_BIN_DIR) - $(call install_cmd,$(IFLAGS2) $^) +SDK_BINARY_FILES := $(SDK_BINARY) +SDK_BINARY_DEST := $(SDK_BIN_DIR) +INSTALL_TARGETS += SDK_BINARY endif - endif # SDK_BINARY ################################################################################ # CHROME PACKAGING JAR_MANIFEST := $(srcdir)/jar.mn chrome:: @@ -1530,61 +1516,78 @@ TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS) $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS) endif endif ################################################################################ # Install/copy rules # # The INSTALL_TARGETS variable contains a list of all install target -# categories. Each category defines a list of files, an install destination, -# and whether the files are executables or not. +# categories. Each category defines a list of files and executables, and an +# install destination, # # FOO_FILES := foo bar # FOO_EXECUTABLES := baz # FOO_DEST := target_path # INSTALL_TARGETS += FOO +# +# Additionally, a FOO_TARGET variable may be added to indicate the target for +# which the files and executables are installed. Default is "libs". + +# If we're using binary nsinstall and it's not built yet, fallback to python nsinstall. +ifneq (,$(filter $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd))) +nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),$(eval nsinstall_is_usable := yes)yes) + +define install_cmd_override +$(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1) +endef +endif + define install_file_template -libs:: $(2)/$(notdir $(1)) +$(or $(3),libs):: $(2)/$(notdir $(1)) +$(call install_cmd_override,$(2)/$(notdir $(1))) $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) - $(INSTALL) $(3) $$< $${@D} + $$(call install_cmd,$(4) $$< $${@D}) endef $(foreach category,$(INSTALL_TARGETS),\ $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\ $(foreach file,$($(category)_FILES),\ - $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS1)))\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\ )\ $(foreach file,$($(category)_EXECUTABLES),\ - $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS2)))\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\ )\ ) ################################################################################ # Preprocessing rules # # The PP_TARGETS variable contains a list of all preprocessing target # categories. Each category defines a target path, and optional extra flags # like the following: # # FOO_PATH := target_path # FOO_FLAGS := -Dsome_flag # PP_TARGETS += FOO +# +# Additionally, a FOO_TARGET variable may be added to indicate the target for +# which the files and executables are installed. Default is "libs". # preprocess_file_template defines preprocessing rules. # $(call preprocess_file_template, source_file, target_path, extra_flags) define preprocess_file_template $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) $$(GLOBAL_DEPS) $$(RM) $$@ - $$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(3) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@ -libs:: $(2)/$(notdir $(1)) + $$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@ +$(or $(3),libs):: $(2)/$(notdir $(1)) endef $(foreach category,$(PP_TARGETS),\ $(foreach file,$($(category)),\ - $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_FLAGS)))\ + $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_TARGET),$($(category)_FLAGS)))\ )\ ) ################################################################################ # Special gmake rules. ################################################################################
--- a/configure.in +++ b/configure.in @@ -186,17 +186,17 @@ if test -n "$gonkdir" ; then arm) ARCH_DIR=arch-arm ;; i?86) ARCH_DIR=arch-x86 ;; esac - CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera -I$gonkdir/system/media/wilhelm/include" + CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera -I$gonkdir/system/media/wilhelm/include" CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS" dnl Add -llog by default, since we use it all over the place. LIBS="$LIBS -llog $STLPORT_LIBS" LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ $LDFLAGS" dnl prevent cross compile section from using these flags as host flags @@ -3849,48 +3849,49 @@ else NSPR_CFLAGS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --includedir="${LIBXUL_DIST}/include/nspr" --cflags` NSPR_LIBS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --libdir="${LIBXUL_DIST}"/lib --libs` fi fi dnl system libevent Support dnl ======================================================== MOZ_ARG_WITH_STRING(system-libevent, -[ --with-system-libevent=[PFX] +[ --with-system-libevent[=PFX] Use system libevent [installed at prefix PFX]], LIBEVENT_DIR=$withval) _SAVE_CFLAGS=$CFLAGS _SAVE_LDFLAGS=$LDFLAGS _SAVE_LIBS=$LIBS if test -z "$LIBEVENT_DIR" -o "$LIBEVENT_DIR" = no; then MOZ_NATIVE_LIBEVENT= +elif test "$LIBEVENT_DIR" = yes; then + PKG_CHECK_MODULES(MOZ_LIBEVENT, libevent, + MOZ_NATIVE_LIBEVENT=1, + AC_MSG_ERROR([--with-system-libevent requested but libevent package not found])) else - if test "${LIBEVENT_DIR}" = "yes"; then - LIBEVENT_DIR=/usr - fi CFLAGS="-I${LIBEVENT_DIR}/include $CFLAGS" LDFLAGS="-L${LIBEVENT_DIR}/lib $LDFLAGS" MOZ_CHECK_HEADER(event.h, [if test ! -f "${LIBEVENT_DIR}/include/event.h"; then AC_MSG_ERROR([event.h found, but is not in ${LIBEVENT_DIR}/include]) fi], AC_MSG_ERROR([--with-system-libevent requested but event.h not found])) AC_CHECK_LIB(event, event_init, [MOZ_NATIVE_LIBEVENT=1 - MOZ_LIBEVENT_INCLUDES="${LIBEVENT_DIR}/include" + MOZ_LIBEVENT_CFLAGS="-I${LIBEVENT_DIR}/include" MOZ_LIBEVENT_LIBS="-L${LIBEVENT_DIR}/lib -levent"], - [MOZ_NATIVE_LIBEVENT= MOZ_LIBEVENT_INCLUDES= MOZ_LIBEVENT_LIBS=]) + [MOZ_NATIVE_LIBEVENT= MOZ_LIBEVENT_CFLAGS= MOZ_LIBEVENT_LIBS=]) fi CFLAGS=$_SAVE_CFLAGS LDFLAGS=$_SAVE_LDFLAGS LIBS=$_SAVE_LIBS AC_SUBST(MOZ_NATIVE_LIBEVENT) -AC_SUBST(MOZ_LIBEVENT_INCLUDES) +AC_SUBST(MOZ_LIBEVENT_CFLAGS) AC_SUBST(MOZ_LIBEVENT_LIBS) dnl ======================================================== dnl = If NSS was not detected in the system, dnl = use the one in the source tree (mozilla/security/nss) dnl ======================================================== MOZ_ARG_WITH_BOOL(system-nss,
--- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -37,16 +37,17 @@ nsContentCID.h \ nsCopySupport.h \ nsContentCreatorFunctions.h \ nsDOMFile.h \ nsLineBreaker.h \ nsReferencedElement.h \ nsTreeSanitizer.h \ nsXMLNameSpaceMap.h \ nsIXFormsUtilityService.h \ +nsBlobProtocolHandler.h \ $(NULL) EXPORTS_NAMESPACES = mozilla/dom mozilla EXPORTS_mozilla/dom = \ DirectionalityUtils.h \ Element.h \ FragmentOrElement.h \
new file mode 100644 --- /dev/null +++ b/content/base/public/nsBlobProtocolHandler.h @@ -0,0 +1,51 @@ +/* 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/. */ + +#ifndef nsBlobProtocolHandler_h +#define nsBlobProtocolHandler_h + +#include "nsIProtocolHandler.h" +#include "nsIURI.h" +#include "nsCOMPtr.h" + +#define BLOBURI_SCHEME "blob" + +class nsIDOMBlob; +class nsIPrincipal; +class nsIInputStream; + +inline bool IsBlobURI(nsIURI* aUri) +{ + bool isBlob; + return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob; +} + +extern nsresult +NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream); + +class nsBlobProtocolHandler : public nsIProtocolHandler +{ +public: + NS_DECL_ISUPPORTS + + // nsIProtocolHandler methods: + NS_DECL_NSIPROTOCOLHANDLER + + // nsBlobProtocolHandler methods: + nsBlobProtocolHandler() {} + virtual ~nsBlobProtocolHandler() {} + + // Methods for managing uri->file mapping + static void AddFileDataEntry(nsACString& aUri, + nsIDOMBlob* aFile, + nsIPrincipal* aPrincipal); + static void RemoveFileDataEntry(nsACString& aUri); + static nsIPrincipal* GetFileDataEntryPrincipal(nsACString& aUri); +}; + +#define NS_BLOBPROTOCOLHANDLER_CID \ +{ 0xb43964aa, 0xa078, 0x44b2, \ + { 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } } + +#endif /* nsBlobProtocolHandler_h */
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -13,27 +13,16 @@ #if defined(XP_WIN) || defined(XP_OS2) #include <float.h> #endif #if defined(SOLARIS) #include <ieeefp.h> #endif -//A trick to handle IEEE floating point exceptions on FreeBSD - E.D. -#ifdef __FreeBSD__ -#include <ieeefp.h> -#if !defined(__i386__) && !defined(__x86_64__) -static fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP; -#else -static fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP|FP_X_DNML; -#endif -static fp_except_t oldmask = fpsetmask(~allmask); -#endif - #include "nsAString.h" #include "nsIStatefulFrame.h" #include "nsNodeInfoManager.h" #include "nsIXPCScriptable.h" #include "nsDataHashtable.h" #include "nsIDOMEvent.h" #include "nsTArray.h" #include "nsReadableUtils.h" @@ -41,16 +30,18 @@ static fp_except_t oldmask = fpsetmask(~ #include "nsIDOMNode.h" #include "nsHtml5StringParser.h" #include "nsIDocument.h" #include "nsContentSink.h" #include "nsMathUtils.h" #include "nsThreadUtils.h" #include "nsIContent.h" #include "nsCharSeparatedTokenizer.h" +#include "gfxContext.h" +#include "gfxFont.h" #include "mozilla/AutoRestore.h" #include "mozilla/GuardObjects.h" #include "mozilla/TimeStamp.h" struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error! class nsIDOMScriptObjectFactory; @@ -108,16 +99,17 @@ class nsIMIMEHeaderParam; class nsIObserver; class nsPresContext; class nsIChannel; class nsAutoScriptBlockerSuppressNodeRemoved; struct nsIntMargin; class nsPIDOMWindow; class nsIDocumentLoaderFactory; class nsIDOMHTMLInputElement; +class gfxTextObjectPaint; namespace mozilla { class Selection; namespace layers { class LayerManager; } // namespace layers @@ -2078,16 +2070,23 @@ public: */ static void GetSelectionInTextControl(mozilla::Selection* aSelection, Element* aRoot, int32_t& aOutStartOffset, int32_t& aOutEndOffset); static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext); + static bool PaintSVGGlyph(Element *aElement, gfxContext *aContext, + gfxFont::DrawMode aDrawMode, + gfxTextObjectPaint *aObjectPaint); + + static bool GetSVGGlyphExtents(Element *aElement, const gfxMatrix& aSVGToAppSpace, + gfxRect *aResult); + private: static bool InitializeEventTable(); static nsresult EnsureStringBundle(PropertiesFile aFile); static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal, nsIPrincipal* aPrincipal);
--- a/content/base/src/FileIOObject.cpp +++ b/content/base/src/FileIOObject.cpp @@ -160,17 +160,17 @@ FileIOObject::DoOnStartRequest(nsIReques { return NS_OK; } NS_IMETHODIMP FileIOObject::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { nsresult rv; rv = DoOnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount); NS_ENSURE_SUCCESS(rv, rv); mTransferred += aCount;
--- a/content/base/src/FileIOObject.h +++ b/content/base/src/FileIOObject.h @@ -63,17 +63,17 @@ protected: // special handling NS_IMETHOD DoOnStartRequest(nsIRequest *aRequest, nsISupports *aContext); // for onStopRequest NS_IMETHOD DoOnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatus, nsAString& aSuccessEvent, nsAString& aTerminationEvent) = 0; // and for onDataAvailable NS_IMETHOD DoOnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, - nsIInputStream *aInputStream, uint32_t aOffset, + nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) = 0; void StartProgressEventTimer(); void ClearProgressEventTimer(); void DispatchError(nsresult rv, nsAString& finalEvent); nsresult DispatchProgressEvent(const nsAString& aType); nsCOMPtr<nsITimer> mProgressNotifier;
--- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -176,16 +176,17 @@ INCLUDES += \ -I$(srcdir)/../../../layout/xul/base/src \ -I$(srcdir)/../../xul/content/src \ -I$(srcdir)/../../xul/document/src \ -I$(srcdir)/../../html/content/src \ -I$(srcdir)/../../base/src \ -I$(srcdir)/../../xbl/src \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ + -I$(srcdir)/../../../layout/svg/base/src \ -I$(srcdir)/../../../dom/base \ -I$(srcdir)/../../xml/document/src \ -I$(topsrcdir)/xpcom/io \ -I$(topsrcdir)/dom/ipc \ -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/caps/include \ -I$(topsrcdir)/netwerk/base/src \ $(NULL)
--- a/content/base/src/nsAttrAndChildArray.cpp +++ b/content/base/src/nsAttrAndChildArray.cpp @@ -559,18 +559,17 @@ nsAttrAndChildArray::SetAndTakeMappedAtt bool willAdd = true; if (mImpl && mImpl->mMappedAttrs) { willAdd = !mImpl->mMappedAttrs->GetAttr(aLocalName); } nsRefPtr<nsMappedAttributes> mapped = GetModifiableMapped(aContent, aSheet, willAdd); - nsresult rv = mapped->SetAndTakeAttr(aLocalName, aValue); - NS_ENSURE_SUCCESS(rv, rv); + mapped->SetAndTakeAttr(aLocalName, aValue); return MakeMappedUnique(mapped); } nsresult nsAttrAndChildArray::DoSetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) { NS_PRECONDITION(mImpl && mImpl->mMappedAttrs,
--- a/content/base/src/nsBlobProtocolHandler.cpp +++ b/content/base/src/nsBlobProtocolHandler.cpp @@ -158,18 +158,18 @@ nsBlobProtocolHandler::NewChannel(nsIURI #endif nsCOMPtr<nsIInputStream> stream; nsresult rv = info->mFile->GetInternalStream(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIChannel> channel; rv = NS_NewInputStreamChannel(getter_AddRefs(channel), - uri, - stream); + uri, + stream); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal); nsAutoString type; rv = info->mFile->GetType(type); NS_ENSURE_SUCCESS(rv, rv); @@ -190,8 +190,28 @@ nsBlobProtocolHandler::NewChannel(nsIURI NS_IMETHODIMP nsBlobProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval) { // don't override anything. *_retval = false; return NS_OK; } + +nsresult +NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream) +{ + NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs"); + + *aStream = nullptr; + + nsCString spec; + aURI->GetSpec(spec); + + FileDataInfo* info = + GetFileDataInfo(spec); + + if (!info) { + return NS_ERROR_DOM_BAD_URI; + } + + return info->mFile->GetInternalStream(aStream); +}
--- a/content/base/src/nsBlobProtocolHandler.h +++ b/content/base/src/nsBlobProtocolHandler.h @@ -1,40 +1,51 @@ /* 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/. */ #ifndef nsBlobProtocolHandler_h #define nsBlobProtocolHandler_h #include "nsIProtocolHandler.h" +#include "nsIURI.h" +#include "nsCOMPtr.h" #define BLOBURI_SCHEME "blob" class nsIDOMBlob; class nsIPrincipal; +class nsIInputStream; + +inline bool IsBlobURI(nsIURI* aUri) +{ + bool isBlob; + return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob; +} + +extern nsresult +NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream); class nsBlobProtocolHandler : public nsIProtocolHandler { public: NS_DECL_ISUPPORTS // nsIProtocolHandler methods: NS_DECL_NSIPROTOCOLHANDLER // nsBlobProtocolHandler methods: nsBlobProtocolHandler() {} virtual ~nsBlobProtocolHandler() {} // Methods for managing uri->file mapping static void AddFileDataEntry(nsACString& aUri, - nsIDOMBlob* aFile, + nsIDOMBlob* aFile, nsIPrincipal* aPrincipal); static void RemoveFileDataEntry(nsACString& aUri); static nsIPrincipal* GetFileDataEntryPrincipal(nsACString& aUri); - }; #define NS_BLOBPROTOCOLHANDLER_CID \ { 0xb43964aa, 0xa078, 0x44b2, \ { 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } } #endif /* nsBlobProtocolHandler_h */
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -117,16 +117,20 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_ #include "nsIViewManager.h" #include "nsEventStateManager.h" #include "nsIDOMHTMLInputElement.h" #include "nsParserConstants.h" #include "nsIWebNavigation.h" #include "nsILoadContext.h" #include "nsTextFragment.h" #include "mozilla/Selection.h" +#include "nsSVGUtils.h" +#include "nsISVGChildFrame.h" +#include "nsRenderingContext.h" +#include "gfxSVGGlyphs.h" #ifdef IBMBIDI #include "nsIBidiKeyboard.h" #endif #include "nsCycleCollectionParticipant.h" // for ReportToConsole #include "nsIStringBundle.h" @@ -3593,31 +3597,49 @@ nsContentUtils::ConvertStringFromCharset nsCOMPtr<nsIUnicodeDecoder> decoder; rv = ccm->GetUnicodeDecoder(PromiseFlatCString(aCharset).get(), getter_AddRefs(decoder)); if (NS_FAILED(rv)) return rv; nsPromiseFlatCString flatInput(aInput); - int32_t srcLen = flatInput.Length(); - int32_t dstLen; - rv = decoder->GetMaxLength(flatInput.get(), srcLen, &dstLen); + int32_t length = flatInput.Length(); + int32_t outLen; + rv = decoder->GetMaxLength(flatInput.get(), length, &outLen); if (NS_FAILED(rv)) return rv; - PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((dstLen + 1) * + PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((outLen + 1) * sizeof(PRUnichar)); if (!ustr) return NS_ERROR_OUT_OF_MEMORY; - rv = decoder->Convert(flatInput.get(), &srcLen, ustr, &dstLen); - if (NS_SUCCEEDED(rv)) { + const char* data = flatInput.get(); + aOutput.Truncate(); + for (;;) { + int32_t srcLen = length; + int32_t dstLen = outLen; + rv = decoder->Convert(data, &srcLen, ustr, &dstLen); + // Convert will convert the input partially even if the status + // indicates a failure. ustr[dstLen] = 0; - aOutput.Assign(ustr, dstLen); + aOutput.Append(ustr, dstLen); + if (rv != NS_ERROR_ILLEGAL_INPUT) { + break; + } + // Emit a decode error manually because some decoders + // do not support kOnError_Recover (bug 638379) + if (srcLen == -1) { + decoder->Reset(); + } else { + data += srcLen + 1; + length -= srcLen + 1; + aOutput.Append(static_cast<PRUnichar>(0xFFFD)); + } } nsMemory::Free(ustr); return rv; } /* static */ bool @@ -6922,16 +6944,70 @@ nsContentUtils::JSArrayToAtomArray(JSCon if (!a) { return NS_ERROR_OUT_OF_MEMORY; } aRetVal.AppendObject(a); } return NS_OK; } +/* static */ +bool +nsContentUtils::PaintSVGGlyph(Element *aElement, gfxContext *aContext, + gfxFont::DrawMode aDrawMode, + gfxTextObjectPaint *aObjectPaint) +{ + nsIFrame *frame = aElement->GetPrimaryFrame(); + if (!frame) { + NS_WARNING("No frame for SVG glyph"); + return false; + } + + nsISVGChildFrame *displayFrame = do_QueryFrame(frame); + if (!displayFrame) { + NS_WARNING("Non SVG frame for SVG glyph"); + return false; + } + + nsRenderingContext context; + + context.Init(frame->PresContext()->DeviceContext(), aContext); + context.AddUserData(&gfxTextObjectPaint::sUserDataKey, aObjectPaint, nullptr); + + nsresult rv = displayFrame->PaintSVG(&context, nullptr); + NS_ENSURE_SUCCESS(rv, false); + + return true; +} + +/* static */ +bool +nsContentUtils::GetSVGGlyphExtents(Element *aElement, const gfxMatrix& aSVGToAppSpace, + gfxRect *aResult) +{ + nsIFrame *frame = aElement->GetPrimaryFrame(); + if (!frame) { + NS_WARNING("No frame for SVG glyph"); + return false; + } + + nsISVGChildFrame *displayFrame = do_QueryFrame(frame); + if (!displayFrame) { + NS_WARNING("Non SVG frame for SVG glyph"); + return false; + } + + *aResult = displayFrame->GetBBoxContribution(aSVGToAppSpace, + nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeFillGeometry | + nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeStrokeGeometry | + nsSVGUtils::eBBoxIncludeMarkers); + + return true; +} + // static void nsContentUtils::GetSelectionInTextControl(Selection* aSelection, Element* aRoot, int32_t& aOutStartOffset, int32_t& aOutEndOffset) { MOZ_ASSERT(aSelection && aRoot);
--- a/content/base/src/nsCrossSiteListenerProxy.cpp +++ b/content/base/src/nsCrossSiteListenerProxy.cpp @@ -609,17 +609,17 @@ nsCORSListenerProxy::OnStopRequest(nsIRe mNewRedirectChannel = nullptr; return rv; } NS_IMETHODIMP nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aInputStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { if (!mRequestApproved) { return NS_ERROR_DOM_BAD_URI; } return mOuterListener->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount); } @@ -1001,17 +1001,17 @@ nsCORSPreflightListener::OnStopRequest(n } /** nsIStreamListener methods **/ NS_IMETHODIMP nsCORSPreflightListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, - uint32_t sourceOffset, + uint64_t sourceOffset, uint32_t count) { uint32_t totalRead; return inStr->ReadSegments(NS_DiscardSegment, nullptr, count, &totalRead); } NS_IMETHODIMP nsCORSPreflightListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
--- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -281,24 +281,27 @@ ReadFuncBinaryString(nsIInputStream* in, return NS_OK; } nsresult nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { if (mDataFormat == FILE_AS_BINARY) { //Continuously update our binary string as data comes in NS_ASSERTION(mResult.Length() == aOffset, "unexpected mResult length"); uint32_t oldLen = mResult.Length(); + if (uint64_t(oldLen) + aCount > PR_UINT32_MAX) + return NS_ERROR_OUT_OF_MEMORY; + PRUnichar *buf = nullptr; mResult.GetMutableData(&buf, oldLen + aCount, fallible_t()); NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); uint32_t bytesRead = 0; aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); @@ -306,16 +309,20 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe else if (mDataFormat == FILE_AS_ARRAYBUFFER) { uint32_t bytesRead = 0; aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer, NULL) + aOffset, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); } else { //Update memory buffer to reflect the contents of the file + if (aOffset + aCount > PR_UINT32_MAX) { + // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS + return NS_ERROR_OUT_OF_MEMORY; + } mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount); NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY); uint32_t bytesRead = 0; aInputStream->Read(mFileData + aOffset, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); mDataLen += aCount;
--- a/content/base/src/nsDOMFileReader.h +++ b/content/base/src/nsDOMFileReader.h @@ -52,17 +52,17 @@ public: uint32_t argc, jsval* argv); // FileIOObject overrides NS_IMETHOD DoAbort(nsAString& aEvent); NS_IMETHOD DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus, nsAString& aSuccessEvent, nsAString& aTerminationEvent); NS_IMETHOD DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, - nsIInputStream* aInputStream, uint32_t aOffset, + nsIInputStream* aInputStream, uint64_t aOffset, uint32_t aCount); nsresult Init(); NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader, FileIOObject) void RootResultArrayBuffer();
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1018,17 +1018,17 @@ nsExternalResourceMap::PendingLoad::Setu newLoadGroup.forget(aLoadGroup); return NS_OK; } NS_IMETHODIMP nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!"); if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) { return NS_BINDING_ABORTED; } return mTargetListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
--- a/content/base/src/nsEventSource.cpp +++ b/content/base/src/nsEventSource.cpp @@ -532,17 +532,17 @@ nsEventSource::StreamReaderFunc(nsIInput *aWriteCount = aCount; return NS_OK; } NS_IMETHODIMP nsEventSource::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { NS_ENSURE_ARG_POINTER(aInputStream); nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); uint32_t totalRead;
--- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -86,16 +86,20 @@ #include "nsIAppsService.h" #include "jsapi.h" #include "nsHTMLIFrameElement.h" #include "nsSandboxFlags.h" #include "mozilla/dom/StructuredCloneUtils.h" +#ifdef MOZ_XUL +#include "nsXULPopupManager.h" +#endif + using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layers; using namespace mozilla::layout; typedef FrameMetrics::ViewID ViewID; class nsAsyncDocShellDestroyer : public nsRunnable { @@ -301,16 +305,17 @@ nsFrameLoader::nsFrameLoader(Element* aO , mHideCalled(false) , mNetworkCreated(aNetworkCreated) , mDelayRemoteDialogs(false) , mRemoteBrowserShown(false) , mRemoteFrame(false) , mClipSubdocument(true) , mClampScrollPosition(true) , mRemoteBrowserInitialized(false) + , mObservingOwnerContent(false) , mCurrentRemoteFrame(nullptr) , mRemoteBrowser(nullptr) , mRenderMode(RENDER_MODE_DEFAULT) , mEventMode(EVENT_MODE_NORMAL_DISPATCH) { } nsFrameLoader* @@ -652,52 +657,47 @@ SetTreeOwnerAndChromeEventHandlerOnDocsh aItem->GetChildAt(i, getter_AddRefs(item)); SetTreeOwnerAndChromeEventHandlerOnDocshellTree(item, aOwner, aHandler); } } /** * Set the type of the treeitem and hook it up to the treeowner. * @param aItem the treeitem we're working with - * @param aOwningContent the content node that owns aItem * @param aTreeOwner the relevant treeowner; might be null * @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell * @param aParentNode if non-null, the docshell we should be added as a child to * * @return whether aItem is top-level content */ -static bool -AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent, - nsIDocShellTreeOwner* aOwner, int32_t aParentType, - nsIDocShellTreeNode* aParentNode) +bool +nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, + nsIDocShellTreeOwner* aOwner, + int32_t aParentType, + nsIDocShellTreeNode* aParentNode) { NS_PRECONDITION(aItem, "Must have docshell treeitem"); - NS_PRECONDITION(aOwningContent, "Must have owning content"); + NS_PRECONDITION(mOwnerContent, "Must have owning content"); nsAutoString value; bool isContent = false; - - if (aOwningContent->IsXUL()) { - aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value); - } else { - aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozframetype, value); - } + mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value); // we accept "content" and "content-xxx" values. // at time of writing, we expect "xxx" to be "primary" or "targetable", but // someday it might be an integer expressing priority or something else. isContent = value.LowerCaseEqualsLiteral("content") || StringBeginsWith(value, NS_LITERAL_STRING("content-"), nsCaseInsensitiveStringComparator()); // Force mozbrowser frames to always be typeContent, even if the // mozbrowser interfaces are disabled. nsCOMPtr<nsIDOMMozBrowserFrame> mozbrowser = - do_QueryInterface(aOwningContent); + do_QueryInterface(mOwnerContent); if (mozbrowser) { bool isMozbrowser = false; mozbrowser->GetMozbrowser(&isMozbrowser); isContent |= isMozbrowser; } if (isContent) { // The web shell's type is content. @@ -720,16 +720,18 @@ AddTreeItemToTreeOwner(nsIDocShellTreeIt if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) { retval = true; bool is_primary = value.LowerCaseEqualsLiteral("content-primary"); if (aOwner) { bool is_targetable = is_primary || value.LowerCaseEqualsLiteral("content-targetable"); + mOwnerContent->AddMutationObserver(this); + mObservingOwnerContent = true; aOwner->ContentShellAdded(aItem, is_primary, is_targetable, value); } } return retval; } static bool @@ -1200,36 +1202,38 @@ nsFrameLoader::SwapWithOtherLoader(nsFra otherParentItem->AddChild(ourTreeItem); // Restore the correct treeowners SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourTreeItem, otherOwner, otherChromeEventHandler); SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherTreeItem, ourOwner, ourChromeEventHandler); - AddTreeItemToTreeOwner(ourTreeItem, otherContent, otherOwner, - otherParentType, nullptr); - AddTreeItemToTreeOwner(otherTreeItem, ourContent, ourOwner, ourParentType, - nullptr); + // Switch the owner content before we start calling AddTreeItemToTreeOwner. + // Note that we rely on this to deal with setting mObservingOwnerContent to + // false and calling RemoveMutationObserver as needed. + SetOwnerContent(otherContent); + aOther->SetOwnerContent(ourContent); + + AddTreeItemToTreeOwner(ourTreeItem, otherOwner, otherParentType, nullptr); + aOther->AddTreeItemToTreeOwner(otherTreeItem, ourOwner, ourParentType, + nullptr); // SetSubDocumentFor nulls out parent documents on the old child doc if a // new non-null document is passed in, so just go ahead and remove both // kids before reinserting in the parent subdoc maps, to avoid // complications. ourParentDocument->SetSubDocumentFor(ourContent, nullptr); otherParentDocument->SetSubDocumentFor(otherContent, nullptr); ourParentDocument->SetSubDocumentFor(ourContent, otherChildDocument); otherParentDocument->SetSubDocumentFor(otherContent, ourChildDocument); ourWindow->SetFrameElementInternal(otherFrameElement); otherWindow->SetFrameElementInternal(ourFrameElement); - SetOwnerContent(otherContent); - aOther->SetOwnerContent(ourContent); - nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager; nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager; // Swap pointers in child message managers. if (mChildMessageManager) { nsInProcessTabChildGlobal* tabChild = static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get()); tabChild->SetOwner(otherContent); tabChild->SetChromeMessageManager(otherMessageManager); @@ -1378,16 +1382,20 @@ nsFrameLoader::GetDepthTooGreat(bool* aD { *aDepthTooGreat = mDepthTooGreat; return NS_OK; } void nsFrameLoader::SetOwnerContent(Element* aContent) { + if (mObservingOwnerContent) { + mObservingOwnerContent = false; + mOwnerContent->RemoveMutationObserver(this); + } mOwnerContent = aContent; if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) { rfp->OwnerContentChanged(aContent); } } bool nsFrameLoader::OwnerIsBrowserFrame() @@ -1554,18 +1562,18 @@ nsFrameLoader::MaybeCreateDocShell() parentAsItem->GetItemType(&parentType); // XXXbz why is this in content code, exactly? We should handle // this some other way..... Not sure how yet. nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner; parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner)); NS_ENSURE_STATE(parentTreeOwner); mIsTopLevelContent = - AddTreeItemToTreeOwner(docShellAsItem, mOwnerContent, parentTreeOwner, - parentType, parentAsNode); + AddTreeItemToTreeOwner(docShellAsItem, parentTreeOwner, parentType, + parentAsNode); // Make sure all shells have links back to the content element // in the nearest enclosing chrome shell. nsCOMPtr<nsIDOMEventTarget> chromeEventHandler; if (parentType == nsIDocShellTreeItem::typeChrome) { // Our parent shell is a chrome shell. It is therefore our nearest // enclosing chrome shell. @@ -2399,8 +2407,83 @@ nsFrameLoader::SetDetachedSubdocView(nsI nsIView* nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const { NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached); return mDetachedSubdocViews; } +/* virtual */ void +nsFrameLoader::AttributeChanged(nsIDocument* aDocument, + mozilla::dom::Element* aElement, + int32_t aNameSpaceID, + nsIAtom* aAttribute, + int32_t aModType) +{ + MOZ_ASSERT(mObservingOwnerContent); + // TODO: Implement ContentShellAdded for remote browsers (bug 658304) + MOZ_ASSERT(!mRemoteBrowser); + + if (aNameSpaceID != kNameSpaceID_None || aAttribute != TypeAttrName()) { + return; + } + + if (aElement != mOwnerContent) { + return; + } + + // Note: This logic duplicates a lot of logic in + // MaybeCreateDocshell. We should fix that. + + // Notify our enclosing chrome that our type has changed. We only do this + // if our parent is chrome, since in all other cases we're random content + // subframes and the treeowner shouldn't worry about us. + + nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell)); + if (!docShellAsItem) { + return; + } + + nsCOMPtr<nsIDocShellTreeItem> parentItem; + docShellAsItem->GetParent(getter_AddRefs(parentItem)); + if (!parentItem) { + return; + } + + int32_t parentType; + parentItem->GetItemType(&parentType); + + if (parentType != nsIDocShellTreeItem::typeChrome) { + return; + } + + nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner; + parentItem->GetTreeOwner(getter_AddRefs(parentTreeOwner)); + if (!parentTreeOwner) { + return; + } + + nsAutoString value; + aElement->GetAttr(kNameSpaceID_None, TypeAttrName(), value); + + bool is_primary = value.LowerCaseEqualsLiteral("content-primary"); + +#ifdef MOZ_XUL + // when a content panel is no longer primary, hide any open popups it may have + if (!is_primary) { + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (pm) + pm->HidePopupsInDocShell(docShellAsItem); + } +#endif + + parentTreeOwner->ContentShellRemoved(docShellAsItem); + if (value.LowerCaseEqualsLiteral("content") || + StringBeginsWith(value, NS_LITERAL_STRING("content-"), + nsCaseInsensitiveStringComparator())) { + bool is_targetable = is_primary || + value.LowerCaseEqualsLiteral("content-targetable"); + + parentTreeOwner->ContentShellAdded(docShellAsItem, is_primary, + is_targetable, value); + } +}
--- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -17,23 +17,27 @@ #include "nsPoint.h" #include "nsSize.h" #include "nsIURI.h" #include "nsAutoPtr.h" #include "nsFrameMessageManager.h" #include "mozilla/dom/Element.h" #include "mozilla/Attributes.h" #include "FrameMetrics.h" +#include "nsStubMutationObserver.h" class nsIURI; class nsSubDocumentFrame; class nsIView; class nsIInProcessContentFrameMessageManager; class AutoResetInShow; class nsITabParent; +class nsIDocShellTreeItem; +class nsIDocShellTreeOwner; +class nsIDocShellTreeNode; namespace mozilla { namespace dom { class PBrowserParent; class TabParent; } namespace layout { @@ -130,17 +134,18 @@ private: nsresult Update(const ViewConfig& aConfig); ViewID mScrollId; ViewConfig mConfig; }; class nsFrameLoader MOZ_FINAL : public nsIFrameLoader, - public nsIContentViewManager + public nsIContentViewManager, + public nsStubMutationObserver { friend class AutoResetInShow; typedef mozilla::dom::PBrowserParent PBrowserParent; typedef mozilla::dom::TabParent TabParent; typedef mozilla::layout::RenderFrameParent RenderFrameParent; protected: nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated); @@ -161,16 +166,17 @@ public: static nsFrameLoader* Create(mozilla::dom::Element* aOwner, bool aNetworkCreated); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader) NS_DECL_NSIFRAMELOADER NS_DECL_NSICONTENTVIEWMANAGER + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); nsresult ReallyStartLoading(); void Finalize(); nsIDocShell* GetExistingDocShell() { return mDocShell; } nsIDOMEventTarget* GetTabChildGlobalAsEventTarget(); nsresult CreateStaticClone(nsIFrameLoader* aDest); /** @@ -332,19 +338,29 @@ private: nsresult ReallyStartLoadingInternal(); // Return true if remote browser created; nothing else to do bool TryRemoteBrowser(); // Tell the remote browser that it's now "virtually visible" bool ShowRemoteFrame(const nsIntSize& size); + bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, + nsIDocShellTreeOwner* aOwner, + int32_t aParentType, + nsIDocShellTreeNode* aParentNode); + + nsIAtom* TypeAttrName() const { + return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype; + } + nsCOMPtr<nsIDocShell> mDocShell; nsCOMPtr<nsIURI> mURIToLoad; mozilla::dom::Element* mOwnerContent; // WEAK + public: // public because a callback needs these. nsRefPtr<nsFrameMessageManager> mMessageManager; nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager; private: // Stores the root view of the subdocument while the subdocument is being // reframed. Used to restore the presentation after reframing. nsIView* mDetachedSubdocViews; @@ -368,16 +384,17 @@ private: bool mNetworkCreated : 1; bool mDelayRemoteDialogs : 1; bool mRemoteBrowserShown : 1; bool mRemoteFrame : 1; bool mClipSubdocument : 1; bool mClampScrollPosition : 1; bool mRemoteBrowserInitialized : 1; + bool mObservingOwnerContent : 1; // XXX leaking nsCOMPtr<nsIObserver> mChildHost; RenderFrameParent* mCurrentRemoteFrame; TabParent* mRemoteBrowser; // See nsIFrameLoader.idl. Short story, if !(mRenderMode & // RENDER_MODE_ASYNC_SCROLL), all the fields below are ignored in
--- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -953,18 +953,17 @@ nsFrameScriptExecutor::InitTabChildGloba (allowXML ? JSOPTION_ALLOW_XML : 0)); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, ContentScriptErrorReporter); xpc_LocalizeContext(cx); JSAutoRequest ar(cx); nsIXPConnect* xpc = nsContentUtils::XPConnect(); - const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES | - nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT; + const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES; JS_SetContextPrivate(cx, aScope); nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal, flags, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false);
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -38,16 +38,17 @@ GK_ATOM(mozallowfullscreen, "mozallowful GK_ATOM(moztype, "_moz-type") GK_ATOM(mozdirty, "_moz_dirty") GK_ATOM(mozdonotsend, "moz-do-not-send") GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node") GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before") GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after") GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image") GK_ATOM(mozquote, "_moz_quote") +GK_ATOM(_moz_is_glyph, "-moz-is-glyph") GK_ATOM(_moz_original_size, "_moz_original_size") GK_ATOM(_moz_target, "_moz_target") GK_ATOM(_moz_type, "_moz-type") GK_ATOM(menuactive, "_moz-menuactive") GK_ATOM(_poundDefault, "#default") GK_ATOM(_asterix, "*") GK_ATOM(a, "a") GK_ATOM(abbr, "abbr") @@ -374,16 +375,18 @@ GK_ATOM(formnovalidate, "formnovalidate" GK_ATOM(formtarget, "formtarget") GK_ATOM(frame, "frame") GK_ATOM(frameborder, "frameborder") GK_ATOM(frameset, "frameset") GK_ATOM(from, "from") GK_ATOM(functionAvailable, "function-available") GK_ATOM(generateId, "generate-id") GK_ATOM(getter, "getter") +GK_ATOM(glyphchar, "glyphchar") +GK_ATOM(glyphid, "glyphid") GK_ATOM(grid, "grid") GK_ATOM(grippy, "grippy") GK_ATOM(group, "group") GK_ATOM(groupingSeparator, "grouping-separator") GK_ATOM(groupingSize, "grouping-size") GK_ATOM(grow, "grow") GK_ATOM(gutter, "gutter") GK_ATOM(h1, "h1")
--- a/content/base/src/nsMappedAttributes.cpp +++ b/content/base/src/nsMappedAttributes.cpp @@ -72,43 +72,40 @@ void* nsMappedAttributes::operator new(s #endif return newAttrs; } NS_IMPL_ISUPPORTS1(nsMappedAttributes, nsIStyleRule) -nsresult +void nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue) { NS_PRECONDITION(aAttrName, "null name"); uint32_t i; for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) { if (Attrs()[i].mName.Equals(aAttrName)) { Attrs()[i].mValue.Reset(); Attrs()[i].mValue.SwapValueWith(aValue); - - return NS_OK; + return; } } NS_ASSERTION(mBufferSize >= mAttrCount + 1, "can't fit attributes"); if (mAttrCount != i) { memmove(&Attrs()[i + 1], &Attrs()[i], (mAttrCount - i) * sizeof(InternalAttr)); } new (&Attrs()[i].mName) nsAttrName(aAttrName); new (&Attrs()[i].mValue) nsAttrValue(); Attrs()[i].mValue.SwapValueWith(aValue); ++mAttrCount; - - return NS_OK; } const nsAttrValue* nsMappedAttributes::GetAttr(nsIAtom* aAttrName) const { NS_PRECONDITION(aAttrName, "null name"); for (uint32_t i = 0; i < mAttrCount; ++i) {
--- a/content/base/src/nsMappedAttributes.h +++ b/content/base/src/nsMappedAttributes.h @@ -27,17 +27,17 @@ public: nsMapRuleToAttributesFunc aMapRuleFunc); // Do not return null. void* operator new(size_t size, uint32_t aAttrCount = 1) CPP_THROW_NEW; nsMappedAttributes* Clone(bool aWillAddAttr); NS_DECL_ISUPPORTS - nsresult SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue); + void SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue); const nsAttrValue* GetAttr(nsIAtom* aAttrName) const; const nsAttrValue* GetAttr(const nsAString& aAttrName) const; uint32_t Count() const { return mAttrCount; }
--- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -682,53 +682,47 @@ nsObjectLoadingContent::~nsObjectLoading StopPluginInstance(); } DestroyImageLoadingContent(); } nsresult nsObjectLoadingContent::InstantiatePluginInstance() { - if (mType != eType_Plugin || mIsLoading) { - LOG(("OBJLC [%p]: Not instantiating loading or non-plugin object, type %u", - this, mType)); + if (mInstanceOwner || mType != eType_Plugin || mIsLoading || mInstantiating) { + return NS_OK; + } + + nsCOMPtr<nsIContent> thisContent = + do_QueryInterface(static_cast<nsIImageLoadingContent *>(this)); + + // Flush layout so that the frame is created if possible and the plugin is + // initialized with the latest information. + nsIDocument* doc = thisContent->GetCurrentDoc(); + + if (!doc || !InActiveDocument(thisContent)) { + NS_ERROR("Shouldn't be calling " + "InstantiatePluginInstance without an active document"); + return NS_ERROR_FAILURE; + } + doc->FlushPendingNotifications(Flush_Layout); + + if (!thisContent->GetPrimaryFrame()) { + LOG(("OBJLC [%p]: Not instantiating plugin with no frame", this)); return NS_OK; } - // Don't do anything if we already have an active instance. - if (mInstanceOwner) { - return NS_OK; - } - - // Don't allow re-entry into initialization code. - if (mInstantiating) { - return NS_OK; - } mInstantiating = true; AutoSetInstantiatingToFalse autoInstantiating(this); // Instantiating an instance can result in script execution, which // can destroy this DOM object. Don't allow that for the scope // of this method. nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this; - nsCOMPtr<nsIContent> thisContent = - do_QueryInterface(static_cast<nsIImageLoadingContent *>(this)); - // Flush layout so that the plugin is initialized with the latest information. - nsIDocument* doc = thisContent->GetCurrentDoc(); - if (!doc) { - return NS_ERROR_FAILURE; - } - if (!InActiveDocument(thisContent)) { - NS_ERROR("Shouldn't be calling " - "InstantiatePluginInstance in an inactive document"); - return NS_ERROR_FAILURE; - } - doc->FlushPendingNotifications(Flush_Layout); - nsresult rv = NS_ERROR_FAILURE; nsRefPtr<nsPluginHost> pluginHost = already_AddRefed<nsPluginHost>(nsPluginHost::GetInst()); if (!pluginHost) { NS_NOTREACHED("No pluginhost"); return NS_ERROR_FAILURE; } @@ -876,17 +870,17 @@ nsObjectLoadingContent::OnStopRequest(ns } // nsIStreamListener NS_IMETHODIMP nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, - uint32_t aOffset, uint32_t aCount) + uint64_t aOffset, uint32_t aCount) { NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); if (aRequest != mChannel) { return NS_BINDING_ABORTED; } if (mFinalListener) { @@ -1724,16 +1718,24 @@ nsObjectLoadingContent::LoadObject(bool break; } // Force a sync state change now, we need the frame created NotifyStateChanged(oldType, oldState, true, aNotify); oldType = mType; oldState = ObjectState(); + if (!thisContent->GetPrimaryFrame()) { + // We're un-rendered, and can't instantiate a plugin. HasNewFrame will + // re-start us when we can proceed. + LOG(("OBJLC [%p]: Aborting load - plugin-type, but no frame", this)); + CloseChannel(); + break; + } + rv = pluginHost->NewEmbeddedPluginStreamListener(mURI, this, nullptr, getter_AddRefs(mFinalListener)); if (NS_SUCCEEDED(rv)) { // Note that LoadObject is called from mChannel's OnStartRequest // when loading with a channel mSrcStreamLoading = true; rv = mFinalListener->OnStartRequest(mChannel, nullptr);
--- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -269,17 +269,17 @@ nsMultipartProxyListener::OnStopRequest( } /** nsIStreamListener methods **/ NS_IMETHODIMP nsMultipartProxyListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, - uint32_t sourceOffset, + uint64_t sourceOffset, uint32_t count) { return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); } ///////////////////////////////////////////// @@ -1920,17 +1920,17 @@ bool nsXMLHttpRequest::CreateDOMFile(nsI } return fromFile; } NS_IMETHODIMP nsXMLHttpRequest::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, nsIInputStream *inStr, - uint32_t sourceOffset, + uint64_t sourceOffset, uint32_t count) { NS_ENSURE_ARG_POINTER(inStr); NS_ABORT_IF_FALSE(mContext.get() == ctxt,"start context different from OnDataAvailable context"); mProgressSinceLastProgressEvent = true; @@ -3883,17 +3883,17 @@ nsHeaderVisitor::VisitHeader(const nsACS // DOM event class to handle progress notifications nsXMLHttpProgressEvent::nsXMLHttpProgressEvent(nsIDOMProgressEvent* aInner, uint64_t aCurrentProgress, uint64_t aMaxProgress, nsPIDOMWindow* aWindow) : mWindow(aWindow) { - mInner = static_cast<nsDOMProgressEvent*>(aInner); + mInner = aInner; mCurProgress = aCurrentProgress; mMaxProgress = aMaxProgress; } nsXMLHttpProgressEvent::~nsXMLHttpProgressEvent() {} NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpProgressEvent) @@ -3913,18 +3913,17 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHtt NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpProgressEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpProgressEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInner); NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpProgressEvent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mInner, - nsIDOMProgressEvent) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWindow); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMETHODIMP nsXMLHttpProgressEvent::GetInput(nsIDOMLSInput * *aInput) { *aInput = nullptr; return NS_ERROR_NOT_IMPLEMENTED; }
--- a/content/base/src/nsXMLHttpRequest.h +++ b/content/base/src/nsXMLHttpRequest.h @@ -22,17 +22,17 @@ #include "nsIHttpHeaderVisitor.h" #include "nsIProgressEventSink.h" #include "nsCOMArray.h" #include "nsJSUtils.h" #include "nsTArray.h" #include "nsIJSNativeInitializer.h" #include "nsIDOMLSProgressEvent.h" #include "nsITimer.h" -#include "nsDOMProgressEvent.h" +#include "nsIDOMProgressEvent.h" #include "nsDOMEventTargetHelper.h" #include "nsContentUtils.h" #include "nsDOMFile.h" #include "nsDOMBlobBuilder.h" #include "nsIPrincipal.h" #include "nsIScriptObjectPrincipal.h" #include "mozilla/Assertions.h" @@ -677,19 +677,17 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpProgressEvent, nsIDOMProgressEvent) NS_FORWARD_NSIDOMEVENT(mInner->) NS_FORWARD_NSIDOMPROGRESSEVENT(mInner->) NS_DECL_NSIDOMLSPROGRESSEVENT protected: void WarnAboutLSProgressEvent(nsIDocument::DeprecatedOperations); - // Use nsDOMProgressEvent so that we can forward - // most of the method calls easily. - nsRefPtr<nsDOMProgressEvent> mInner; + nsCOMPtr<nsIDOMProgressEvent> mInner; nsCOMPtr<nsPIDOMWindow> mWindow; uint64_t mCurProgress; uint64_t mMaxProgress; }; class nsXHRParseEndListener : public nsIDOMEventListener { public:
new file mode 100644 --- /dev/null +++ b/content/canvas/crashtests/0px-size-font-shadow.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<body> +<canvas id="canv" width="5" height="5"></canvas> +<script> +var canv = document.getElementById("canv"); +var ctx = canv.getContext("2d"); + +ctx.fillStyle = "red"; +// 0 size font shouldn't assert! +ctx.font = "0px Arial"; +ctx.shadowColor = '#f00'; +ctx.shadowBlur = 4; +ctx.fillText("A", 0, 0); +document.documentElement.className = ""; +</script> +</body> +</html>
--- a/content/canvas/crashtests/crashtests.list +++ b/content/canvas/crashtests/crashtests.list @@ -1,14 +1,15 @@ load 360293-1.html load 421715-1.html load 553938-1.html load 647480.html load 727547.html load 0px-size-font-667225.html +load 0px-size-font-shadow.html load texImage2D.html load 729116.html load 745699-1.html load 746813-1.html # this test crashes in a bunch places still #load 745818-large-source.html load 743499-negative-size.html load 767337-1.html
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -57,16 +57,17 @@ #include "gfxContext.h" #include "gfxASurface.h" #include "gfxImageSurface.h" #include "gfxPlatform.h" #include "gfxFont.h" #include "gfxBlur.h" #include "gfxUtils.h" #include "nsRenderingContext.h" +#include "gfxSVGGlyphs.h" #include "nsFrameManager.h" #include "nsFrameLoader.h" #include "nsBidi.h" #include "nsBidiPresUtils.h" #include "Layers.h" #include "CanvasUtils.h" #include "nsIMemoryReporter.h" @@ -2819,25 +2820,30 @@ struct NS_STACK_CLASS nsCanvasBidiProces nullptr); point.x += textRunMetrics.mAdvanceWidth; // old code was: // point.x += width * mAppUnitsPerDevPixel; // TODO: restore this if/when we move to fractional coords // throughout the text layout process } + nsRefPtr<gfxPattern> pattern = mThebes->GetPattern(); + + bool isFill = mOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_FILL; + SimpleTextObjectPaint objectPaint(isFill ? pattern.get() : nullptr, + isFill ? nullptr : pattern.get()); + mTextRun->Draw(mThebes, point, - mOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_STROKE ? - gfxFont::GLYPH_STROKE : gfxFont::GLYPH_FILL, + isFill ? gfxFont::GLYPH_FILL : gfxFont::GLYPH_STROKE, 0, mTextRun->GetLength(), nullptr, nullptr, - nullptr); + &objectPaint); } // current text run nsAutoPtr<gfxTextRun> mTextRun; // pointer to the context, may not be the canvas's context // if an intermediate surface is being used gfxContext* mThebes; @@ -4316,32 +4322,38 @@ static uint8_t g2DContextLayerUserData; already_AddRefed<CanvasLayer> nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasLayer *aOldLayer, LayerManager *aManager) { // If we don't have anything to draw, don't bother. if (!mValid || !mSurface || mSurface->CairoStatus() || !mThebes || !mSurfaceCreated) { + // No DidTransactionCallback will be received, so mark the context clean + // now so future invalidations will be dispatched. + MarkContextClean(); return nullptr; } if (!mResetLayer && aOldLayer) { CanvasRenderingContext2DUserData* userData = static_cast<CanvasRenderingContext2DUserData*>( aOldLayer->GetUserData(&g2DContextLayerUserData)); if (userData && userData->IsForContext(this)) { NS_ADDREF(aOldLayer); return aOldLayer; } } nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer(); if (!canvasLayer) { NS_WARNING("CreateCanvasLayer returned null!"); + // No DidTransactionCallback will be received, so mark the context clean + // now so future invalidations will be dispatched. + MarkContextClean(); return nullptr; } CanvasRenderingContext2DUserData *userData = nullptr; if (aBuilder->IsPaintingToWindow()) { // Make the layer tell us whenever a transaction finishes (including // the current transaction), so we can clear our invalidation state and // start invalidating again. We need to do this for the layer that is // being painted to a window (there shouldn't be more than one at a time,
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -3211,16 +3211,26 @@ nsCanvasRenderingContext2DAzure::DrawOrM } isRTL = canvasStyle->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; } else { isRTL = GET_BIDI_OPTION_DIRECTION(document->GetBidiOptions()) == IBMBIDI_TEXTDIRECTION_RTL; } + gfxFontGroup* currentFontStyle = GetCurrentFontStyle(); + NS_ASSERTION(currentFontStyle, "font group is null"); + + if (currentFontStyle->GetStyle()->size == 0.0F) { + if (aWidth) { + *aWidth = 0; + } + return NS_OK; + } + const ContextState &state = CurrentState(); // This is only needed to know if we can know the drawing bounding box easily. bool doDrawShadow = aOp == TEXT_DRAW_OPERATION_FILL && NeedToDrawShadow(); nsCanvasBidiProcessorAzure processor; GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, nullptr); @@ -3229,21 +3239,18 @@ nsCanvasRenderingContext2DAzure::DrawOrM new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); Matrix matrix = mTarget->GetTransform(); processor.mThebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32)); processor.mCtx = this; processor.mOp = aOp; processor.mBoundingBox = gfxRect(0, 0, 0, 0); processor.mDoMeasureBoundingBox = doDrawShadow || !mIsEntireFrameInvalid; processor.mState = &CurrentState(); + processor.mFontgrp = currentFontStyle; - - processor.mFontgrp = GetCurrentFontStyle(); - NS_ASSERTION(processor.mFontgrp, "font group is null"); - nscoord totalWidthCoord; // calls bidi algo twice since it needs the full text width and the // bounding boxes before rendering anything nsBidi bidiEngine; rv = nsBidiPresUtils::ProcessText(textToDraw.get(), textToDraw.Length(), isRTL ? NSBIDI_RTL : NSBIDI_LTR, @@ -4621,16 +4628,19 @@ nsCanvasRenderingContext2DAzure::SetMozI static uint8_t g2DContextLayerUserData; already_AddRefed<CanvasLayer> nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasLayer *aOldLayer, LayerManager *aManager) { if (!mValid) { + // No DidTransactionCallback will be received, so mark the context clean + // now so future invalidations will be dispatched. + MarkContextClean(); return nullptr; } if (mTarget) { mTarget->Flush(); } if (!mResetLayer && aOldLayer) { @@ -4641,16 +4651,19 @@ nsCanvasRenderingContext2DAzure::GetCanv NS_ADDREF(aOldLayer); return aOldLayer; } } nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer(); if (!canvasLayer) { NS_WARNING("CreateCanvasLayer returned null!"); + // No DidTransactionCallback will be received, so mark the context clean + // now so future invalidations will be dispatched. + MarkContextClean(); return nullptr; } CanvasRenderingContext2DUserDataAzure *userData = nullptr; // Make the layer tell us whenever a transaction finishes (including // the current transaction), so we can clear our invalidation state and // start invalidating again. We need to do this for all layers since // callers of DrawWindow may be expecting to receive normal invalidation // notifications after this paint.
--- a/content/events/src/Makefile.in +++ b/content/events/src/Makefile.in @@ -45,17 +45,16 @@ CPPSRCS = \ nsPrivateTextRange.cpp \ nsXMLEventsManager.cpp \ nsXMLEventsElement.cpp \ nsAsyncDOMEvent.cpp \ nsEventDispatcher.cpp \ nsIMEStateManager.cpp \ nsContentEventHandler.cpp \ nsEventListenerService.cpp \ - nsDOMProgressEvent.cpp \ nsDOMDataTransfer.cpp \ nsDOMNotifyPaintEvent.cpp \ nsDOMNotifyAudioAvailableEvent.cpp \ nsDOMSimpleGestureEvent.cpp \ nsDOMMozTouchEvent.cpp \ nsDOMEventTargetHelper.cpp \ nsDOMScrollAreaEvent.cpp \ nsDOMTransitionEvent.cpp \
deleted file mode 100644 --- a/content/events/src/nsDOMProgressEvent.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#include "nsDOMClassInfoID.h" -#include "nsDOMProgressEvent.h" - -DOMCI_DATA(ProgressEvent, nsDOMProgressEvent) - -NS_INTERFACE_MAP_BEGIN(nsDOMProgressEvent) - NS_INTERFACE_MAP_ENTRY(nsIDOMProgressEvent) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ProgressEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) - -NS_IMPL_ADDREF_INHERITED(nsDOMProgressEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(nsDOMProgressEvent, nsDOMEvent) - -NS_IMETHODIMP -nsDOMProgressEvent::GetLengthComputable(bool* aLengthComputable) -{ - *aLengthComputable = mLengthComputable; - return NS_OK; -} - -NS_IMETHODIMP -nsDOMProgressEvent::GetLoaded(uint64_t* aLoaded) -{ - *aLoaded = mLoaded; - return NS_OK; -} - -NS_IMETHODIMP -nsDOMProgressEvent::GetTotal(uint64_t* aTotal) -{ - *aTotal = mTotal; - return NS_OK; -} - -NS_IMETHODIMP -nsDOMProgressEvent::InitProgressEvent(const nsAString& aType, - bool aCanBubble, - bool aCancelable, - bool aLengthComputable, - uint64_t aLoaded, - uint64_t aTotal) -{ - nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); - NS_ENSURE_SUCCESS(rv, rv); - - mLoaded = aLoaded; - mLengthComputable = aLengthComputable; - mTotal = aTotal; - - return NS_OK; -} - -nsresult -NS_NewDOMProgressEvent(nsIDOMEvent** aInstancePtrResult, - nsPresContext* aPresContext, - nsEvent* aEvent) -{ - nsDOMProgressEvent* it = new nsDOMProgressEvent(aPresContext, aEvent); - if (nullptr == it) - return NS_ERROR_OUT_OF_MEMORY; - - return CallQueryInterface(it, aInstancePtrResult); -}
deleted file mode 100644 --- a/content/events/src/nsDOMProgressEvent.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#ifndef nsDOMProgressEvent_h__ -#define nsDOMProgressEvent_h__ - -#include "nsIDOMProgressEvent.h" -#include "nsDOMEvent.h" - -/** - * Implements the ProgressEvent event, used for progress events from the media - * elements. - - * See http://www.whatwg.org/specs/web-apps/current-work/#progress0 for - * further details. - */ -class nsDOMProgressEvent : public nsDOMEvent, - public nsIDOMProgressEvent -{ -public: - nsDOMProgressEvent(nsPresContext* aPresContext, nsEvent* aEvent) - : nsDOMEvent(aPresContext, aEvent) - { - } - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMPROGRESSEVENT - - // Forward to base class - NS_FORWARD_TO_NSDOMEVENT - -private: - bool mLengthComputable; - uint64_t mLoaded; - uint64_t mTotal; -}; - -#endif // nsDOMProgressEvent_h__
--- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -4887,18 +4887,17 @@ nsEventStateManager::UnregisterAccessKey { if (aContent) mAccessKeys.RemoveObject(aContent); } uint32_t nsEventStateManager::GetRegisteredAccessKey(nsIContent* aContent) { - NS_ASSERTION(aContent, "Null pointer passed to GetRegisteredAccessKey"); - NS_ENSURE_TRUE(aContent, 0); + MOZ_ASSERT(aContent); if (mAccessKeys.IndexOf(aContent) == -1) return 0; nsAutoString accessKey; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey); return accessKey.First(); }
--- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -131,17 +131,17 @@ public: * @param aContent the given element * @param aKey accesskey */ void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey); /** * Get accesskey registered on the given element or 0 if there is none. * - * @param aContent the given element + * @param aContent the given element (must not be null) * @return registered accesskey */ uint32_t GetRegisteredAccessKey(nsIContent* aContent); bool GetAccessKeyLabelPrefix(nsAString& aPrefix); nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer, bool aHaveHotspot, float aHotspotX, float aHotspotY,
--- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -308,16 +308,21 @@ public: #endif #ifdef MOZ_MEDIA_PLUGINS static bool IsMediaPluginsEnabled(); static bool IsMediaPluginsType(const nsACString& aType); #endif /** + * Get the mime type for this element. + */ + void GetMimeType(nsCString& aMimeType); + + /** * Called when a child source element is added to this media element. This * may queue a task to run the select resource algorithm if appropriate. */ void NotifyAddedSource(); /** * Called when there's been an error fetching the resource. This decides * whether it's appropriate to fire an error event. @@ -867,11 +872,18 @@ protected: // The CORS mode when loading the media element mozilla::CORSMode mCORSMode; // True if the media has an audio track bool mHasAudio; // True if the media's channel's download has been suspended. bool mDownloadSuspendedByCache; + + // The Content-Type for this media. When we are sniffing for the Content-Type, + // and we are recreating a channel after the initial load, we need that + // information to give it as a hint to the channel for it to bypass the + // sniffing phase, that would fail because sniffing only works when applied to + // the first bytes of the stream. + nsCString mMimeType; }; #endif
--- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -1055,19 +1055,34 @@ nsHTMLInputElement::SetValue(const nsASt const PRUnichar *name = PromiseFlatString(aValue).get(); return MozSetFileNameArray(&name, 1); } else { ClearFiles(true); } } else { - SetValueInternal(aValue, false, true); if (IsSingleLineTextControl(false)) { - GetValueInternal(mFocusedValue); + // If the value has been set by a script, we basically want to keep the + // current change event state. If the element is ready to fire a change + // event, we should keep it that way. Otherwise, we should make sure the + // element will not fire any event because of the script interaction. + // + // NOTE: this is currently quite expensive work (too much string + // manipulation). We should probably optimize that. + nsAutoString currentValue; + GetValueInternal(currentValue); + + SetValueInternal(aValue, false, true); + + if (mFocusedValue.Equals(currentValue)) { + GetValueInternal(mFocusedValue); + } + } else { + SetValueInternal(aValue, false, true); } } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
--- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -353,19 +353,22 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaL nsresult aStatus) { if (mNextListener) { return mNextListener->OnStopRequest(aRequest, aContext, aStatus); } return NS_OK; } -NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, - nsIInputStream* aStream, uint32_t aOffset, - uint32_t aCount) +NS_IMETHODIMP +nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest* aRequest, + nsISupports* aContext, + nsIInputStream* aStream, + uint64_t aOffset, + uint32_t aCount) { if (!mNextListener) { NS_ERROR("Must have a chained listener; OnStartRequest should have canceled this request"); return NS_BINDING_ABORTED; } return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount); } @@ -1029,16 +1032,21 @@ nsresult nsHTMLMediaElement::LoadResourc // Set the media element's CORS mode only when loading a resource mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc); if (other) { // Clone it. nsresult rv = InitializeDecoderAsClone(other->mDecoder); + // Get the mimetype from the element we clone, since we will not get it via + // the channel, and we won't be able to sniff for it, because we will not + // open a channel to get the beginning of the media (it is likely to already + // be in the cache). + mMimeType = other->mMimeType; if (NS_SUCCEEDED(rv)) return rv; } int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA, mLoadingSrc, NodePrincipal(), @@ -1067,17 +1075,18 @@ nsresult nsHTMLMediaElement::LoadResourc channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA); } nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), mLoadingSrc, nullptr, loadGroup, nullptr, - nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY, + nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | + nsIChannel::LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN, channelPolicy); NS_ENSURE_SUCCESS(rv,rv); // The listener holds a strong reference to us. This creates a // reference cycle, once we've set mChannel, which is manually broken // in the listener's OnStartRequest method after it is finished with // the element. The cycle will also be broken if we get a shutdown // notification before OnStartRequest fires. Necko guarantees that @@ -2428,29 +2437,31 @@ nsresult nsHTMLMediaElement::InitializeD nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel, nsIStreamListener **aListener) { NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set"); NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder"); nsAutoCString mimeType; - aChannel->GetContentType(mimeType); - - nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType); + + aChannel->GetContentType(mMimeType); + NS_ASSERTION(!mMimeType.IsEmpty(), "We should have the Content-Type."); + + nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mMimeType); if (!decoder) { nsAutoString src; GetCurrentSrc(src); - NS_ConvertUTF8toUTF16 mimeUTF16(mimeType); + NS_ConvertUTF8toUTF16 mimeUTF16(mMimeType); const PRUnichar* params[] = { mimeUTF16.get(), src.get() }; ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params)); return NS_ERROR_FAILURE; } - LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get())); + LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mMimeType.get())); MediaResource* resource = MediaResource::Create(decoder, aChannel); if (!resource) return NS_ERROR_OUT_OF_MEMORY; // stream successfully created, the stream now owns the channel. mChannel = nullptr; @@ -3523,14 +3534,19 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMoz NS_ENSURE_SUCCESS(rv, rv); // If there is no end fragment, or the fragment end is greater than the // duration, return the duration. *aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd; return NS_OK; } +void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType) +{ + aMimeType = mMimeType; +} + void nsHTMLMediaElement::NotifyAudioAvailableListener() { if (mDecoder) { mDecoder->NotifyAudioAvailableListener(); } }
--- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -255,17 +255,17 @@ nsHTMLOptionElement::BeforeSetAttr(int32 return rv; } NS_IMETHODIMP nsHTMLOptionElement::GetText(nsAString& aText) { nsAutoString text; - nsContentUtils::GetNodeTextContent(this, false, text); + nsContentUtils::GetNodeTextContent(this, true, text); // XXX No CompressWhitespace for nsAString. Sad. text.CompressWhitespace(true, true); aText = text; return NS_OK; }
--- a/content/html/content/src/nsHTMLTableRowElement.cpp +++ b/content/html/content/src/nsHTMLTableRowElement.cpp @@ -55,18 +55,18 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableRowElement, nsGenericHTMLElement) protected: - nsresult GetSection(nsIDOMHTMLTableSectionElement** aSection); - nsresult GetTable(nsIDOMHTMLTableElement** aTable); + already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection() const; + already_AddRefed<nsIDOMHTMLTableElement> GetTable() const; nsRefPtr<nsContentList> mCells; }; NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow) nsHTMLTableRowElement::nsHTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo) @@ -95,62 +95,54 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION nsGenericHTMLElement) NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTableRowElement) NS_IMPL_ELEMENT_CLONE(nsHTMLTableRowElement) // protected method -nsresult -nsHTMLTableRowElement::GetSection(nsIDOMHTMLTableSectionElement** aSection) +already_AddRefed<nsIDOMHTMLTableSectionElement> +nsHTMLTableRowElement::GetSection() const { - NS_ENSURE_ARG_POINTER(aSection); nsCOMPtr<nsIDOMHTMLTableSectionElement> section = do_QueryInterface(GetParent()); - section.forget(aSection); - return NS_OK; + return section.forget(); } // protected method -nsresult -nsHTMLTableRowElement::GetTable(nsIDOMHTMLTableElement** aTable) +already_AddRefed<nsIDOMHTMLTableElement> +nsHTMLTableRowElement::GetTable() const { - NS_ENSURE_ARG_POINTER(aTable); - *aTable = nullptr; - nsIContent* parent = GetParent(); if (!parent) { - return NS_OK; + return nullptr; } // We may not be in a section nsCOMPtr<nsIDOMHTMLTableElement> table = do_QueryInterface(parent); if (table) { - table.forget(aTable); - return NS_OK; + return table.forget(); } parent = parent->GetParent(); if (!parent) { - return NS_OK; + return nullptr; } table = do_QueryInterface(parent); - table.forget(aTable); - return NS_OK; + return table.forget(); } NS_IMETHODIMP nsHTMLTableRowElement::GetRowIndex(int32_t* aValue) { *aValue = -1; - nsCOMPtr<nsIDOMHTMLTableElement> table; - nsresult rv = GetTable(getter_AddRefs(table)); - if (NS_FAILED(rv) || !table) { - return rv; + nsCOMPtr<nsIDOMHTMLTableElement> table = GetTable(); + if (!table) { + return NS_OK; } nsCOMPtr<nsIDOMHTMLCollection> rows; table->GetRows(getter_AddRefs(rows)); uint32_t numRows; rows->GetLength(&numRows); @@ -162,20 +154,19 @@ nsHTMLTableRowElement::GetRowIndex(int32 } return NS_OK; } NS_IMETHODIMP nsHTMLTableRowElement::GetSectionRowIndex(int32_t* aValue) { *aValue = -1; - nsCOMPtr<nsIDOMHTMLTableSectionElement> section; - nsresult rv = GetSection(getter_AddRefs(section)); - if (NS_FAILED(rv) || !section) { - return rv; + nsCOMPtr<nsIDOMHTMLTableSectionElement> section = GetSection(); + if (!section) { + return NS_OK; } nsCOMPtr<nsIDOMHTMLCollection> rows; section->GetRows(getter_AddRefs(rows)); uint32_t numRows; rows->GetLength(&numRows); for (uint32_t i = 0; i < numRows; i++) {
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -540,18 +540,32 @@ nsHTMLTextAreaElement::SetValueInternal( mState.SetValue(aValue, aUserInput, true); return NS_OK; } NS_IMETHODIMP nsHTMLTextAreaElement::SetValue(const nsAString& aValue) { + // If the value has been set by a script, we basically want to keep the + // current change event state. If the element is ready to fire a change + // event, we should keep it that way. Otherwise, we should make sure the + // element will not fire any event because of the script interaction. + // + // NOTE: this is currently quite expensive work (too much string + // manipulation). We should probably optimize that. + nsAutoString currentValue; + GetValueInternal(currentValue, true); + SetValueInternal(aValue, false); - GetValueInternal(mFocusedValue, true); + + if (mFocusedValue.Equals(currentValue)) { + GetValueInternal(mFocusedValue, true); + } + return NS_OK; } NS_IMETHODIMP nsHTMLTextAreaElement::SetUserInput(const nsAString& aValue) { if (!nsContentUtils::IsCallerTrustedForWrite()) { return NS_ERROR_DOM_SECURITY_ERR;
--- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -27,23 +27,24 @@ MOCHITEST_FILES = \ test_label_control_attribute.html \ test_output_element.html \ test_button_attributes_reflection.html \ test_textarea_attributes_reflection.html \ test_validation.html \ test_maxlength_attribute.html \ test_datalist_element.html \ test_form_attributes_reflection.html \ + test_option_disabled.html \ test_option_index_attribute.html \ + test_option_text.html \ test_progress_element.html \ test_form_attribute-1.html \ test_form_attribute-2.html \ test_form_attribute-3.html \ test_form_attribute-4.html \ - test_option_disabled.html \ test_meter_element.html \ test_meter_pseudo-classes.html \ test_max_attribute.html \ test_min_attribute.html \ test_step_attribute.html \ test_stepup_stepdown.html \ test_valueasnumber_attribute.html \ test_experimental_forms_pref.html \
--- a/content/html/content/test/forms/test_change_event.html +++ b/content/html/content/test/forms/test_change_event.html @@ -101,23 +101,49 @@ https://bugzilla.mozilla.org/show_bug.cg //focus and blur text input input = document.getElementById("input_text"); input.focus(); synthesizeKey("f", {}); input.blur(); is(textInputChange[0], 2, "text input element should have dispatched change event (2)."); + // value being set while focused + input.focus(); + input.value = 'foo'; + input.blur(); + is(textInputChange[0], 2, "text input element should not have dispatched change event (2)."); + + // value being set while focused after being modified manually + input.focus(); + synthesizeKey("f", {}); + input.value = 'bar'; + input.blur(); + is(textInputChange[0], 3, "text input element should have dispatched change event (3)."); + //focus and blur textarea var textarea = document.getElementById("textarea"); textarea.focus(); synthesizeKey("f", {}); textarea.blur(); is(textareaChange, 1, "Textarea element should have dispatched change event."); + // value being set while focused + textarea.focus(); + textarea.value = 'foo'; + textarea.blur(); + is(textareaChange, 1, "textarea should not have dispatched change event (1)."); + + // value being set while focused after being modified manually + textarea.focus(); + synthesizeKey("f", {}); + textarea.value = 'bar'; + textarea.blur(); + is(textareaChange, 2, "textearea should have dispatched change event (2)."); + //Non-text input tests: for (var i = 0; i < NonTextInputTypes.length; ++i) { //button, submit, image and reset input type tests. if (i < 4) { input = document.getElementById("input_" + NonTextInputTypes[i]); input.focus(); input.click(); is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
new file mode 100644 --- /dev/null +++ b/content/html/content/test/forms/test_option_text.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>HTMLOptionElement.text</title> +<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com"> +<link rel=help href="http://www.whatwg.org/html/#dom-option-text"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createElement("font")) + .appendChild(document.createTextNode(" font ")); + assert_equals(option.text, "font"); +}); +</script>
--- a/content/html/document/src/MediaDocument.cpp +++ b/content/html/document/src/MediaDocument.cpp @@ -72,17 +72,17 @@ MediaDocumentStreamListener::OnStopReque return rv; } NS_IMETHODIMP MediaDocumentStreamListener::OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr, - uint32_t sourceOffset, + uint64_t sourceOffset, uint32_t count) { if (mNextStream) { return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count); } return NS_OK; }
--- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1241,17 +1241,20 @@ nsHTMLDocument::GetCookie(nsAString& aCo // Document's principal is not a codebase (may be system), so // can't set cookies return NS_OK; } nsXPIDLCString cookie; service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie)); - CopyASCIItoUTF16(cookie, aCookie); + // CopyUTF8toUTF16 doesn't handle error + // because it assumes that the input is valid. + nsContentUtils::ConvertStringFromCharset(NS_LITERAL_CSTRING("utf-8"), + cookie, aCookie); } return NS_OK; } NS_IMETHODIMP nsHTMLDocument::SetCookie(const nsAString& aCookie) { @@ -1280,17 +1283,17 @@ nsHTMLDocument::SetCookie(const nsAStrin if (!codebaseURI) { // Document's principal is not a codebase (may be system), so // can't set cookies return NS_OK; } - NS_LossyConvertUTF16toASCII cookie(aCookie); + NS_ConvertUTF16toUTF8 cookie(aCookie); service->SetCookieString(codebaseURI, prompt, cookie.get(), mChannel); } return NS_OK; } NS_IMETHODIMP nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
--- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -67,16 +67,18 @@ MOCHITEST_FILES = test_bug1682.html \ test_bug499092.html \ bug499092.xml \ bug499092.html \ test_bug512367.html \ test_bug571981.html \ test_bug677495.html \ test_bug677495-1.html \ test_bug741266.html \ + test_non-ascii-cookie.html \ + test_non-ascii-cookie.html^headers^ \ $(NULL) ifneq (mobile,$(MOZ_BUILD_APP)) MOCHITEST_BROWSER_FILES = \ browser_bug592641.js \ bug592641_img.jpg \ $(NULL) endif
new file mode 100644 --- /dev/null +++ b/content/html/document/test/test_non-ascii-cookie.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=784367 +--> +<head> + <meta charset="utf-8"> + <title>Test for non-ASCII document.cookie</title> + <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=784367">Mozilla Bug 784367</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for non-ASCII document.cookie **/ +var c = document.cookie; +is(document.cookie, 'abc=012©ABC\ufffdDEF', "document.cookie should be decoded as UTF-8"); +var newCookie = 'def=∼≩â‰â‰§âˆ¯â‰³â‰²â‰£âˆ½â‰¸â‰¸âˆºâ‰¸âˆ ≯≮≥≲≲≯≲∽≡≬≥≲≴∨∱∩∾'; +document.cookie = newCookie; +is(document.cookie, c + '; ' + newCookie, "document.cookie should be encoded as UTF-8"); +var date1 = new Date(); +date1.setTime(0); +document.cookie = newCookie + 'def=;expires=' + date1.toGMTString(); +</script> +</pre> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/content/html/document/test/test_non-ascii-cookie.html^headers^ @@ -0,0 +1,1 @@ +Set-Cookie: abc=012©ABC©DEF
--- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -23,16 +23,17 @@ #include "nsCrossSiteListenerProxy.h" #include "nsHTMLMediaElement.h" #include "nsError.h" #include "nsICachingChannel.h" #include "nsURILoader.h" #include "nsIAsyncVerifyRedirectCallback.h" #include "mozilla/Util.h" // for DebugOnly #include "nsContentUtils.h" +#include "nsBlobProtocolHandler.h" static const uint32_t HTTP_OK_CODE = 200; static const uint32_t HTTP_PARTIAL_RESPONSE_CODE = 206; using namespace mozilla; ChannelMediaResource::ChannelMediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) @@ -82,17 +83,17 @@ ChannelMediaResource::Listener::OnStopRe return NS_OK; return mResource->OnStopRequest(aRequest, aStatus); } nsresult ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream, - uint32_t aOffset, + uint64_t aOffset, uint32_t aCount) { if (!mResource) return NS_OK; return mResource->OnDataAvailable(aRequest, aStream, aCount); } nsresult @@ -699,22 +700,34 @@ ChannelMediaResource::RecreateChannel() nsHTMLMediaElement* element = mDecoder->GetMediaElement(); if (!element) { // The decoder is being shut down, so don't bother opening a new channel return NS_OK; } nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup(); NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER); - return NS_NewChannel(getter_AddRefs(mChannel), - mURI, - nullptr, - loadGroup, - nullptr, - loadFlags); + nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), + mURI, + nullptr, + loadGroup, + nullptr, + loadFlags); + + // We have cached the Content-Type, which should not change. Give a hint to + // the channel to avoid a sniffing failure, which would be expected because we + // are probably seeking in the middle of the bitstream, and sniffing relies + // on the presence of a magic number at the beginning of the stream. + nsAutoCString contentType; + element->GetMimeType(contentType); + NS_ASSERTION(!contentType.IsEmpty(), + "When recreating a channel, we should know the Content-Type."); + mChannel->SetContentType(contentType); + + return rv; } void ChannelMediaResource::DoNotifyDataReceived() { mDataReceivedEvent.Revoke(); mDecoder->NotifyBytesDownloaded(); } @@ -1088,24 +1101,25 @@ nsresult FileMediaResource::Open(nsIStre } nsresult rv = NS_OK; if (aStreamListener) { // The channel is already open. We need a synchronous stream that // implements nsISeekableStream, so we have to find the underlying // file and reopen it nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(mChannel)); - if (!fc) - return NS_ERROR_UNEXPECTED; + if (fc) { + nsCOMPtr<nsIFile> file; + rv = fc->GetFile(getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsIFile> file; - rv = fc->GetFile(getter_AddRefs(file)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file); + rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file); + } else if (IsBlobURI(mURI)) { + rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput)); + } } else { // Ensure that we never load a local file from some page on a // web server. nsHTMLMediaElement* element = mDecoder->GetMediaElement(); NS_ENSURE_TRUE(element, NS_ERROR_FAILURE); rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(element->NodePrincipal(), @@ -1245,27 +1259,27 @@ int64_t FileMediaResource::Tell() mSeekable->Tell(&offset); return offset; } MediaResource* MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel) { NS_ASSERTION(NS_IsMainThread(), - "MediaResource::Open called on non-main thread"); + "MediaResource::Open called on non-main thread"); // If the channel was redirected, we want the post-redirect URI; // but if the URI scheme was expanded, say from chrome: to jar:file:, // we want the original URI. nsCOMPtr<nsIURI> uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, nullptr); nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel); - if (fc) { + if (fc || IsBlobURI(uri)) { return new FileMediaResource(aDecoder, aChannel, uri); } return new ChannelMediaResource(aDecoder, aChannel, uri); } void MediaResource::MoveLoadsToBackground() { NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?"); mLoadInBackground = true;
--- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -122,16 +122,18 @@ MOCHITEST_FILES = \ test_autoplay_contentEditable.html \ test_buffered.html \ test_bug448534.html \ test_bug463162.xhtml \ test_decoder_disable.html \ test_media_selection.html \ test_playback.html \ test_seekLies.html \ + test_media_sniffer.html \ + contentType.sjs \ $(NULL) $(warning test_error_in_video_document.html is disabled for intermittent failures. Bug 608634) # Disabled on Windows for frequent intermittent failures ifneq ($(OS_ARCH), WINNT) MOCHITEST_FILES += \ test_streams_element_capture.html \ @@ -207,16 +209,19 @@ MOCHITEST_FILES += \ seek.yuv \ short-video.ogv \ small-shot.ogg \ sound.ogg \ spacestorm-1000Hz-100ms.ogg \ video-overhang.ogg \ file_a4_tone.ogg \ detodos.opus \ + short.mp4 \ + notags.mp3 \ + id3tags.mp3 \ $(NULL) # Wave sample files MOCHITEST_FILES += \ big.wav \ bogus.wav \ r11025_msadpcm_c1.wav \ r11025_s16_c1.wav \
new file mode 100644 --- /dev/null +++ b/content/media/test/contentType.sjs @@ -0,0 +1,77 @@ +// Parse the query string, and give us the value for a certain key, or false if +// it does not exist. +function parseQuery(request, key) { + var params = request.queryString.split('?')[0].split('&'); + for (var j = 0; j < params.length; ++j) { + var p = params[j]; + if (p == key) + return true; + if (p.indexOf(key + "=") == 0) + return p.substring(key.length + 1); + if (p.indexOf("=") < 0 && key == "") + return p; + } + return false; +} + +function handleRequest(request, response) { + try { + // Get the filename to send back. + var filename = parseQuery(request, "file"); + + const CC = Components.Constructor; + const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream"); + var file = Components.classes["@mozilla.org/file/directory_service;1"]. + getService(Components.interfaces.nsIProperties). + get("CurWorkD", Components.interfaces.nsILocalFile); + var fis = Components.classes['@mozilla.org/network/file-input-stream;1']. + createInstance(Components.interfaces.nsIFileInputStream); + var bis = Components.classes["@mozilla.org/binaryinputstream;1"]. + createInstance(Components.interfaces.nsIBinaryInputStream); + var paths = "tests/content/media/test/" + filename; + dump(paths + '\n'); + var split = paths.split("/"); + for(var i = 0; i < split.length; ++i) { + file.append(split[i]); + } + fis.init(file, -1, -1, false); + + // handle range requests + var partialstart = 0, + partialend = file.fileSize - 1; + if (request.hasHeader("Range")) { + var range = request.getHeader("Range"); + var parts = range.replace(/bytes=/, "").split("-"); + var partialstart = parts[0]; + var partialend = parts[1]; + if (!partialend.length) { + partialend = file.fileSize - 1; + } + response.setStatusLine(request.httpVersion, 206, "Partial Content"); + var contentRange = "bytes " + partialstart + "-" + partialend + "/" + file.fileSize; + response.setHeader("Content-Range", contentRange); + } + + fis.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, partialstart); + bis.setInputStream(fis); + + var sendContentType = parseQuery(request, "nomime"); + if (sendContentType == false) { + var contentType = parseQuery(request, "type"); + if (contentType == false) { + // This should not happen. + dump("No type specified without having \'nomime\' in parameters."); + return; + } + response.setHeader("Content-Type", contentType, false); + } + response.setHeader("Content-Length", ""+bis.available(), false); + + var bytes = bis.readBytes(bis.available()); + response.write(bytes, bytes.length); + } catch (e) { + dump ("ERROR : " + e + "\n"); + } +}
new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bad506cf185478c9c903793d11d95f278148e007 GIT binary patch literal 3530 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 E0HD#jxc~qF
--- a/content/media/test/manifest.js +++ b/content/media/test/manifest.js @@ -151,16 +151,29 @@ var gPlayTests = [ { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 }, { name:"gizmo.mp4", type:"video/mp4", duration:5.0 }, // Invalid file { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN } ]; +// A file for each type we can support. +var gSnifferTests = [ + { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444 }, + { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942 }, + { name:"seek.webm", type:"video/webm", duration:3.966, size:215529 }, + { name:"short.mp4", type:"video/mp4", duration:0.2, size:29435}, + // A mp3 file without id3 tags. + { name:"notags.mp3", type:"audio/mpeg", duration:0.28, size:2506}, + // A mp3 file with id3 tags. + { name:"id3tags.mp3", type:"audio/mpeg", duration:0.28, size:3530}, + { name:"bogus.duh", type:"bogus/duh" } +]; + // Converts a path/filename to a file:// URI which we can load from disk. // Optionally checks whether the file actually exists on disk at the location // we've specified. function fileUriToSrc(path, mustExist) { // android mochitest doesn't support file:// if (navigator.appVersion.indexOf("Android") != -1) return path;
new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f298131aa437897eb7ff41b64ddc452ec2a0ef8 GIT binary patch literal 2506 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 H|AT)6tPzX8
new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0b9870bdcb500389b78a84e7feb6cce31fd828b4 GIT binary patch literal 29435 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 MRG|T@ofi2215^f=E&u=k
new file mode 100644 --- /dev/null +++ b/content/media/test/test_media_sniffer.html @@ -0,0 +1,70 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Media test: mozStopDownload</title> + <meta charset='utf-8'> + <script type="text/javascript" src="/MochiKit/Base.js"></script> + <script type="text/javascript" src="/MochiKit/DOM.js"></script> + <script type="text/javascript" src="/MochiKit/Style.js"></script> + <script type="text/javascript" src="/MochiKit/Signal.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <script type="text/javascript" src="manifest.js"></script> +</head> +<body> +<pre id="test"> +<script class="testbody" type="text/javascript"> +var manager = new MediaTestManager; + +function finish_test(element) { + if (element.parentNode) + element.parentNode.removeChild(element); + manager.finished(element.token); +} + +function onApplicationOctetStreamLoaded(e) { + var t = e.target; + t.removeEventListener('loadedmetadata', onApplicationOctetStreamLoaded); + ok(true, "The media loads when served with application/octet-stream."); + finish_test(t); +} + +function checkApplicationOctetStream(t) { + t.src = t.src.replace("&nomime", "&type=application/octet-stream"); + t.addEventListener("loadedmetadata", onApplicationOctetStreamLoaded); +} + +function onmetadataloaded(e) { + var t = e.target; + t.removeEventListener('loadedmetadata', onmetadataloaded) + ok(true, "The media loads when served without a Content-Type."); + checkApplicationOctetStream(t); +} + +function onerror(e) { + var t = e.target; + t.removeEventListener('error', onerror); + ok(false, "The media could not be loaded." + t.src + "\n"); + finish_test(t); +} + +function startTest(test, token) { + var elemType = /^audio/.test(test.type) ? "audio" : "video"; + var element = document.createElement(elemType); + // This .sjs file serve the media file without Content-Type header, or with a + // specific Content-Type header. + element.src = 'contentType.sjs?file=' + test.name + "&nomime"; + element.token = token; + element.controls = true; + element.preload = "metadata"; + document.body.appendChild(element); + manager.started(token); + element.addEventListener("loadedmetadata", onmetadataloaded); + element.addEventListener("error", onerror); +} + +manager.runTests(gSnifferTests, startTest); +</script> +</pre> +</body> +</html>
--- a/content/svg/content/src/SVGPathData.cpp +++ b/content/svg/content/src/SVGPathData.cpp @@ -245,25 +245,26 @@ ApproximateZeroLengthSubpathSquareCaps(c segType == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH)) { \ ApproximateZeroLengthSubpathSquareCaps(segStart, aCtx); \ } \ } while(0) void SVGPathData::ConstructPath(gfxContext *aCtx) const { - if (!mData.Length() || !IsMoveto(SVGPathSegUtils::DecodeType(mData[0]))) { + if (mData.IsEmpty() || !IsMoveto(SVGPathSegUtils::DecodeType(mData[0]))) { return; // paths without an initial moveto are invalid } bool capsAreSquare = aCtx->CurrentLineCap() == gfxContext::LINE_CAP_SQUARE; bool subpathHasLength = false; // visual length bool subpathContainsNonArc = false; - uint32_t segType, prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN; + uint32_t segType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN; + uint32_t prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN; gfxPoint pathStart(0.0, 0.0); // start point of [sub]path gfxPoint segStart(0.0, 0.0); gfxPoint segEnd; gfxPoint cp1, cp2; // previous bezier's control points gfxPoint tcp1, tcp2; // temporaries // Regarding cp1 and cp2: If the previous segment was a cubic bezier curve, // then cp2 is its second control point. If the previous segment was a @@ -480,16 +481,18 @@ SVGPathData::ConstructPath(gfxContext *a return; // according to spec we'd use everything up to the bad seg anyway } i += argCount; prevSegType = segType; segStart = segEnd; }