author | Richard Newman <rnewman@mozilla.com> |
Tue, 29 Oct 2013 19:20:42 -0700 | |
changeset 152663 | 829d7bef8b0a6d2cda14cfdc0fd0061fdedb0dd7 |
parent 152662 | cdfe0db3e7620b96e43efdf2714fbfe61954713f (current diff) |
parent 152654 | 35b73bb96ca0a7eea38a022ae63505857eb8132b (diff) |
child 152683 | 747923d3bc466bc00a362a93d7531fc4ad3e53c4 |
child 161482 | fe534998400415f1a10e999076392e21840de6b4 |
push id | 25557 |
push user | rnewman@mozilla.com |
push date | Wed, 30 Oct 2013 02:21:21 +0000 |
treeherder | mozilla-central@829d7bef8b0a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 28.0a1 |
first release with | nightly linux32
829d7bef8b0a
/
28.0a1
/
20131030030201
/
files
nightly linux64
829d7bef8b0a
/
28.0a1
/
20131030030201
/
files
nightly mac
829d7bef8b0a
/
28.0a1
/
20131030030201
/
files
nightly win32
829d7bef8b0a
/
28.0a1
/
20131030030201
/
files
nightly win64
829d7bef8b0a
/
28.0a1
/
20131030030201
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
28.0a1
/
20131030030201
/
pushlog to previous
nightly linux64
28.0a1
/
20131030030201
/
pushlog to previous
nightly mac
28.0a1
/
20131030030201
/
pushlog to previous
nightly win32
28.0a1
/
20131030030201
/
pushlog to previous
nightly win64
28.0a1
/
20131030030201
/
pushlog to previous
|
accessible/src/base/nsAccessNode.cpp | file | annotate | diff | comparison | revisions | |
accessible/src/base/nsAccessNode.h | file | annotate | diff | comparison | revisions | |
layout/reftests/forms/input/color/testcase-style.css | file | annotate | diff | comparison | revisions | |
media/mtransport/third_party/Makefile.in | file | annotate | diff | comparison | revisions | |
media/webrtc/Makefile.in | file | annotate | diff | comparison | revisions | |
mobile/android/base/BrowserApp.java | file | annotate | diff | comparison | revisions | |
netwerk/protocol/app/AppProtocolHandler.js | file | annotate | diff | comparison | revisions | |
netwerk/protocol/app/AppProtocolHandler.manifest | file | annotate | diff | comparison | revisions | |
toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js | file | annotate | diff | comparison | revisions |
--- a/Makefile.in +++ b/Makefile.in @@ -27,19 +27,19 @@ include $(topsrcdir)/config/config.mk GARBAGE_DIRS += dist _javagen _profile staticlib DIST_GARBAGE = config.cache config.log config.status* config-defs.h \ config/autoconf.mk \ mozilla-config.h \ netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \ .mozconfig.mk ifndef MOZ_PROFILE_USE -# We need to explicitly put backend.RecursiveMakeBackend.built here +# We need to explicitly put backend.RecursiveMakeBackend here # otherwise the rule in rules.mk doesn't run early enough. -libs binaries export tools:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend.built +libs binaries export tools:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend ifndef LIBXUL_SDK libs binaries export tools:: js-config-status endif endif CLOBBER: $(topsrcdir)/CLOBBER @echo "STOP! The CLOBBER file has changed." @echo "Please run the build through a sanctioned build wrapper, such as" @@ -58,25 +58,25 @@ config.status: $(topsrcdir)/configure @echo "Please rerun configure." @echo "To ignore this message, touch 'config.status' in the build directory," @echo "but your build might not succeed." @exit 1 ifndef LIBXUL_SDK .PHONY: js-config-status js-config-status: - $(call SUBMAKE,backend.RecursiveMakeBackend.built,js/src,1) + $(call SUBMAKE,backend.RecursiveMakeBackend,js/src,1) endif install_manifests := bin idl include public private sdk install_manifest_depends = \ CLOBBER \ $(topsrcdir)/configure \ config.status \ - backend.RecursiveMakeBackend.built \ + backend.RecursiveMakeBackend \ $(NULL) ifndef LIBXUL_SDK install_manifest_depends += js-config-status endif .PHONY: install-manifests install-manifests: $(addprefix install-dist-,$(install_manifests))
--- a/accessible/public/msaa/ISimpleDOMNode.idl +++ b/accessible/public/msaa/ISimpleDOMNode.idl @@ -79,17 +79,17 @@ cpp_quote("// DOM navigation - get a dif cpp_quote("//") cpp_quote("// get_innerHTML(/* [out] */ BSTR *htmlText);") cpp_quote("// ---------------------------------------------------------------------------------------------------=") cpp_quote("// Returns HTML of this DOM node's subtree. Does not include the start and end tag for this node/element.") cpp_quote("//") cpp_quote("//") cpp_quote("// get_localInterface(/* [out] */ void **localInterface);") cpp_quote("// ---------------------------------------------------------------------------------------------------=") -cpp_quote("// Only available in Gecko's process - casts to an XPCOM nsAccessNode object pointer") +cpp_quote("// Only available in Gecko's process") cpp_quote("//") cpp_quote("//") cpp_quote("// get_language(/* [out] */ BSTR *htmlText);") cpp_quote("// ---------------------------------------------------------------------------------------------------=") cpp_quote("// Returns the computed language for this node, or empty string if unknown.") cpp_quote("//") cpp_quote("//") cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
--- a/accessible/src/atk/AccessibleWrap.h +++ b/accessible/src/atk/AccessibleWrap.h @@ -47,17 +47,16 @@ class MaiHyperlink; */ class AccessibleWrap : public Accessible { public: AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc); virtual ~AccessibleWrap(); void ShutdownAtkObject(); - // nsAccessNode virtual void Shutdown(); // return the atk object for this AccessibleWrap NS_IMETHOD GetNativeInterface(void **aOutAccessible); virtual nsresult HandleAccEvent(AccEvent* aEvent); AtkObject * GetAtkObject(void); static AtkObject * GetAtkObject(nsIAccessible * acc);
--- a/accessible/src/atk/AtkSocketAccessible.h +++ b/accessible/src/atk/AtkSocketAccessible.h @@ -40,17 +40,16 @@ public: * True if the current Atk version supports AtkSocket and it was correctly * loaded. */ static bool gCanEmbed; AtkSocketAccessible(nsIContent* aContent, DocAccessible* aDoc, const nsCString& aPlugId); - // nsAccessNode virtual void Shutdown(); // nsIAccessible NS_IMETHODIMP GetNativeInterface(void** aOutAccessible); }; } // namespace a11y } // namespace mozilla
--- a/accessible/src/base/moz.build +++ b/accessible/src/base/moz.build @@ -5,18 +5,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. include('../shared.mozbuild') MODULE = 'accessibility' EXPORTS += [ 'AccEvent.h', - 'nsAccessibilityService.h', - 'nsAccessNode.h', + 'nsAccessibilityService.h' ] EXPORTS.mozilla.a11y += [ 'AccTypes.h', 'DocManager.h', 'FocusManager.h', 'Platform.h', 'RelationType.h', @@ -40,17 +39,16 @@ SOURCES += [ 'Asserts.cpp', 'DocManager.cpp', 'EventQueue.cpp', 'Filters.cpp', 'FocusManager.cpp', 'NotificationController.cpp', 'nsAccessibilityService.cpp', 'nsAccessiblePivot.cpp', - 'nsAccessNode.cpp', 'nsAccUtils.cpp', 'nsCoreUtils.cpp', 'nsEventShell.cpp', 'nsTextEquivUtils.cpp', 'SelectionManager.cpp', 'StyleInfo.cpp', 'TextAttrs.cpp', 'TextUpdater.cpp',
deleted file mode 100644 --- a/accessible/src/base/nsAccessNode.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsAccessNode.h" - -#include "nsAccUtils.h" -#include "nsCoreUtils.h" -#include "RootAccessible.h" - -#include "nsIDocShell.h" - -using namespace mozilla::a11y; - -/* For documentation of the accessibility architecture, - * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html - */ - -/* - * Class nsAccessNode - */ - -//////////////////////////////////////////////////////////////////////////////// -// AccessNode. nsISupports - -NS_IMPL_CYCLE_COLLECTION_1(nsAccessNode, mContent) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode) - NS_INTERFACE_MAP_ENTRY(nsAccessNode) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccessNode) -NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsAccessNode, LastRelease()) - -//////////////////////////////////////////////////////////////////////////////// -// nsAccessNode construction/desctruction - -nsAccessNode:: - nsAccessNode(nsIContent* aContent, DocAccessible* aDoc) : - mContent(aContent), mDoc(aDoc) -{ -} - -nsAccessNode::~nsAccessNode() -{ - NS_ASSERTION(!mDoc, "LastRelease was never called!?!"); -} - -void nsAccessNode::LastRelease() -{ - // First cleanup if needed... - if (mDoc) { - Shutdown(); - NS_ASSERTION(!mDoc, "A Shutdown() impl forgot to call its parent's Shutdown?"); - } - // ... then die. - delete this; -} - -//////////////////////////////////////////////////////////////////////////////// -// nsAccessNode public - - -void -nsAccessNode::Shutdown() -{ - mContent = nullptr; - mDoc = nullptr; -} - -RootAccessible* -nsAccessNode::RootAccessible() const -{ - nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(GetNode()); - NS_ASSERTION(docShell, "No docshell for mContent"); - if (!docShell) { - return nullptr; - } - nsCOMPtr<nsIDocShellTreeItem> root; - docShell->GetRootTreeItem(getter_AddRefs(root)); - NS_ASSERTION(root, "No root content tree item"); - if (!root) { - return nullptr; - } - - DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root); - return docAcc ? docAcc->AsRoot() : nullptr; -} - -nsIFrame* -nsAccessNode::GetFrame() const -{ - return mContent ? mContent->GetPrimaryFrame() : nullptr; -} - -nsINode* -nsAccessNode::GetNode() const -{ - return mContent; -} - -void -nsAccessNode::Language(nsAString& aLanguage) -{ - aLanguage.Truncate(); - - if (!mDoc) - return; - - nsCoreUtils::GetLanguageFor(mContent, nullptr, aLanguage); - if (aLanguage.IsEmpty()) { // Nothing found, so use document's language - mDoc->DocumentNode()->GetHeaderData(nsGkAtoms::headerContentLanguage, - aLanguage); - } -} -
deleted file mode 100644 --- a/accessible/src/base/nsAccessNode.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -/* For documentation of the accessibility architecture, - * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html - */ - -#ifndef _nsAccessNode_H_ -#define _nsAccessNode_H_ - -#include "nsINode.h" - -class nsIContent; -class nsIFrame; - -namespace mozilla { -namespace a11y { - -class DocAccessible; -class RootAccessible; - -class nsAccessNode : public nsISupports -{ -public: - - nsAccessNode(nsIContent* aContent, DocAccessible* aDoc); - virtual ~nsAccessNode(); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(nsAccessNode) - - /** - * Return the document accessible for this access node. - */ - DocAccessible* Document() const { return mDoc; } - - /** - * Return the root document accessible for this accessnode. - */ - a11y::RootAccessible* RootAccessible() const; - - /** - * Shutdown the access node object. - */ - virtual void Shutdown(); - - /** - * Return frame for the given access node object. - */ - virtual nsIFrame* GetFrame() const; - - /** - * Return DOM node associated with the accessible. - */ - virtual nsINode* GetNode() const; - nsIContent* GetContent() const { return mContent; } - - /** - * Return node type information of DOM node associated with the accessible. - */ - bool IsContent() const - { - return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); - } - - /** - * Return the unique identifier of the accessible. - */ - void* UniqueID() { return static_cast<void*>(this); } - - /** - * Interface methods on nsIAccessible shared with ISimpleDOM. - */ - void Language(nsAString& aLocale); - -protected: - void LastRelease(); - - nsCOMPtr<nsIContent> mContent; - DocAccessible* mDoc; - -private: - nsAccessNode() MOZ_DELETE; - nsAccessNode(const nsAccessNode&) MOZ_DELETE; - nsAccessNode& operator =(const nsAccessNode&) MOZ_DELETE; -}; - -} // namespace a11y -} // namespace mozilla - -#endif -
--- a/accessible/src/generic/ARIAGridAccessible.cpp +++ b/accessible/src/generic/ARIAGridAccessible.cpp @@ -35,17 +35,17 @@ ARIAGridAccessible:: //////////////////////////////////////////////////////////////////////////////// // nsISupports NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridAccessible, Accessible, nsIAccessibleTable) //////////////////////////////////////////////////////////////////////////////// -//nsAccessNode +// Accessible void ARIAGridAccessible::Shutdown() { mTable = nullptr; AccessibleWrap::Shutdown(); }
--- a/accessible/src/generic/ARIAGridAccessible.h +++ b/accessible/src/generic/ARIAGridAccessible.h @@ -31,18 +31,16 @@ public: // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::) // Accessible virtual TableAccessible* AsTable() { return this; } - - // nsAccessNode virtual void Shutdown(); // TableAccessible virtual uint32_t ColCount(); virtual uint32_t RowCount(); virtual Accessible* CellAt(uint32_t aRowIndex, uint32_t aColumnIndex); virtual bool IsColSelected(uint32_t aColIdx); virtual bool IsRowSelected(uint32_t aRowIdx);
--- a/accessible/src/generic/Accessible.cpp +++ b/accessible/src/generic/Accessible.cpp @@ -83,79 +83,37 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/Element.h" using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// -// Accessible. nsISupports - -NS_IMPL_CYCLE_COLLECTION_INHERITED_2(Accessible, nsAccessNode, - mParent, mChildren) - -NS_IMPL_ADDREF_INHERITED(Accessible, nsAccessNode) -NS_IMPL_RELEASE_INHERITED(Accessible, nsAccessNode) - -nsresult -Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable - // based on role attribute and aria-multiselectable - *aInstancePtr = nullptr; - - if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { - *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible); - return NS_OK; - } - - if (aIID.Equals(NS_GET_IID(nsIAccessible))) { - *aInstancePtr = static_cast<nsIAccessible*>(this); - NS_ADDREF_THIS(); - return NS_OK; - } - - if (aIID.Equals(NS_GET_IID(Accessible))) { - *aInstancePtr = static_cast<Accessible*>(this); - NS_ADDREF_THIS(); - return NS_OK; - } - - if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) { - if (IsSelect()) { - *aInstancePtr = static_cast<nsIAccessibleSelectable*>(this); - NS_ADDREF_THIS(); - return NS_OK; - } - return NS_ERROR_NO_INTERFACE; - } - - if (aIID.Equals(NS_GET_IID(nsIAccessibleValue))) { - if (HasNumericValue()) { - *aInstancePtr = static_cast<nsIAccessibleValue*>(this); - NS_ADDREF_THIS(); - return NS_OK; - } - } - - if (aIID.Equals(NS_GET_IID(nsIAccessibleHyperLink))) { - if (IsLink()) { - *aInstancePtr = static_cast<nsIAccessibleHyperLink*>(this); - NS_ADDREF_THIS(); - return NS_OK; - } - return NS_ERROR_NO_INTERFACE; - } - - return nsAccessNode::QueryInterface(aIID, aInstancePtr); -} +// Accessible: nsISupports and cycle collection + +NS_IMPL_CYCLE_COLLECTION_3(Accessible, + mContent, mParent, mChildren) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Accessible) + NS_INTERFACE_MAP_ENTRY(nsIAccessible) + if (aIID.Equals(NS_GET_IID(Accessible))) + foundInterface = static_cast<nsIAccessible*>(this); + else + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleSelectable, IsSelect()) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleValue, HasNumericValue()) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleHyperLink, IsLink()) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessible) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(Accessible) +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(Accessible, LastRelease()) Accessible::Accessible(nsIContent* aContent, DocAccessible* aDoc) : - nsAccessNode(aContent, aDoc), + mContent(aContent), mDoc(aDoc), mParent(nullptr), mIndexInParent(-1), mChildrenFlags(eChildrenUninitialized), mStateFlags(0), mType(0), mGenericTypes(0), mIndexOfEmbeddedChild(-1), mRoleMapEntry(nullptr) { #ifdef NS_DEBUG_X { nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aShell)); printf(">>> %p Created Acc - DOM: %p PS: %p", @@ -170,21 +128,19 @@ Accessible::Accessible(nsIContent* aCont Name(buf); printf(" Name:[%s]", NS_ConvertUTF16toUTF8(buf).get()); } printf("\n"); } #endif } -//----------------------------------------------------- -// destruction -//----------------------------------------------------- Accessible::~Accessible() { + NS_ASSERTION(!mDoc, "LastRelease was never called!?!"); } NS_IMETHODIMP Accessible::GetDocument(nsIAccessibleDocument** aDocument) { NS_ENSURE_ARG_POINTER(aDocument); NS_IF_ADDREF(*aDocument = Document()); @@ -2619,31 +2575,29 @@ Accessible::AppendTextTo(nsAString& aTex // character if its parent hypertext accessible doesn't expose children to // AT. aText += kImaginaryEmbeddedObjectChar; } else { aText += kEmbeddedObjectChar; } } -//////////////////////////////////////////////////////////////////////////////// -// nsAccessNode public methods - void Accessible::Shutdown() { // Mark the accessible as defunct, invalidate the child count and pointers to // other accessibles, also make sure none of its children point to this parent mStateFlags |= eIsDefunct; InvalidateChildren(); if (mParent) mParent->RemoveChild(this); - nsAccessNode::Shutdown(); + mContent = nullptr; + mDoc = nullptr; } // Accessible protected void Accessible::ARIAName(nsString& aName) { // aria-labelledby now takes precedence over aria-label nsresult rv = nsTextEquivUtils:: @@ -2711,16 +2665,63 @@ Accessible::UnbindFromParent() mIndexInParent = -1; mIndexOfEmbeddedChild = -1; mGroupInfo = nullptr; } //////////////////////////////////////////////////////////////////////////////// // Accessible public methods +RootAccessible* +Accessible::RootAccessible() const +{ + nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(GetNode()); + NS_ASSERTION(docShell, "No docshell for mContent"); + if (!docShell) { + return nullptr; + } + + nsCOMPtr<nsIDocShellTreeItem> root; + docShell->GetRootTreeItem(getter_AddRefs(root)); + NS_ASSERTION(root, "No root content tree item"); + if (!root) { + return nullptr; + } + + DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root); + return docAcc ? docAcc->AsRoot() : nullptr; +} + +nsIFrame* +Accessible::GetFrame() const +{ + return mContent ? mContent->GetPrimaryFrame() : nullptr; +} + +nsINode* +Accessible::GetNode() const +{ + return mContent; +} + +void +Accessible::Language(nsAString& aLanguage) +{ + aLanguage.Truncate(); + + if (!mDoc) + return; + + nsCoreUtils::GetLanguageFor(mContent, nullptr, aLanguage); + if (aLanguage.IsEmpty()) { // Nothing found, so use document's language + mDoc->DocumentNode()->GetHeaderData(nsGkAtoms::headerContentLanguage, + aLanguage); + } +} + void Accessible::InvalidateChildren() { int32_t childCount = mChildren.Length(); for (int32_t childIdx = 0; childIdx < childCount; childIdx++) { Accessible* child = mChildren.ElementAt(childIdx); child->UnbindFromParent(); } @@ -3123,16 +3124,29 @@ Accessible::ContainerWidget() const } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // Accessible protected methods void +Accessible::LastRelease() +{ + // First cleanup if needed... + if (mDoc) { + Shutdown(); + NS_ASSERTION(!mDoc, + "A Shutdown() impl forgot to call its parent's Shutdown?"); + } + // ... then die. + delete this; +} + +void Accessible::CacheChildren() { DocAccessible* doc = Document(); NS_ENSURE_TRUE_VOID(doc); TreeWalker walker(this, mContent); Accessible* child = nullptr;
--- a/accessible/src/generic/Accessible.h +++ b/accessible/src/generic/Accessible.h @@ -5,17 +5,16 @@ #ifndef _Accessible_H_ #define _Accessible_H_ #include "mozilla/a11y/AccTypes.h" #include "mozilla/a11y/RelationType.h" #include "mozilla/a11y/Role.h" #include "mozilla/a11y/States.h" -#include "nsAccessNode.h" #include "nsIAccessible.h" #include "nsIAccessibleHyperLink.h" #include "nsIAccessibleSelectable.h" #include "nsIAccessibleValue.h" #include "nsIAccessibleStates.h" #include "nsIContent.h" @@ -31,23 +30,25 @@ class nsIAtom; class nsView; namespace mozilla { namespace a11y { class Accessible; class AccEvent; class AccGroupInfo; +class DocAccessible; class EmbeddedObjCollector; class HTMLImageMapAccessible; class HTMLLIAccessible; class HyperTextAccessible; class ImageAccessible; class KeyBinding; class Relation; +class RootAccessible; class TableAccessible; class TableCellAccessible; class TextLeafAccessible; class XULLabelAccessible; class XULTreeAccessible; /** * Name type flags. @@ -96,42 +97,78 @@ typedef nsRefPtrHashtable<nsPtrHashKey<c #define NS_ACCESSIBLE_IMPL_IID \ { /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */ \ 0x133c8bf4, \ 0x4913, \ 0x4355, \ { 0xbd, 0x50, 0x42, 0x6b, 0xd1, 0xd6, 0xe1, 0xad } \ } -class Accessible : public nsAccessNode, - public nsIAccessible, +class Accessible : public nsIAccessible, public nsIAccessibleHyperLink, public nsIAccessibleSelectable, public nsIAccessibleValue { public: Accessible(nsIContent* aContent, DocAccessible* aDoc); virtual ~Accessible(); - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Accessible, nsAccessNode) + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(Accessible, nsIAccessible) NS_DECL_NSIACCESSIBLE NS_DECL_NSIACCESSIBLEHYPERLINK NS_DECL_NSIACCESSIBLESELECTABLE NS_DECL_NSIACCESSIBLEVALUE NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID) ////////////////////////////////////////////////////////////////////////////// - // nsAccessNode + // Public methods + + /** + * Return the document accessible for this accessible. + */ + DocAccessible* Document() const { return mDoc; } + + /** + * Return the root document accessible for this accessible. + */ + a11y::RootAccessible* RootAccessible() const; + + /** + * Return frame for this accessible. + */ + virtual nsIFrame* GetFrame() const; - virtual void Shutdown(); + /** + * Return DOM node associated with the accessible. + */ + virtual nsINode* GetNode() const; + inline already_AddRefed<nsIDOMNode> DOMNode() const + { + nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(GetNode()); + return DOMNode.forget(); + } + nsIContent* GetContent() const { return mContent; } - ////////////////////////////////////////////////////////////////////////////// - // Public methods + /** + * Return node type information of DOM node associated with the accessible. + */ + bool IsContent() const + { return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); } + + /** + * Return the unique identifier of the accessible. + */ + void* UniqueID() { return static_cast<void*>(this); } + + /** + * Return language associated with the accessible. + */ + void Language(nsAString& aLocale); /** * Get the description of this accessible. */ virtual void Description(nsString& aDescription); /** * Get the value of this accessible. @@ -142,25 +179,16 @@ public: * Get the name of this accessible. * * Note: aName.IsVoid() when name was left empty by the author on purpose. * aName.IsEmpty() when the author missed name, AT can try to repair a name. */ virtual ENameValueFlag Name(nsString& aName); /** - * Return DOM node associated with this accessible. - */ - inline already_AddRefed<nsIDOMNode> DOMNode() const - { - nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(GetNode()); - return DOMNode.forget(); - } - - /** * Maps ARIA state attributes to state of accessible. Note the given state * argument should hold states for accessible before you pass it into this * method. * * @param [in/out] where to fill the states into. */ virtual void ApplyARIAState(uint64_t* aState) const; @@ -296,16 +324,21 @@ public: * Get the relation of the given type. */ virtual Relation RelationByType(RelationType aType); ////////////////////////////////////////////////////////////////////////////// // Initializing methods /** + * Shutdown this accessible object. + */ + virtual void Shutdown(); + + /** * Set the ARIA role map entry for a new accessible. */ void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry) { mRoleMapEntry = aRoleMapEntry; } /** * Update the children cache. */ @@ -379,17 +412,16 @@ public: inline Accessible* FirstChild() { return GetChildAt(0); } inline Accessible* LastChild() { uint32_t childCount = ChildCount(); return childCount != 0 ? GetChildAt(childCount - 1) : nullptr; } - /** * Return embedded accessible children count. */ uint32_t EmbeddedChildCount(); /** * Return embedded accessible child at the given index. */ @@ -752,16 +784,21 @@ protected: * account ARIA. */ virtual already_AddRefed<nsIPersistentProperties> NativeAttributes(); ////////////////////////////////////////////////////////////////////////////// // Initializing, cache and tree traverse methods /** + * Destroy the object. + */ + void LastRelease(); + + /** * Cache accessible children. */ virtual void CacheChildren(); /** * Set accessible parent and index in parent. */ virtual void BindToParent(Accessible* aParent, uint32_t aIndexInParent); @@ -895,16 +932,19 @@ protected: uint32_t GetActionRule(); /** * Return group info. */ AccGroupInfo* GetGroupInfo(); // Data Members + nsCOMPtr<nsIContent> mContent; + DocAccessible* mDoc; + nsRefPtr<Accessible> mParent; nsTArray<nsRefPtr<Accessible> > mChildren; int32_t mIndexInParent; static const uint8_t kChildrenFlagsBits = 2; static const uint8_t kStateFlagsBits = 5; static const uint8_t kTypeBits = 6; static const uint8_t kGenericTypesBits = 12; @@ -927,16 +967,22 @@ protected: nsAutoPtr<AccGroupInfo> mGroupInfo; friend class AccGroupInfo; /** * Non-null indicates author-supplied role; possibly state & value as well */ nsRoleMapEntry* mRoleMapEntry; + +private: + Accessible() MOZ_DELETE; + Accessible(const Accessible&) MOZ_DELETE; + Accessible& operator =(const Accessible&) MOZ_DELETE; + }; NS_DEFINE_STATIC_IID_ACCESSOR(Accessible, NS_ACCESSIBLE_IMPL_IID) /** * Represent key binding associated with accessible (such as access key and
--- a/accessible/src/generic/ApplicationAccessible.cpp +++ b/accessible/src/generic/ApplicationAccessible.cpp @@ -260,28 +260,24 @@ ApplicationAccessible::GetPlatformVersio nsresult rv = mAppInfo->GetPlatformVersion(cversion); NS_ENSURE_SUCCESS(rv, rv); AppendUTF8toUTF16(cversion, aVersion); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// -// nsAccessNode public methods +// Accessible public methods void ApplicationAccessible::Shutdown() { mAppInfo = nullptr; } - -//////////////////////////////////////////////////////////////////////////////// -// Accessible public methods - void ApplicationAccessible::ApplyARIAState(uint64_t* aState) const { } role ApplicationAccessible::NativeRole() {
--- a/accessible/src/generic/ApplicationAccessible.h +++ b/accessible/src/generic/ApplicationAccessible.h @@ -52,20 +52,18 @@ public: NS_IMETHOD TakeFocus(); NS_IMETHOD GetActionName(uint8_t aIndex, nsAString &aName); NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString &aDescription); NS_IMETHOD DoAction(uint8_t aIndex); // nsIAccessibleApplication NS_DECL_NSIACCESSIBLEAPPLICATION - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE; virtual GroupPos GroupPosition(); virtual ENameValueFlag Name(nsString& aName); virtual void ApplyARIAState(uint64_t* aState) const; virtual void Description(nsString& aDescription); virtual void Value(nsString& aValue); virtual mozilla::a11y::role NativeRole(); virtual uint64_t State();
--- a/accessible/src/generic/BaseAccessibles.cpp +++ b/accessible/src/generic/BaseAccessibles.cpp @@ -150,17 +150,17 @@ LinkableAccessible::DoAction(uint8_t aIn KeyBinding LinkableAccessible::AccessKey() const { return mActionAcc ? mActionAcc->AccessKey() : Accessible::AccessKey(); } //////////////////////////////////////////////////////////////////////////////// -// LinkableAccessible. nsAccessNode +// LinkableAccessible. Accessible void LinkableAccessible::Shutdown() { mIsLink = false; mIsOnclick = false; mActionAcc = nullptr; AccessibleWrap::Shutdown();
--- a/accessible/src/generic/BaseAccessibles.h +++ b/accessible/src/generic/BaseAccessibles.h @@ -59,20 +59,18 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessible NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName); NS_IMETHOD DoAction(uint8_t index); NS_IMETHOD TakeFocus(); - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual void Value(nsString& aValue); virtual uint64_t NativeLinkState() const; // ActionAccessible virtual uint8_t ActionCount(); virtual KeyBinding AccessKey() const; // HyperLinkAccessible
--- a/accessible/src/generic/DocAccessible.cpp +++ b/accessible/src/generic/DocAccessible.cpp @@ -547,17 +547,17 @@ DocAccessible::GetAccessible(nsINode* aN if (parent) parent->TestChildCache(accessible); #endif return accessible; } //////////////////////////////////////////////////////////////////////////////// -// nsAccessNode +// Accessible void DocAccessible::Init() { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eDocCreate)) logging::DocCreate("document initialize", mDocumentNode, this); #endif
--- a/accessible/src/generic/DocAccessible.h +++ b/accessible/src/generic/DocAccessible.h @@ -66,24 +66,23 @@ public: // nsIScrollPositionListener virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) {} virtual void ScrollPositionDidChange(nscoord aX, nscoord aY); // nsIDocumentObserver NS_DECL_NSIDOCUMENTOBSERVER - // nsAccessNode + // Accessible virtual void Init(); virtual void Shutdown(); virtual nsIFrame* GetFrame() const; virtual nsINode* GetNode() const { return mDocumentNode; } nsIDocument* DocumentNode() const { return mDocumentNode; } - // Accessible virtual mozilla::a11y::ENameValueFlag Name(nsString& aName); virtual void Description(nsString& aDescription); virtual Accessible* FocusedChild(); virtual mozilla::a11y::role NativeRole(); virtual uint64_t NativeState(); virtual uint64_t NativeInteractiveState() const; virtual bool NativelyUnavailable() const; virtual void ApplyARIAState(uint64_t* aState) const; @@ -217,17 +216,17 @@ public: * Return whether the given DOM node has an accessible or not. */ bool HasAccessible(nsINode* aNode) const { return GetAccessible(aNode); } /** * Return the cached accessible by the given unique ID within this document. * - * @note the unique ID matches with the uniqueID() of nsAccessNode + * @note the unique ID matches with the uniqueID() of Accessible * * @param aUniqueID [in] the unique ID used to cache the node. */ Accessible* GetAccessibleByUniqueID(void* aUniqueID) { return UniqueID() == aUniqueID ? this : mAccessibleCache.GetWeak(aUniqueID); }
--- a/accessible/src/generic/OuterDocAccessible.cpp +++ b/accessible/src/generic/OuterDocAccessible.cpp @@ -97,17 +97,17 @@ OuterDocAccessible::GetActionDescription NS_IMETHODIMP OuterDocAccessible::DoAction(uint8_t aIndex) { return NS_ERROR_INVALID_ARG; } //////////////////////////////////////////////////////////////////////////////// -// nsAccessNode public +// Accessible public void OuterDocAccessible::Shutdown() { // XXX: sometimes outerdoc accessible is shutdown because of layout style // change however the presshell of underlying document isn't destroyed and // the document doesn't get pagehide events. Schedule a document rebind // to its parent document. Otherwise a document accessible may be lost if its @@ -128,19 +128,16 @@ OuterDocAccessible::Shutdown() #endif RemoveChild(child); mDoc->BindChildDocument(child->AsDoc()); } AccessibleWrap::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// Accessible public - void OuterDocAccessible::InvalidateChildren() { // Do not invalidate children because DocManager is responsible for // document accessible lifetime when DOM document is created or destroyed. If // DOM document isn't destroyed but its presshell is destroyed (for example, // when DOM node of outerdoc accessible is hidden), then outerdoc accessible // notifies DocManager about this. If presshell is created for existing
--- a/accessible/src/generic/OuterDocAccessible.h +++ b/accessible/src/generic/OuterDocAccessible.h @@ -28,20 +28,18 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessible NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName); NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString& aDescription); NS_IMETHOD DoAction(uint8_t aIndex); - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual mozilla::a11y::role NativeRole(); virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild); virtual void InvalidateChildren(); virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) MOZ_OVERRIDE; virtual bool RemoveChild(Accessible* aAccessible);
--- a/accessible/src/generic/RootAccessible.cpp +++ b/accessible/src/generic/RootAccessible.cpp @@ -462,22 +462,22 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START, accessible); } #endif } //////////////////////////////////////////////////////////////////////////////// -// nsAccessNode +// Accessible void RootAccessible::Shutdown() { - // Called manually or by nsAccessNode::LastRelease() + // Called manually or by Accessible::LastRelease() if (!PresShell()) return; // Already shutdown DocAccessibleWrap::Shutdown(); } // nsIAccessible method Relation
--- a/accessible/src/generic/RootAccessible.h +++ b/accessible/src/generic/RootAccessible.h @@ -24,20 +24,18 @@ class RootAccessible : public DocAccessi public: RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent, nsIPresShell* aPresShell); virtual ~RootAccessible(); // nsIDOMEventListener NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual mozilla::a11y::ENameValueFlag Name(nsString& aName); virtual Relation RelationByType(RelationType aType) MOZ_OVERRIDE; virtual mozilla::a11y::role NativeRole(); virtual uint64_t NativeState(); // RootAccessible /**
--- a/accessible/src/html/HTMLListAccessible.cpp +++ b/accessible/src/html/HTMLListAccessible.cpp @@ -142,28 +142,25 @@ HTMLLIAccessible::CacheChildren() HTMLListBulletAccessible:: HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc) : LeafAccessible(aContent, aDoc) { mStateFlags |= eSharedNode; } //////////////////////////////////////////////////////////////////////////////// -// HTMLListBulletAccessible: nsAccessNode +// HTMLListBulletAccessible: Accessible nsIFrame* HTMLListBulletAccessible::GetFrame() const { nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); return blockFrame ? blockFrame->GetBullet() : nullptr; } -//////////////////////////////////////////////////////////////////////////////// -// HTMLListBulletAccessible: Accessible - ENameValueFlag HTMLListBulletAccessible::Name(nsString &aName) { aName.Truncate(); // Native anonymous content, ARIA can't be used. Get list bullet text. nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); if (blockFrame) {
--- a/accessible/src/html/HTMLListAccessible.h +++ b/accessible/src/html/HTMLListAccessible.h @@ -41,24 +41,22 @@ class HTMLLIAccessible : public HyperTex { public: HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc); virtual ~HTMLLIAccessible() { } // nsISupports NS_DECL_ISUPPORTS_INHERITED - // nsAccessNode - virtual void Shutdown(); - // nsIAccessible NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth, int32_t* aHeight); // Accessible + virtual void Shutdown(); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); // nsHTMLLIAccessible void UpdateBullet(bool aHasBullet); protected: // Accessible @@ -73,20 +71,18 @@ private: * Used for bullet of HTML list item element (for example, HTML li). */ class HTMLListBulletAccessible : public LeafAccessible { public: HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc); virtual ~HTMLListBulletAccessible() { } - // nsAccessNode + // Accessible virtual nsIFrame* GetFrame() const; - - // Accessible virtual ENameValueFlag Name(nsString& aName); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0, uint32_t aLength = UINT32_MAX); // HTMLListBulletAccessible
--- a/accessible/src/html/HTMLSelectAccessible.cpp +++ b/accessible/src/html/HTMLSelectAccessible.cpp @@ -590,36 +590,33 @@ HTMLComboboxListAccessible:: HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent, DocAccessible* aDoc) : HTMLSelectListAccessible(aContent, aDoc) { mStateFlags |= eSharedNode; } //////////////////////////////////////////////////////////////////////////////// -// HTMLComboboxAccessible: nsAccessNode +// HTMLComboboxAccessible: Accessible nsIFrame* HTMLComboboxListAccessible::GetFrame() const { nsIFrame* frame = HTMLSelectListAccessible::GetFrame(); if (frame) { nsIComboboxControlFrame* comboBox = do_QueryFrame(frame); if (comboBox) { return comboBox->GetDropDown(); } } return nullptr; } -//////////////////////////////////////////////////////////////////////////////// -// HTMLComboboxAccessible: Accessible - role HTMLComboboxListAccessible::NativeRole() { return roles::COMBOBOX_LIST; } uint64_t HTMLComboboxListAccessible::NativeState()
--- a/accessible/src/html/HTMLSelectAccessible.h +++ b/accessible/src/html/HTMLSelectAccessible.h @@ -170,20 +170,18 @@ public: HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc); virtual ~HTMLComboboxAccessible() {} // nsIAccessible NS_IMETHOD DoAction(uint8_t index); NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName); - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual void Description(nsString& aDescription); virtual void Value(nsString& aValue); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual void InvalidateChildren(); // ActionAccessible virtual uint8_t ActionCount(); @@ -216,20 +214,18 @@ private: class HTMLComboboxListAccessible : public HTMLSelectListAccessible { public: HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent, DocAccessible* aDoc); virtual ~HTMLComboboxListAccessible() {} - // nsAccessNode + // Accessible virtual nsIFrame* GetFrame() const; - - // Accessible virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame); // Widgets virtual bool IsActiveWidget() const; virtual bool AreItemsOperable() const; };
--- a/accessible/src/html/HTMLTableAccessible.cpp +++ b/accessible/src/html/HTMLTableAccessible.cpp @@ -360,29 +360,25 @@ HTMLTableRowAccessible::NativeRole() //////////////////////////////////////////////////////////////////////////////// // HTMLTableAccessible //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableAccessible, Accessible, nsIAccessibleTable) //////////////////////////////////////////////////////////////////////////////// -//nsAccessNode +// HTMLTableAccessible: Accessible void HTMLTableAccessible::Shutdown() { mTable = nullptr; AccessibleWrap::Shutdown(); } - -//////////////////////////////////////////////////////////////////////////////// -// HTMLTableAccessible: Accessible implementation - void HTMLTableAccessible::CacheChildren() { // Move caption accessible so that it's the first child. Check for the first // caption only, because nsAccessibilityService ensures we don't create // accessibles for the other captions, since only the first is actually // visible. TreeWalker walker(this, mContent);
--- a/accessible/src/html/HTMLTableAccessible.h +++ b/accessible/src/html/HTMLTableAccessible.h @@ -158,20 +158,18 @@ public: 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 + // Accessible virtual void Shutdown(); - - // Accessible virtual TableAccessible* AsTable() { return this; } virtual void Description(nsString& aDescription); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE; virtual Relation RelationByType(RelationType aRelationType) MOZ_OVERRIDE; protected:
--- a/accessible/src/windows/msaa/DocAccessibleWrap.cpp +++ b/accessible/src/windows/msaa/DocAccessibleWrap.cpp @@ -72,17 +72,17 @@ DocAccessibleWrap::get_accValue(VARIANT *aValue = ::SysAllocStringLen(URL.get(), URL.Length()); return *aValue ? S_OK : E_OUTOFMEMORY; A11Y_TRYBLOCK_END } //////////////////////////////////////////////////////////////////////////////// -// nsAccessNode +// Accessible void DocAccessibleWrap::Shutdown() { // Do window emulation specific shutdown if emulation was started. if (nsWinUtils::IsWindowEmulationStarted()) { // Destroy window created for root document. if (mDocFlags & eTabDocument) {
--- a/accessible/src/windows/msaa/DocAccessibleWrap.h +++ b/accessible/src/windows/msaa/DocAccessibleWrap.h @@ -23,17 +23,17 @@ public: // IAccessible // Override get_accValue to provide URL when no other value is available virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR __RPC_FAR *pszValue); - // nsAccessNode + // Accessible virtual void Shutdown(); // DocAccessible virtual void* GetNativeWindow() const; protected: // DocAccessible virtual void DoInitialUpdate();
--- a/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.cpp +++ b/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.cpp @@ -20,28 +20,25 @@ HTMLWin32ObjectOwnerAccessible:: AccessibleWrap(aContent, aDoc), mHwnd(aHwnd) { // Our only child is a HTMLWin32ObjectAccessible object. if (mHwnd) mNativeAccessible = new HTMLWin32ObjectAccessible(mHwnd); } //////////////////////////////////////////////////////////////////////////////// -// HTMLWin32ObjectOwnerAccessible: nsAccessNode implementation +// HTMLWin32ObjectOwnerAccessible: Accessible implementation void HTMLWin32ObjectOwnerAccessible::Shutdown() { AccessibleWrap::Shutdown(); mNativeAccessible = nullptr; } -//////////////////////////////////////////////////////////////////////////////// -// HTMLWin32ObjectOwnerAccessible: Accessible implementation - role HTMLWin32ObjectOwnerAccessible::NativeRole() { return roles::EMBEDDED_OBJECT; } bool HTMLWin32ObjectOwnerAccessible::NativelyUnavailable() const
--- a/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.h +++ b/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.h @@ -21,20 +21,18 @@ public: // will still point to Gecko accessible sibling content. This is necessary // because the native plugin accessible doesn't know where it exists in the // Mozilla tree, and returns null for previous and next sibling. This would // have the effect of cutting off all content after the plugin. HTMLWin32ObjectOwnerAccessible(nsIContent* aContent, DocAccessible* aDoc, void* aHwnd); virtual ~HTMLWin32ObjectOwnerAccessible() {} - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual mozilla::a11y::role NativeRole(); virtual bool NativelyUnavailable() const; protected: // Accessible virtual void CacheChildren();
--- a/accessible/src/xul/XULListboxAccessible.cpp +++ b/accessible/src/xul/XULListboxAccessible.cpp @@ -128,17 +128,17 @@ XULListboxAccessible::QueryInterface(REF NS_ADDREF_THIS(); return NS_OK; } return NS_ERROR_NO_INTERFACE; } //////////////////////////////////////////////////////////////////////////////// -//nsAccessNode +// Accessible void XULListboxAccessible::Shutdown() { mTable = nullptr; XULSelectControlAccessible::Shutdown(); }
--- a/accessible/src/xul/XULListboxAccessible.h +++ b/accessible/src/xul/XULListboxAccessible.h @@ -87,20 +87,18 @@ 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 SelectRow(uint32_t aRowIdx); virtual void UnselectRow(uint32_t aRowIdx); virtual Accessible* AsAccessible() { return this; } - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual void Value(nsString& aValue); virtual TableAccessible* AsTable() { return this; } virtual a11y::role NativeRole(); virtual uint64_t NativeState(); // Widgets virtual bool IsWidget() const; virtual bool IsActiveWidget() const;
--- a/accessible/src/xul/XULSelectControlAccessible.cpp +++ b/accessible/src/xul/XULSelectControlAccessible.cpp @@ -31,17 +31,17 @@ XULSelectControlAccessible:: XULSelectControlAccessible(nsIContent* aContent, DocAccessible* aDoc) : AccessibleWrap(aContent, aDoc) { mGenericTypes |= eSelect; mSelectControl = do_QueryInterface(aContent); } //////////////////////////////////////////////////////////////////////////////// -// XULSelectControlAccessible: nsAccessNode +// XULSelectControlAccessible: Accessible void XULSelectControlAccessible::Shutdown() { mSelectControl = nullptr; AccessibleWrap::Shutdown(); }
--- a/accessible/src/xul/XULSelectControlAccessible.h +++ b/accessible/src/xul/XULSelectControlAccessible.h @@ -17,17 +17,17 @@ namespace a11y { * The basic implementation of accessible selection for XUL select controls. */ class XULSelectControlAccessible : public AccessibleWrap { public: XULSelectControlAccessible(nsIContent* aContent, DocAccessible* aDoc); virtual ~XULSelectControlAccessible() {} - // nsAccessNode + // Accessible virtual void Shutdown(); // SelectAccessible virtual already_AddRefed<nsIArray> SelectedItems(); virtual uint32_t SelectedItemCount(); virtual Accessible* GetSelectedItem(uint32_t aIndex); virtual bool IsItemSelected(uint32_t aIndex); virtual bool AddItemToSelection(uint32_t aIndex);
--- a/accessible/src/xul/XULTreeAccessible.cpp +++ b/accessible/src/xul/XULTreeAccessible.cpp @@ -129,36 +129,33 @@ XULTreeAccessible::Value(nsString& aValu cols->GetKeyColumn(getter_AddRefs(keyCol)); mTreeView->GetCellText(currentIndex, keyCol, aValue); } } //////////////////////////////////////////////////////////////////////////////// -// XULTreeAccessible: nsAccessNode implementation +// XULTreeAccessible: Accessible implementation void XULTreeAccessible::Shutdown() { // XXX: we don't remove accessible from document cache if shutdown wasn't // initiated by document destroying. Note, we can't remove accessible from // document cache here while document is going to be shutdown. Note, this is // not unique place where we have similar problem. ClearCache(mAccessibleCache); mTree = nullptr; mTreeView = nullptr; AccessibleWrap::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// XULTreeAccessible: Accessible implementation (put methods here) - role XULTreeAccessible::NativeRole() { // No primary column means we're in a list. In fact, history and mail turn off // the primary flag when switching to a flat view. nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren); NS_ASSERTION(child, "tree without treechildren!"); @@ -884,32 +881,28 @@ XULTreeItemAccessibleBase::DoAction(uint (aIndex != eAction_Expand || !IsExpandable())) return NS_ERROR_INVALID_ARG; DoCommand(nullptr, aIndex); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// -// XULTreeItemAccessibleBase: nsAccessNode implementation +// XULTreeItemAccessibleBase: Accessible implementation void XULTreeItemAccessibleBase::Shutdown() { mTree = nullptr; mTreeView = nullptr; mRow = -1; AccessibleWrap::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// XULTreeItemAccessibleBase: Accessible public methods - -// nsIAccessible::groupPosition GroupPos XULTreeItemAccessibleBase::GroupPosition() { GroupPos groupPos; int32_t level; nsresult rv = mTreeView->GetLevel(mRow, &level); NS_ENSURE_SUCCESS(rv, groupPos); @@ -1129,28 +1122,25 @@ XULTreeItemAccessible::Name(nsString& aN { aName.Truncate(); GetCellName(mColumn, aName); return eNameOK; } //////////////////////////////////////////////////////////////////////////////// -// XULTreeItemAccessible: nsAccessNode implementation +// XULTreeItemAccessible: Accessible implementation void XULTreeItemAccessible::Shutdown() { mColumn = nullptr; XULTreeItemAccessibleBase::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// XULTreeItemAccessible: Accessible implementation - role XULTreeItemAccessible::NativeRole() { nsCOMPtr<nsITreeColumns> columns; mTree->GetColumns(getter_AddRefs(columns)); if (!columns) { NS_ERROR("No tree columns object in the tree!"); return roles::NOTHING;
--- a/accessible/src/xul/XULTreeAccessible.h +++ b/accessible/src/xul/XULTreeAccessible.h @@ -33,20 +33,18 @@ public: XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, nsTreeBodyFrame* aTreeframe); // nsISupports and cycle collection NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeAccessible, Accessible) - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual void Value(nsString& aValue); virtual a11y::role NativeRole(); virtual uint64_t NativeState(); virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild); virtual Accessible* GetChildAt(uint32_t aIndex); virtual uint32_t ChildCount() const; @@ -150,20 +148,18 @@ public: int32_t *aWidth, int32_t *aHeight); NS_IMETHOD SetSelected(bool aSelect); NS_IMETHOD TakeFocus(); NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName); NS_IMETHOD DoAction(uint8_t aIndex); - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual GroupPos GroupPosition(); virtual uint64_t NativeState(); virtual uint64_t NativeInteractiveState() const; virtual int32_t IndexInParent() const; virtual Relation RelationByType(RelationType aType) MOZ_OVERRIDE; virtual Accessible* FocusedChild(); // ActionAccessible @@ -231,20 +227,18 @@ public: Accessible* aParent, nsITreeBoxObject* aTree, nsITreeView* aTreeView, int32_t aRow); // nsISupports and cycle collection NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase) - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual ENameValueFlag Name(nsString& aName); virtual a11y::role NativeRole(); // XULTreeItemAccessibleBase virtual void RowInvalidated(int32_t aStartColIdx, int32_t aEndColIdx); protected:
--- a/accessible/src/xul/XULTreeGridAccessible.cpp +++ b/accessible/src/xul/XULTreeGridAccessible.cpp @@ -215,28 +215,25 @@ XULTreeGridAccessible::UnselectRow(uint3 nsCOMPtr<nsITreeSelection> selection; mTreeView->GetSelection(getter_AddRefs(selection)); if (selection) selection->ClearRange(aRowIdx, aRowIdx); } //////////////////////////////////////////////////////////////////////////////// -// XULTreeGridAccessible: nsAccessNode implementation +// XULTreeGridAccessible: Accessible implementation void XULTreeGridAccessible::Shutdown() { mTable = nullptr; XULTreeAccessible::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// XULTreeGridAccessible: Accessible implementation - role XULTreeGridAccessible::NativeRole() { nsCOMPtr<nsITreeColumns> treeColumns; mTree->GetColumns(getter_AddRefs(treeColumns)); if (!treeColumns) { NS_ERROR("No treecolumns object for tree!"); return roles::NOTHING; @@ -286,28 +283,25 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_ NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase) NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase) NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase) //////////////////////////////////////////////////////////////////////////////// -// XULTreeGridRowAccessible: nsAccessNode implementation +// XULTreeGridRowAccessible: Accessible implementation void XULTreeGridRowAccessible::Shutdown() { ClearCache(mAccessibleCache); XULTreeItemAccessibleBase::Shutdown(); } -//////////////////////////////////////////////////////////////////////////////// -// XULTreeGridRowAccessible: Accessible implementation - role XULTreeGridRowAccessible::NativeRole() { return roles::ROW; } ENameValueFlag XULTreeGridRowAccessible::Name(nsString& aName)
--- a/accessible/src/xul/XULTreeGridAccessible.h +++ b/accessible/src/xul/XULTreeGridAccessible.h @@ -49,20 +49,18 @@ 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 SelectRow(uint32_t aRowIdx); virtual void UnselectRow(uint32_t aRowIdx); virtual Accessible* AsAccessible() { return this; } - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual TableAccessible* AsTable() { return this; } virtual a11y::role NativeRole(); protected: // XULTreeAccessible virtual already_AddRefed<Accessible> CreateTreeItemAccessible(int32_t aRow); }; @@ -81,20 +79,18 @@ public: Accessible* aParent, nsITreeBoxObject* aTree, nsITreeView* aTreeView, int32_t aRow); // nsISupports and cycle collection NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase) - // nsAccessNode + // Accessible virtual void Shutdown(); - - // Accessible virtual a11y::role NativeRole(); virtual ENameValueFlag Name(nsString& aName); virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild); virtual Accessible* GetChildAt(uint32_t aIndex); virtual uint32_t ChildCount() const;
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -563,16 +563,20 @@ pref("dom.disable_window_print", true); // Disable window.showModalDialog pref("dom.disable_window_showModalDialog", true); // Enable new experimental html forms pref("dom.experimental_forms", true); pref("dom.forms.number", true); +// Don't enable <input type=color> yet as we don't have a color picker +// implemented for b2g (bug 875751) +pref("dom.forms.color", false); + // Turns on gralloc-based direct texturing for Gonk pref("gfx.gralloc.enabled", false); // XXXX REMOVE FOR PRODUCTION. Turns on GC and CC logging pref("javascript.options.mem.log", false); // Increase mark slice time from 10ms to 30ms pref("javascript.options.mem.gc_incremental_slice_ms", 30);
--- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "166023c341cca944563c410f05dff37a992cb05b", + "revision": "d2dbad943faf566fe36dbe79086127da837af6a3", "repo_path": "/integration/gaia-central" }
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -540,19 +540,16 @@ @BINPATH@/components/ActivityWrapper.js @BINPATH@/components/ActivityMessageConfigurator.js @BINPATH@/components/TCPSocket.js @BINPATH@/components/TCPServerSocket.js @BINPATH@/components/TCPSocketParentIntermediary.js @BINPATH@/components/TCPSocket.manifest -@BINPATH@/components/AppProtocolHandler.js -@BINPATH@/components/AppProtocolHandler.manifest - @BINPATH@/components/Payment.js @BINPATH@/components/PaymentFlowInfo.js @BINPATH@/components/PaymentRequestInfo.js @BINPATH@/components/Payment.manifest ; InputMethod API @BINPATH@/components/MozKeyboard.js @BINPATH@/components/InputMethod.manifest
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1181,17 +1181,17 @@ pref("devtools.gcli.hideIntro", false); // How eager are we to show help: never=1, sometimes=2, always=3 pref("devtools.gcli.eagerHelper", 2); // Remember the Web Console filters pref("devtools.webconsole.filter.network", true); pref("devtools.webconsole.filter.networkinfo", true); pref("devtools.webconsole.filter.netwarn", true); pref("devtools.webconsole.filter.csserror", true); -pref("devtools.webconsole.filter.cssparser", true); +pref("devtools.webconsole.filter.cssparser", false); pref("devtools.webconsole.filter.csslog", false); pref("devtools.webconsole.filter.exception", true); pref("devtools.webconsole.filter.jswarn", true); pref("devtools.webconsole.filter.jslog", true); pref("devtools.webconsole.filter.error", true); pref("devtools.webconsole.filter.warn", true); pref("devtools.webconsole.filter.info", true); pref("devtools.webconsole.filter.log", true);
--- a/browser/base/content/test/general/browser_popupNotification.js +++ b/browser/base/content/test/general/browser_popupNotification.js @@ -144,70 +144,38 @@ function basicNotification() { self.shownCallbackTriggered = true; break; case "removed": self.removedCallbackTriggered = true; break; } } }; - this.addOptions = function(options) { - for (let [name, value] in Iterator(options)) - self.options[name] = value; - } } +basicNotification.prototype.addOptions = function(options) { + for (let [name, value] in Iterator(options)) + this.options[name] = value; +}; + function errorNotification() { var self = this; - this.browser = gBrowser.selectedBrowser; - this.id = "test-notification-" + gTestIndex; - this.message = "This is popup notification " + this.id + " from test " + gTestIndex; - this.anchorID = null; - this.mainAction = { - label: "Main Action", - accessKey: "M", - callback: function () { - self.mainActionClicked = true; - throw new Error("Oops!"); - } + this.mainAction.callback = function () { + self.mainActionClicked = true; + throw new Error("Oops!"); }; - this.secondaryActions = [ - { - label: "Secondary Action", - accessKey: "S", - callback: function () { - self.secondaryActionClicked = true; - throw new Error("Oops!"); - } - } - ]; - this.options = { - eventCallback: function (eventName) { - switch (eventName) { - case "dismissed": - self.dismissalCallbackTriggered = true; - break; - case "showing": - self.showingCallbackTriggered = true; - break; - case "shown": - self.shownCallbackTriggered = true; - break; - case "removed": - self.removedCallbackTriggered = true; - break; - } - } + this.secondaryActions[0].callback = function () { + self.secondaryActionClicked = true; + throw new Error("Oops!"); }; - this.addOptions = function(options) { - for (let [name, value] in Iterator(options)) - self.options[name] = value; - } } +errorNotification.prototype = new basicNotification(); +errorNotification.prototype.constructor = errorNotification; + var wrongBrowserNotificationObject = new basicNotification(); var wrongBrowserNotification; var tests = [ { // Test #0 run: function () { this.notifyObj = new basicNotification(); showNotification(this.notifyObj);
--- a/browser/devtools/app-manager/content/projects.js +++ b/browser/devtools/app-manager/content/projects.js @@ -9,17 +9,17 @@ const Cr = Components.results; Cu.import("resource:///modules/devtools/gDevTools.jsm"); const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); const {require} = devtools; const {ConnectionManager, Connection} = require("devtools/client/connection-manager"); const {AppProjects} = require("devtools/app-manager/app-projects"); const {AppValidator} = require("devtools/app-manager/app-validator"); const {Services} = Cu.import("resource://gre/modules/Services.jsm"); const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm"); -const {installHosted, installPackaged, getTargetForApp} = require("devtools/app-actor-front"); +const {installHosted, installPackaged, getTargetForApp, reloadApp} = require("devtools/app-actor-front"); const {EventEmitter} = Cu.import("resource:///modules/devtools/shared/event-emitter.js"); const promise = require("sdk/core/promise"); const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled"; window.addEventListener("message", function(event) { try { @@ -171,26 +171,36 @@ let UI = { }) .then(() => { // Install the app to the device if we are connected, // and there is no error if (project.errorsCount == 0 && this.listTabsResponse) { return this.install(project); } }) - .then( - () => { + .then(() => { button.disabled = false; - }, - (res) => { - button.disabled = false; - let message = res.error + ": " + res.message; - alert(message); - this.connection.log(message); - }); + // Finally try to reload the app if it is already opened + this.reload(project); + }, + (res) => { + button.disabled = false; + let message = res.error + ": " + res.message; + alert(message); + this.connection.log(message); + }); + }, + + reload: function (project) { + return reloadApp(this.connection.client, + this.listTabsResponse.webappsActor, + this._getProjectManifestURL(project)). + then(() => { + this.connection.log("App reloaded"); + }); }, remove: function(location, event) { if (event) { // We don't want the "click" event to be propagated to the project item. // That would trigger `selectProject()`. event.stopPropagation(); }
--- a/browser/devtools/shadereditor/test/head.js +++ b/browser/devtools/shadereditor/test/head.js @@ -196,17 +196,17 @@ function ensurePixelIs(aDebuggee, aPosit function navigate(aTarget, aUrl) { let navigated = once(aTarget, "navigate"); aTarget.client.activeTab.navigateTo(aUrl); return navigated; } function reload(aTarget) { let navigated = once(aTarget, "navigate"); - aTarget.client.activeTab.reload(); + executeSoon(() => aTarget.client.activeTab.reload()); return navigated; } function initBackend(aUrl) { info("Initializing a shader editor front."); if (!DebuggerServer.initialized) { DebuggerServer.init(() => true);
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -516,19 +516,16 @@ @BINPATH@/components/Push.js @BINPATH@/components/Push.manifest @BINPATH@/components/PushServiceLauncher.js @BINPATH@/components/TCPSocket.js @BINPATH@/components/TCPServerSocket.js @BINPATH@/components/TCPSocketParentIntermediary.js @BINPATH@/components/TCPSocket.manifest -@BINPATH@/components/AppProtocolHandler.js -@BINPATH@/components/AppProtocolHandler.manifest - @BINPATH@/components/Payment.js @BINPATH@/components/PaymentFlowInfo.js @BINPATH@/components/PaymentRequestInfo.js @BINPATH@/components/Payment.manifest #ifdef MOZ_WEBRTC @BINPATH@/components/PeerConnection.js @BINPATH@/components/PeerConnection.manifest
--- a/browser/metro/base/content/browser.xul +++ b/browser/metro/base/content/browser.xul @@ -233,17 +233,18 @@ <box id="identity-box" align="center" role="button"> <image id="identity-icon"/> </box> <textbox id="urlbar-edit" type="url" flex="1" autocompletesearch="history" autocompletepopup="urlbar-autocomplete" completeselectedindex="true" - placeholder="&urlbar.emptytext;"/> + placeholder="&urlbar.emptytext;" + onclick="SelectionHelperUI.urlbarClick();"/> <toolbarbutton id="go-button" class="urlbar-button" command="cmd_go"/> <toolbarbutton id="reload-button" class="urlbar-button" oncommand="CommandUpdater.doCommand( event.shiftKey ? 'cmd_forceReload' : 'cmd_reload');"/> <toolbarbutton id="stop-button" class="urlbar-button"
--- a/browser/metro/base/content/contenthandlers/SelectionHandler.js +++ b/browser/metro/base/content/contenthandlers/SelectionHandler.js @@ -20,16 +20,17 @@ var SelectionHandler = { addMessageListener("Browser:SelectionCopy", this); addMessageListener("Browser:SelectionDebug", this); addMessageListener("Browser:CaretAttach", this); addMessageListener("Browser:CaretMove", this); addMessageListener("Browser:CaretUpdate", this); addMessageListener("Browser:SelectionSwitchMode", this); addMessageListener("Browser:RepositionInfoRequest", this); addMessageListener("Browser:SelectionHandlerPing", this); + addMessageListener("Browser:ResetLastPos", this); }, shutdown: function shutdown() { removeMessageListener("Browser:SelectionStart", this); removeMessageListener("Browser:SelectionAttach", this); removeMessageListener("Browser:SelectionEnd", this); removeMessageListener("Browser:SelectionMoveStart", this); removeMessageListener("Browser:SelectionMove", this); @@ -39,16 +40,17 @@ var SelectionHandler = { removeMessageListener("Browser:SelectionCopy", this); removeMessageListener("Browser:SelectionDebug", this); removeMessageListener("Browser:CaretAttach", this); removeMessageListener("Browser:CaretMove", this); removeMessageListener("Browser:CaretUpdate", this); removeMessageListener("Browser:SelectionSwitchMode", this); removeMessageListener("Browser:RepositionInfoRequest", this); removeMessageListener("Browser:SelectionHandlerPing", this); + removeMessageListener("Browser:ResetLastPos", this); }, sendAsync: function sendAsync(aMsg, aJson) { sendAsyncMessage(aMsg, aJson); }, /************************************************* * Browser event handlers @@ -538,16 +540,20 @@ var SelectionHandler = { content.setTimeout (function () { SelectionHandler._repositionInfoRequest(json); }, 50); break; case "Browser:SelectionHandlerPing": this._onPing(json.id); break; + + case "Browser:ResetLastPos": + this._onClickCoords(json.xPos, json.yPos); + break; } }, /************************************************* * Utilities */ /*
--- a/browser/metro/base/content/helperui/SelectionHelperUI.js +++ b/browser/metro/base/content/helperui/SelectionHelperUI.js @@ -787,16 +787,26 @@ var SelectionHelperUI = { this.startMark.show(); } }, /* * Event handlers for document events */ + urlbarClick: function() { + // Workaround for bug 925457: taping browser chrome resets last tap + // co-ordinates to 'undefined' so that we know not to shift the browser + // when the keyboard is up (in SelectionHandler._calcNewContentPosition()) + Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:ResetLastPos", { + xPos: null, + yPos: null + }); + }, + /* * Handles taps that move the current caret around in text edits, * clear active selection and focus when neccessary, or change * modes. */ _onClick: function(aEvent) { if (this.layerMode == kChromeLayer && this._targetIsEditable) { this.attachToCaret(this._msgTarget, aEvent.clientX, aEvent.clientY);
--- a/browser/metro/profile/metro.js +++ b/browser/metro/profile/metro.js @@ -643,8 +643,12 @@ pref("full-screen-api.content-only", tru pref("full-screen-api.ignore-widgets", true); // image visibility prefs. // image visibility tries to only keep images near the viewport decoded instead // of keeping all images decoded. pref("layout.imagevisibility.enabled", true); pref("layout.imagevisibility.numscrollportwidths", 1); pref("layout.imagevisibility.numscrollportheights", 1); + +// Don't enable <input type=color> yet as we don't have a color picker +// implemented for Windows Metro (bug 895464) +pref("dom.forms.color", false);
--- a/browser/themes/shared/devtools/dark-theme.css +++ b/browser/themes/shared/devtools/dark-theme.css @@ -58,34 +58,34 @@ .theme-link, .cm-s-mozilla .cm-link { /* blue */ color: #3689b2; } .theme-comment, .cm-s-mozilla .cm-meta, -.cm-s-mozilla .cm-hr { /* grey */ +.cm-s-mozilla .cm-hr, +.cm-s-mozilla .cm-comment { /* grey */ color: #5c6773; } .theme-gutter { background-color: #0f171f; color: #667380; border-color: #303b47; } .theme-separator { /* grey */ border-color: #303b47; } .theme-fg-color1, .cm-s-mozilla .cm-variable-2, -.cm-s-mozilla .cm-quote, -.cm-s-mozilla .CodeMirror-matchingbracket { /* green */ +.cm-s-mozilla .cm-quote { /* green */ color: #5c9966; } .theme-fg-color2, .cm-s-mozilla .cm-attribute, .cm-s-mozilla .cm-builtin, .cm-s-mozilla .cm-variable, .cm-s-mozilla .cm-def, @@ -96,35 +96,33 @@ } .theme-fg-color3, .cm-s-mozilla .cm-tag, .cm-s-mozilla .cm-header { /* pink/lavender */ color: #a673bf; } -.theme-fg-color4, -.cm-s-mozilla .cm-comment { /* purple/violet */ +.theme-fg-color4 { /* purple/violet */ color: #6270b2; } .theme-fg-color5, .cm-s-mozilla .cm-bracket, .cm-s-mozilla .cm-atom, .cm-s-mozilla .cm-keyword { /* Yellow */ color: #a18650; } .theme-fg-color6, .cm-s-mozilla .cm-string { /* Orange */ color: #b26b47; } .theme-fg-color7, -.cm-s-mozilla .CodeMirror-nonmatchingbracket, .cm-s-mozilla .cm-string-2, .cm-s-mozilla .cm-error { /* Red */ color: #bf5656; } .theme-fg-contrast { /* To be used for text on theme-bg-contrast */ color: black; } @@ -155,20 +153,28 @@ .cm-s-mozilla .CodeMirror-lines .CodeMirror-cursor { border-left: solid 1px #fff; } .cm-s-mozilla.CodeMirror-focused .CodeMirror-selected { /* selected text (focused) */ background: rgb(185, 215, 253); } -.dcm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */ +.cm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */ background: rgb(176, 176, 176); } .CodeMirror-activeline-background { /* selected color with alpha */ - background: rgba(185, 215, 253, .05); + background: rgba(185, 215, 253, .15); +} + +.cm-s-mozilla .CodeMirror-linenumber { /* line number text */ + color: #5f7387; +} + +.cm-s-mozilla .CodeMirror-gutters { /* vertical line next to line numbers */ + border-right-color: #343c45; } .cm-s-markup-view pre { line-height: 1.4em; min-height: 1.4em; }
--- a/browser/themes/shared/devtools/light-theme.css +++ b/browser/themes/shared/devtools/light-theme.css @@ -58,34 +58,34 @@ .theme-link, .cm-s-mozilla .cm-link { /* blue */ color: hsl(208,56%,40%); } .theme-comment, .cm-s-mozilla .cm-meta, -.cm-s-mozilla .cm-hr { /* grey */ +.cm-s-mozilla .cm-hr, +.cm-s-mozilla .cm-comment { /* grey */ color: hsl(90,2%,46%); } .theme-gutter { background-color: hsl(0,0%,90%); color: #667380; border-color: hsl(0,0%,65%); } .theme-separator { /* grey */ border-color: #cddae5; } .theme-fg-color1, .cm-s-mozilla .cm-variable-2, -.cm-s-mozilla .cm-quote, -.cm-s-mozilla .CodeMirror-matchingbracket { /* green */ +.cm-s-mozilla .cm-quote { /* green */ color: hsl(72,100%,27%); } .theme-fg-color2, .cm-s-mozilla .cm-attribute, .cm-s-mozilla .cm-builtin, .cm-s-mozilla .cm-variable, .cm-s-mozilla .cm-def, @@ -96,35 +96,33 @@ } .theme-fg-color3, .cm-s-mozilla .cm-tag, .cm-s-mozilla .cm-header { /* dark blue */ color: hsl(208,81%,21%) } -.theme-fg-color4, -.cm-s-mozilla .cm-comment { /* Orange */ +.theme-fg-color4 { /* Orange */ color: hsl(24,85%,39%); } .theme-fg-color5, .cm-s-mozilla .cm-bracket, .cm-s-mozilla .cm-keyword, .cm-s-mozilla .cm-atom { /* Yellow */ color: #a18650; } .theme-fg-color6, .cm-s-mozilla .cm-string { /* Orange */ color: hsl(24,85%,39%); } .theme-fg-color7, -.cm-s-mozilla .CodeMirror-nonmatchingbracket, .cm-s-mozilla .cm-string-2, .cm-s-mozilla .cm-error { /* Red */ color: #bf5656; } .theme-fg-contrast { /* To be used for text on theme-bg-contrast */ color: black; } @@ -160,15 +158,28 @@ background: rgb(185, 215, 253); } .cm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */ background: rgb(176, 176, 176); } .CodeMirror-activeline-background { /* selected color with alpha */ - background: rgba(185, 215, 253, .4); + background: rgba(185, 215, 253, .35); +} + +div.cm-s-mozilla span.CodeMirror-matchingbracket { /* highlight brackets */ + outline: solid 1px rgba(0, 0, 0, .25); + color: black; +} + +.cm-s-mozilla .CodeMirror-linenumber { /* line number text */ + color: #667380; +} + +.cm-s-mozilla .CodeMirror-gutters { /* vertical line next to line numbers */ + border-right-color: #a6a6a6; } .cm-s-markup-view pre { line-height: 1.4em; min-height: 1.4em; }
--- a/build/ConfigStatus.py +++ b/build/ConfigStatus.py @@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo from mozbuild.frontend.emitter import TreeMetadataEmitter from mozbuild.frontend.reader import BuildReader from mozbuild.mozinfo import write_mozinfo log_manager = LoggingManager() -def config_status(topobjdir = '.', topsrcdir = '.', - defines = [], non_global_defines = [], substs = [], - files = [], headers = []): +def config_status(topobjdir='.', topsrcdir='.', + defines=[], non_global_defines=[], substs=[]): '''Main function, providing config.status functionality. Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS - variables, but like config.status from autoconf 2.6, single files may be - generated with the --file and --header options. Several such options can - be given to generate several files at the same time. + variables. Without the -n option, this program acts as config.status and considers the current directory as the top object directory, even when config.status is in a different directory. It will, however, treat the directory - containing config.status as the top object directory with the -n option, - while files given to the --file and --header arguments are considered - relative to the current directory. + containing config.status as the top object directory with the -n option. The --recheck option, like with the original config.status, runs configure again, with the options given in the "ac_configure_args" subst. The options to this function are passed when creating the - ConfigEnvironment, except for files and headers, which contain the list - of files and headers to be generated by default. These lists, as well as - the actual wrapper script around this function, are meant to be generated - by configure. See build/autoconf/config.status.m4. - - Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS, - but like config.status behaviour with --file and --header, providing - files or headers on the command line inhibits the default generation of - files when given headers and headers when given files. - - Unlike config.status, the FILE:TEMPLATE syntax is not supported for - files and headers. The template is always the filename suffixed with - '.in', in the corresponding directory under the top source directory. + ConfigEnvironment. These lists, as well as the actual wrapper script + around this function, are meant to be generated by configure. + See build/autoconf/config.status.m4. ''' if 'CONFIG_FILES' in os.environ: - raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.' + raise Exception('Using the CONFIG_FILES environment variable is not ' + 'supported.') if 'CONFIG_HEADERS' in os.environ: - raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.' + raise Exception('Using the CONFIG_HEADERS environment variable is not ' + 'supported.') + + if not os.path.isabs(topsrcdir): + raise Exception('topsrcdir must be defined as an absolute directory: ' + '%s' % topsrcdir) parser = OptionParser() parser.add_option('--recheck', dest='recheck', action='store_true', help='update config.status by reconfiguring in the same conditions') - parser.add_option('--file', dest='files', metavar='FILE', action='append', - help='instantiate the configuration file FILE') - parser.add_option('--header', dest='headers', metavar='FILE', action='append', - help='instantiate the configuration header FILE') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='display verbose output') parser.add_option('-n', dest='not_topobjdir', action='store_true', help='do not consider current directory as top object directory') (options, args) = parser.parse_args() # Without -n, the current directory is meant to be the top object directory if not options.not_topobjdir: @@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr reader = BuildReader(env) emitter = TreeMetadataEmitter(env) backend = RecursiveMakeBackend(env) # This won't actually do anything because of the magic of generators. definitions = emitter.emit(reader.read_topsrcdir()) if options.recheck: # Execute configure from the top object directory - if not os.path.isabs(topsrcdir): - topsrcdir = relpath(topsrcdir, topobjdir) os.chdir(topobjdir) os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion'])) - if options.files: - files = options.files - headers = [] - if options.headers: - headers = options.headers - if not options.files: - files = [] - # Default to display messages when giving --file or --headers on the - # command line. - log_level = logging.INFO - - if options.files or options.headers or options.verbose: - log_level = logging.DEBUG - + log_level = logging.DEBUG if options.verbose else logging.INFO log_manager.add_terminal_logging(level=log_level) log_manager.enable_unstructured() - if not options.files and not options.headers: - print('Reticulating splines...', file=sys.stderr) - summary = backend.consume(definitions) - - for line in summary.summaries(): - print(line, file=sys.stderr) + print('Reticulating splines...', file=sys.stderr) + summary = backend.consume(definitions) - files = [os.path.join(topobjdir, f) for f in files] - headers = [os.path.join(topobjdir, f) for f in headers] - - for file in files: - env.create_config_file(file) - for header in headers: - env.create_config_header(header) + for line in summary.summaries(): + print(line, file=sys.stderr)
--- a/build/autoconf/config.status.m4 +++ b/build/autoconf/config.status.m4 @@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([ define([AC_DEFINE_UNQUOTED], [cat >> confdefs.pytmp <<EOF (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 ')) EOF ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl ]) dnl Replace AC_OUTPUT to create and call a python config.status -define([AC_OUTPUT], +define([_MOZ_AC_OUTPUT], [dnl Top source directory in Windows format (as opposed to msys format). WIN_TOP_SRC= encoding=utf-8 case "$host_os" in mingw*) WIN_TOP_SRC=`cd $srcdir; pwd -W` encoding=mbcs ;; @@ -116,57 +116,30 @@ dnl Add in the output from the subconfig for ac_subst_arg in $_subconfigure_ac_subst_args; do variable='$'$ac_subst_arg echo " (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS done cat >> $CONFIG_STATUS <<\EOF ] ] -dnl List of files to apply AC_SUBSTs to. This is the list of files given -dnl as an argument to AC_OUTPUT ($1) -files = [ -EOF - -for out in $1; do - echo " '$out'," >> $CONFIG_STATUS -done - -cat >> $CONFIG_STATUS <<\EOF -] - -dnl List of header files to apply AC_DEFINEs to. This is stored in the -dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER. -headers = [ -EOF - -ifdef(<<<AC_LIST_HEADER>>>, <<< -HEADERS="AC_LIST_HEADER" -for header in $HEADERS; do - echo " '$header'," >> $CONFIG_STATUS -done ->>>)dnl - -cat >> $CONFIG_STATUS <<\EOF -] - dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES non_global_defines = [ EOF if test -n "$_NON_GLOBAL_ACDEFINES"; then for var in $_NON_GLOBAL_ACDEFINES; do echo " '$var'," >> $CONFIG_STATUS done fi cat >> $CONFIG_STATUS <<EOF ] -__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers'] +__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs'] dnl Do the actual work if __name__ == '__main__': args = dict([(name, globals()[name]) for name in __all__]) import sys dnl Don't rely on virtualenv here. Standalone js doesn't use it. sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build')) from ConfigStatus import config_status @@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files dnl Execute config.status, unless --no-create was passed to configure. if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then trap '' EXIT exit 1 fi ]) +define([m4_fatal],[ +errprint([$1 +]) +m4exit(1) +]) + +define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()], +[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])] +)]) + +define([AC_CONFIG_HEADER], +[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.]) +]) + AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/build/mobile/b2gautomation.py +++ b/build/mobile/b2gautomation.py @@ -344,30 +344,8 @@ class B2GRemoteAutomation(Automation): def wait(self, timeout=None): # this should never happen raise Exception("'wait' called on B2GInstance") def kill(self): # this should never happen raise Exception("'kill' called on B2GInstance") - -class B2GDesktopAutomation(Automation): - - def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs): - """ build the application command line """ - - cmd = os.path.abspath(app) - args = [] - - if debuggerInfo: - args.extend(debuggerInfo["args"]) - args.append(cmd) - cmd = os.path.abspath(debuggerInfo["path"]) - - if self.IS_MAC: - args.append("-foreground") - - profileDirectory = profileDir + "/" - - args.extend(("-profile", profileDirectory)) - args.extend(extraArgs) - return cmd, args
--- a/build/mobile/robocop/PaintedSurface.java.in +++ b/build/mobile/robocop/PaintedSurface.java.in @@ -1,16 +1,21 @@ #filter substitution /* 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/. */ package @ANDROID_PACKAGE_NAME@; +import android.graphics.Bitmap; +import android.util.Base64; +import android.util.Base64OutputStream; + import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class PaintedSurface { private String mFileName; private int mWidth; @@ -39,38 +44,62 @@ public class PaintedSurface { public final int getWidth() { return mWidth; } public final int getHeight() { return mHeight; } + private int pixelAtIndex(int index) { + int b1 = mPixelBuffer.get(index) & 0xFF; + int b2 = mPixelBuffer.get(index + 1) & 0xFF; + int b3 = mPixelBuffer.get(index + 2) & 0xFF; + int b4 = mPixelBuffer.get(index + 3) & 0xFF; + int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0); + return value; + } + public final int getPixelAt(int x, int y) { if (mPixelBuffer == null) { throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer"); } if (x >= mWidth || x < 0) { throw new RoboCopException("Trying to access PaintedSurface with invalid x value"); } if (y >= mHeight || y < 0) { throw new RoboCopException("Trying to access PaintedSurface with invalid y value"); } // The rows are reversed so row 0 is at the end and we start with the last row. // This is why we do mHeight-y; int index = (x + ((mHeight - y - 1) * mWidth)) * 4; - int b1 = mPixelBuffer.get(index) & 0xFF; - int b2 = mPixelBuffer.get(index + 1) & 0xFF; - int b3 = mPixelBuffer.get(index + 2) & 0xFF; - int b4 = mPixelBuffer.get(index + 3) & 0xFF; - int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0); - return value; + return pixelAtIndex(index); + } + + public final String asDataUri() { + try { + Bitmap bm = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); + for (int y = 0; y < mHeight; y++) { + for (int x = 0; x < mWidth; x++) { + int index = (x + ((mHeight - y - 1) * mWidth)) * 4; + bm.setPixel(x, y, pixelAtIndex(index)); + } + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write("data:image/png;base64,".getBytes()); + Base64OutputStream b64 = new Base64OutputStream(out, Base64.NO_WRAP); + bm.compress(Bitmap.CompressFormat.PNG, 100, b64); + return new String(out.toByteArray()); + } catch (Exception e) { + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); + throw new RoboCopException("Unable to convert surface to a PNG data:uri"); + } } public void close() { try { mPixelFile.close(); } catch (Exception e) { FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, e); }
--- a/config/makefiles/xpidl/Makefile.in +++ b/config/makefiles/xpidl/Makefile.in @@ -1,15 +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/. SUPPRESS_DEFAULT_RULES := 1 STANDALONE_MAKEFILE := 1 -NO_MAKEFILE_RULE := 1 include $(topsrcdir)/config/rules.mk # Building XPIDLs effectively consists of two steps: # # 1) Staging all .idl files to a common directory. # 2) Doing everything with the .idl files. #
--- a/config/rules.mk +++ b/config/rules.mk @@ -597,36 +597,31 @@ ifndef MOZBUILD_BACKEND_CHECKED # Since Makefile is listed as a global dependency, this has the # unfortunate side-effect of invalidating all targets if it is executed. # So e.g. if you are in /dom/bindings and /foo/moz.build changes, # /dom/bindings will get invalidated. The upside is if the current # Makefile/backend.mk is updated as a result of backend regeneration, we # actually pick up the changes. This should reduce the amount of # required clobbers and is thus the lesser evil. -Makefile: $(DEPTH)/backend.RecursiveMakeBackend.built +Makefile: $(DEPTH)/backend.RecursiveMakeBackend @$(TOUCH) $@ -$(DEPTH)/backend.RecursiveMakeBackend.built: +$(DEPTH)/backend.RecursiveMakeBackend: @echo "Build configuration changed. Regenerating backend." @cd $(DEPTH) && $(PYTHON) ./config.status @$(TOUCH) $@ -include $(DEPTH)/backend.RecursiveMakeBackend.built.pp +include $(DEPTH)/backend.RecursiveMakeBackend.pp -default:: $(DEPTH)/backend.RecursiveMakeBackend.built +default:: $(DEPTH)/backend.RecursiveMakeBackend export MOZBUILD_BACKEND_CHECKED=1 endif - -# SUBMAKEFILES: List of Makefiles for next level down. -# This is used to update or create the Makefiles before invoking them. -SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS)) - # The root makefile doesn't want to do a plain export/libs, because # of the tiers and because of libxul. Suppress the default rules in favor # of something else. Makefiles which use this var *must* provide a sensible # default rule before including rules.mk ifndef SUPPRESS_DEFAULT_RULES default all:: $(MAKE) export ifdef MOZ_PSEUDO_DERECURSE @@ -644,35 +639,24 @@ ECHO := true QUIET := -q endif # Do everything from scratch everything:: $(MAKE) clean $(MAKE) all -# Target to only regenerate makefiles -makefiles: $(SUBMAKEFILES) -ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS)) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS))) $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only) endif HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS)) # Dependencies which, if modified, should cause everything to rebuild GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk -ifndef NO_MAKEFILE_RULE -GLOBAL_DEPS += Makefile.in -endif ############################################## OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS) compile:: $(OBJ_TARGETS) include $(topsrcdir)/config/makefiles/target_libs.mk @@ -737,30 +721,30 @@ endif endif # NO_PROFILE_GUIDED_OPTIMIZE ############################################## checkout: $(MAKE) -C $(topsrcdir) -f client.mk checkout -clean clobber realclean clobber_all:: $(SUBMAKEFILES) +clean clobber realclean clobber_all:: -$(RM) $(ALL_TRASH) -$(RM) -r $(ALL_TRASH_DIRS) ifdef TIERS clean clobber realclean clobber_all distclean:: $(foreach dir, \ $(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \ -$(call SUBMAKE,$@,$(dir))) else clean clobber realclean clobber_all distclean:: $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) -distclean:: $(SUBMAKEFILES) +distclean:: $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) endif distclean:: -$(RM) -r $(ALL_TRASH_DIRS) -$(RM) $(ALL_TRASH) \ Makefile .HSancillary \ $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \ @@ -1158,44 +1142,16 @@ endif ############################################################################### # Java rules ############################################################################### ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS)) include $(topsrcdir)/config/makefiles/java-build.mk endif ############################################################################### -# Update Files Managed by Build Backend -############################################################################### - -ifndef NO_MAKEFILE_RULE -Makefile: Makefile.in - @$(PYTHON) $(DEPTH)/config.status -n --file=Makefile - @$(TOUCH) $@ -endif - -ifndef NO_SUBMAKEFILES_RULE -ifdef SUBMAKEFILES -# VPATH does not work on some machines in this case, so add $(srcdir) -$(SUBMAKEFILES): % : $(srcdir)/%.in - $(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@" - @$(TOUCH) "$@" -endif -endif - -ifdef AUTOUPDATE_CONFIGURE -$(topsrcdir)/configure: $(topsrcdir)/configure.in - (cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck -endif - -$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in - $(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk - $(TOUCH) $@ - -############################################################################### # Bunch of things that extend the 'export' rule (in order): ############################################################################### ifneq ($(XPI_NAME),) $(FINAL_TARGET): $(NSINSTALL) -D $@ export:: $(FINAL_TARGET) @@ -1620,34 +1576,34 @@ endif # Used as a dependency to force targets to rebuild FORCE: # Delete target if error occurs when building target .DELETE_ON_ERROR: tags: TAGS -TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h) +TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h) -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h) $(LOOP_OVER_PARALLEL_DIRS) $(LOOP_OVER_DIRS) ifndef INCLUDED_DEBUGMAKE_MK #{ ## Only parse when an echo* or show* target is requested ifneq (,$(call isTargetStem,echo,show)) include $(topsrcdir)/config/makefiles/debugmake.mk endif #} endif #} documentation: @cd $(DEPTH) $(DOXYGEN) $(DEPTH)/config/doxygen.cfg ifdef ENABLE_TESTS -check:: $(SUBMAKEFILES) +check:: $(LOOP_OVER_PARALLEL_DIRS) $(LOOP_OVER_DIRS) $(LOOP_OVER_TOOL_DIRS) endif FREEZE_VARIABLES = \ CSRCS \
--- a/configure.in +++ b/configure.in @@ -3980,17 +3980,17 @@ MOZ_UNIVERSALCHARDET=1 MOZ_URL_CLASSIFIER= MOZ_XUL=1 MOZ_ZIPWRITER=1 NS_PRINTING=1 MOZ_PDF_PRINTING= MOZ_DISABLE_CRYPTOLEGACY= NSS_DISABLE_DBM= NECKO_COOKIES=1 -NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device" +NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device" USE_ARM_KUSER= BUILD_CTYPES=1 MOZ_USE_NATIVE_POPUP_WINDOWS= MOZ_ANDROID_HISTORY= MOZ_WEBSMS_BACKEND= MOZ_ANDROID_BEAM= ACCESSIBILITY=1 MOZ_TIME_MANAGER= @@ -8767,27 +8767,20 @@ HAVE_STATVFS HAVE_STATFS64 HAVE_STATFS HAVE_SYS_STATVFS_H HAVE_SYS_STATFS_H HAVE_SYS_VFS_H HAVE_SYS_MOUNT_H " -# FUTURE? Consider moving all these to moz.build files. -AC_CONFIG_HEADER( -netwerk/necko-config.h -xpcom/xpcom-config.h -xpcom/xpcom-private.h -) - AC_SUBST(STLPORT_LIBS) export WRITE_MOZINFO=1 -AC_OUTPUT([mozilla-config.h]) +AC_OUTPUT() unset WRITE_MOZINFO # Hack around an Apple bug that affects the egrep that comes with OS X 10.7. # "env ARCHPREFERENCE=i386,x86_64 arch egrep" first tries to use the 32-bit # Intel part of the egrep fat binary, even on 64-bit systems, and falls back on # the 64-bit part if it's not a fat binary, as can happen with MacPorts. We # (apparently) only need this hack when egrep's "pattern" is particularly long # (as in the following code) and the first egrep on our $PATH is Apple's. See
--- a/content/events/src/nsDOMKeyboardEvent.cpp +++ b/content/events/src/nsDOMKeyboardEvent.cpp @@ -18,16 +18,17 @@ nsDOMKeyboardEvent::nsDOMKeyboardEvent(m NS_ASSERTION(mEvent->eventStructType == NS_KEY_EVENT, "event type mismatch"); if (aEvent) { mEventIsInternal = false; } else { mEventIsInternal = true; mEvent->time = PR_Now(); + mEvent->AsKeyboardEvent()->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING; } } NS_IMPL_ADDREF_INHERITED(nsDOMKeyboardEvent, nsDOMUIEvent) NS_IMPL_RELEASE_INHERITED(nsDOMKeyboardEvent, nsDOMUIEvent) NS_INTERFACE_MAP_BEGIN(nsDOMKeyboardEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMKeyEvent) @@ -97,19 +98,17 @@ nsDOMKeyboardEvent::GetModifierState(con *aState = GetModifierState(aKey); return NS_OK; } NS_IMETHODIMP nsDOMKeyboardEvent::GetKey(nsAString& aKeyName) { - if (!mEventIsInternal) { - mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName); - } + mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName); return NS_OK; } NS_IMETHODIMP nsDOMKeyboardEvent::GetCharCode(uint32_t* aCharCode) { NS_ENSURE_ARG_POINTER(aCharCode); *aCharCode = CharCode();
--- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -130,17 +130,17 @@ RoundDown(double aDouble) { return (aDouble > 0) ? static_cast<int32_t>(floor(aDouble)) : static_cast<int32_t>(ceil(aDouble)); } static inline bool IsMouseEventReal(WidgetEvent* aEvent) { - NS_ABORT_IF_FALSE(aEvent->IsMouseDerivedEvent(), "Not a mouse event"); + NS_ABORT_IF_FALSE(aEvent->AsMouseEvent(), "Not a mouse event"); // Return true if not synthesized. return aEvent->AsMouseEvent()->reason == WidgetMouseEvent::eReal; } #ifdef DEBUG_DOCSHELL_FOCUS static void PrintDocTree(nsIDocShellTreeItem* aParentItem, int aLevel) {
--- a/content/html/content/public/HTMLMediaElement.h +++ b/content/html/content/public/HTMLMediaElement.h @@ -12,16 +12,17 @@ #include "nsCycleCollectionParticipant.h" #include "nsIObserver.h" #include "mozilla/CORSMode.h" #include "DOMMediaStream.h" #include "AudioChannelCommon.h" #include "DecoderTraits.h" #include "nsIAudioChannelAgent.h" #include "mozilla/Attributes.h" +#include "mozilla/dom/AudioChannelBinding.h" #include "mozilla/dom/TextTrackManager.h" // Define to output information on decoding and painting framerate /* #define DEBUG_FRAME_RATE 1 */ class nsIChannel; class nsIHttpChannel; class nsILoadGroup; @@ -508,22 +509,18 @@ public: uint32_t GetMozFrameBufferLength(ErrorResult& aRv) const; void SetMozFrameBufferLength(uint32_t aValue, ErrorResult& aRv); JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv); double MozFragmentEnd(); - // XPCOM GetMozAudioChannelType() is OK - - void SetMozAudioChannelType(const nsAString& aValue, ErrorResult& aRv) - { - SetHTMLAttr(nsGkAtoms::mozaudiochannel, aValue, aRv); - } + AudioChannel MozAudioChannelType() const; + void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv); TextTrackList* TextTracks() const; already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind, const nsAString& aLabel, const nsAString& aLanguage); void AddTextTrack(TextTrack* aTextTrack) {
--- a/content/html/content/src/HTMLMediaElement.cpp +++ b/content/html/content/src/HTMLMediaElement.cpp @@ -3923,10 +3923,46 @@ HTMLMediaElement::AddTextTrack(TextTrack void HTMLMediaElement::PopulatePendingTextTrackList() { if (mTextTrackManager) { mTextTrackManager->PopulatePendingList(); } } +AudioChannel +HTMLMediaElement::MozAudioChannelType() const +{ + switch (mAudioChannelType) { + case AUDIO_CHANNEL_CONTENT: + return AudioChannel::Content; + + case AUDIO_CHANNEL_NOTIFICATION: + return AudioChannel::Notification; + + case AUDIO_CHANNEL_ALARM: + return AudioChannel::Alarm; + + case AUDIO_CHANNEL_TELEPHONY: + return AudioChannel::Telephony; + + case AUDIO_CHANNEL_RINGER: + return AudioChannel::Ringer; + + case AUDIO_CHANNEL_PUBLICNOTIFICATION: + return AudioChannel::Publicnotification; + + default: + return AudioChannel::Normal; + } +} + +void +HTMLMediaElement::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv) +{ + nsString channel; + channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value, + AudioChannelValues::strings[uint32_t(aValue)].length); + SetHTMLAttr(nsGkAtoms::mozaudiochannel, channel, aRv); +} + } // namespace dom } // namespace mozilla
--- a/content/html/content/test/test_mozaudiochannel.html +++ b/content/html/content/test/test_mozaudiochannel.html @@ -38,16 +38,16 @@ audio2.mozAudioChannelType = "alarm"; ok(audio2.mozAudioChannelType == "alarm", "Default audio2 channel == 'alarm'"); var audio3 = document.getElementById("audio3"); ok(audio3, "Audio Element exists"); ok(audio3.mozAudioChannelType == "content", "Default audio3 channel == 'content'"); try { audio3.mozAudioChannelType = "foo"; } catch(e) {} -ok(audio3.mozAudioChannelType == "normal", "audio3 channel == 'normal'"); +ok(audio3.mozAudioChannelType == "content", "audio3 channel == 'content'"); audio3.mozAudioChannelType = "alarm"; ok(audio3.mozAudioChannelType == "alarm", "audio3 channel == 'alarm'"); </script> </pre> </body> </html>
--- a/content/media/TextTrack.cpp +++ b/content/media/TextTrack.cpp @@ -70,17 +70,19 @@ TextTrack::SetDefaultSettings() mCuePos = 0; mDirty = false; mReadyState = HTMLTrackElement::NONE; } void TextTrack::Update(double aTime) { - mCueList->Update(aTime); + if (mCueList) { + mCueList->Update(aTime); + } } JSObject* TextTrack::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) { return TextTrackBinding::Wrap(aCx, aScope, this); }
--- a/content/media/webaudio/AudioContext.h +++ b/content/media/webaudio/AudioContext.h @@ -2,17 +2,17 @@ /* 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 AudioContext_h_ #define AudioContext_h_ -#include "mozilla/dom/AudioContextBinding.h" +#include "mozilla/dom/AudioChannelBinding.h" #include "EnableWebAudioCheck.h" #include "MediaBufferDecoder.h" #include "mozilla/Attributes.h" #include "mozilla/dom/TypedArray.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsDOMEventTargetHelper.h"
--- a/content/media/webaudio/AudioDestinationNode.h +++ b/content/media/webaudio/AudioDestinationNode.h @@ -2,17 +2,17 @@ /* 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 AudioDestinationNode_h_ #define AudioDestinationNode_h_ -#include "mozilla/dom/AudioContextBinding.h" +#include "mozilla/dom/AudioChannelBinding.h" #include "AudioNode.h" #include "nsIDOMEventListener.h" #include "nsIAudioChannelAgent.h" #include "AudioChannelCommon.h" #include "nsWeakReference.h" namespace mozilla { namespace dom {
--- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -8455,17 +8455,23 @@ if (""", ] methods = [] if self.needToInitIds: methods.append(self.initIdsMethod()) methods.append(self.initMethod()) methods.append(self.initFromJSONMethod()) - methods.append(self.toObjectMethod()) + try: + methods.append(self.toObjectMethod()) + except MethodNotCreatorError: + # If we can't have a ToObject() because one of our members can only + # be returned from [NewObject] methods, then just skip generating + # ToObject(). + pass methods.append(self.traceDictionaryMethod()) if CGDictionary.isDictionaryCopyConstructible(d): disallowCopyConstruction = False # Note: no base constructors because our operator= will # deal with that. ctors.append(ClassConstructor([Argument("const %s&" % selfName, "aOther")],
--- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -245,17 +245,16 @@ ParserResults.pkl: $(globalgen_dependenc .changed-dependency-list @$(TOUCH) $@ GARBAGE += \ webidlyacc.py \ parser.out \ $(wildcard *-example.h) \ $(wildcard *-example.cpp) \ - $(unified_binding_cpp_files) \ .BindingGen \ .all-webidl-file-list \ .generated-events-webidl-files \ .changed-dependency-list \ $(binding_dependency_trackers) \ $(NULL) # Make sure all binding header files are created during the export stage, so we
--- a/dom/bindings/TypedArray.h +++ b/dom/bindings/TypedArray.h @@ -28,17 +28,19 @@ protected: TypedArrayObjectStorage() { } public: inline void TraceSelf(JSTracer* trc) { - JS_CallObjectTracer(trc, &mObj, "TypedArray.mObj"); + if (mObj) { + JS_CallObjectTracer(trc, &mObj, "TypedArray.mObj"); + } } private: TypedArrayObjectStorage(const TypedArrayObjectStorage&) MOZ_DELETE; }; /* * Various typed array classes for argument conversion. We have a base class
--- a/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl +++ b/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl @@ -5,26 +5,26 @@ #include "nsISupports.idl" interface nsIDOMMozCellBroadcastEtwsInfo; /** * MozCellBroadcastMessage encapsulates Cell Broadcast short message service * (CBS) messages. */ -[scriptable, uuid(cb210e8b-ad9c-4052-b70c-02ec0c25d669)] +[scriptable, uuid(6abe65de-6729-41f7-906a-3f3a2dbe30ae)] interface nsIDOMMozCellBroadcastMessage : nsISupports { /** * Indication of the geographical area over which the Message Code is unique, * and the display mode. * * Possible values are: "cell-immediate", "plmn", "location-area" and "cell". */ - readonly attribute DOMString geographicalScope; + readonly attribute DOMString gsmGeographicalScope; /** * The Message Code differentiates between messages from the same source and * type (e.g., with the same Message Identifier). */ readonly attribute unsigned short messageCode; /** @@ -54,16 +54,21 @@ interface nsIDOMMozCellBroadcastMessage * System time stamp at receival. */ readonly attribute jsval timestamp; // jsval is for Date. /** * Additional ETWS-specific info. */ readonly attribute nsIDOMMozCellBroadcastEtwsInfo etws; + + /** + * Service Category. + */ + readonly attribute long cdmaServiceCategory; }; /** * ETWS (Earthquake and Tsunami Warning service) Primary Notification message * specific information. */ [scriptable, uuid(af009d9a-f5e8-4573-a6ee-a85118465bed)] interface nsIDOMMozCellBroadcastEtwsInfo : nsISupports
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js +++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js @@ -97,30 +97,31 @@ function testEtwsMessageAttributes() { // ok(event instanceof MozCellBroadcastEvent, // "event is instanceof " + event.constructor) ok(event, "event is valid"); let message = event.message; ok(message, "event.message is valid"); // Attributes other than `language` and `body` should always be assigned. - ok(message.geographicalScope != null, "message.geographicalScope"); + ok(message.gsmGeographicalScope != null, "message.gsmGeographicalScope"); ok(message.messageCode != null, "message.messageCode"); ok(message.messageId != null, "message.messageId"); ok('language' in message, "message.language"); ok(message.language == null, "message.language"); ok('body' in message, "message.body"); ok(message.body == null, "message.body"); is(message.messageClass, "normal", "message.messageClass"); ok(message.timestamp != null, "message.timestamp"); ok(message.etws != null, "message.etws"); ok(message.etws.warningType != null, "message.etws.warningType"); ok(message.etws.emergencyUserAlert != null, "message.etws.emergencyUserAlert"); ok(message.etws.popup != null, "message.etws.popup"); + ok(message.cdmaServiceCategory != null, "message.cdmaServiceCategory"); window.setTimeout(testReceiving_ETWS_GeographicalScope, 0); }); // Here we use a simple ETWS message for test. let pdu = buildHexStr(0, CB_MESSAGE_SIZE_ETWS * 2); // 6 octets sendCellBroadcastMessage(pdu); } @@ -129,18 +130,18 @@ function testReceiving_ETWS_Geographical log("Test receiving ETWS Primary Notification - Geographical Scope"); function do_test(gs, nextTest) { // Here we use a simple ETWS message for test. let pdu = buildHexStr(((gs & 0x03) << 14), 4) + buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 2) * 2); doTestHelper(pdu, nextTest, function (message) { - is(message.geographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs], - "message.geographicalScope"); + is(message.gsmGeographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs], + "message.gsmGeographicalScope"); }); } repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length), testReceiving_ETWS_MessageCode); } function testReceiving_ETWS_MessageCode() {
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js +++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js @@ -152,29 +152,30 @@ function testGsmMessageAttributes() { // ok(event instanceof MozCellBroadcastEvent, // "event is instanceof " + event.constructor) ok(event, "event is valid"); let message = event.message; ok(message, "event.message is valid"); // Attributes other than `language` and `body` should always be assigned. - ok(message.geographicalScope != null, "message.geographicalScope"); + ok(message.gsmGeographicalScope != null, "message.gsmGeographicalScope"); ok(message.messageCode != null, "message.messageCode"); ok(message.messageId != null, "message.messageId"); ok(message.language != null, "message.language"); ok(message.body != null, "message.body"); ok(message.messageClass != null, "message.messageClass"); ok(message.timestamp != null, "message.timestamp"); ok('etws' in message, "message.etws"); if (message.etws) { ok('warningType' in message.etws, "message.etws.warningType"); ok(message.etws.emergencyUserAlert != null, "message.etws.emergencyUserAlert"); ok(message.etws.popup != null, "message.etws.popup"); } + ok(message.cdmaServiceCategory != null, "message.cdmaServiceCategory"); window.setTimeout(testReceiving_GSM_GeographicalScope, 0); }); // Here we use a simple GSM message for test. let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2); sendCellBroadcastMessage(pdu); } @@ -182,18 +183,18 @@ function testGsmMessageAttributes() { function testReceiving_GSM_GeographicalScope() { log("Test receiving GSM Cell Broadcast - Geographical Scope"); function do_test(gs, nextTest) { let pdu = buildHexStr(((gs & 0x03) << 14), 4) + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 2) * 2); doTestHelper(pdu, nextTest, function (message) { - is(message.geographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs], - "message.geographicalScope"); + is(message.gsmGeographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs], + "message.gsmGeographicalScope"); }); } repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length), testReceiving_GSM_MessageCode); } function testReceiving_GSM_MessageCode() { @@ -435,17 +436,36 @@ function testReceiving_GSM_Multipart() { } doTestHelper(pdus, nextTest, function (message) { is(message.body.length, (numParts * CB_MAX_CONTENT_7BIT), "message.body"); }); } - repeat(do_test, seq(16, 1), cleanUp); + repeat(do_test, seq(16, 1), testReceiving_GSM_ServiceCategory); +} + +function testReceiving_GSM_ServiceCategory() { + log("Test receiving GSM Cell Broadcast - Service Category"); + + cbs.addEventListener("received", function onreceived(event) { + cbs.removeEventListener("received", onreceived); + + let message = event.message; + + // Bug 910091 + // "Service Category" is not defined in GSM. We should always get '0' here. + is(message.cdmaServiceCategory, 0, "message.cdmaServiceCategory"); + + window.setTimeout(cleanUp, 0); + }); + + let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2); + sendCellBroadcastMessage(pdu); } function cleanUp() { if (pendingEmulatorCmdCount > 0) { window.setTimeout(cleanUp, 100); return; }
--- a/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl +++ b/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl @@ -12,17 +12,17 @@ namespace mozilla { namespace dom { class PositionOptions; } } %} [ptr] native NamespacedPositionOptions(mozilla::dom::PositionOptions); -[builtinclass, uuid(1bc7d103-c7ae-4467-881c-21a8dfa17938)] +[builtinclass, uuid(9142ab45-0ab5-418c-9bab-338a6d271d4f)] interface nsIDOMGeoGeolocation : nsISupports { int32_t watchPosition(in nsIDOMGeoPositionCallback callback, in nsIDOMGeoPositionErrorCallback errorCallback, in NamespacedPositionOptions options); void getCurrentPosition(in nsIDOMGeoPositionCallback callback, in nsIDOMGeoPositionErrorCallback errorCallback, in NamespacedPositionOptions options);
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -23,17 +23,17 @@ #include "mozilla/hal_sandbox/PHalChild.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/TestShellChild.h" #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/PCompositorChild.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/Preferences.h" -#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX) +#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) #include "mozilla/Sandbox.h" #endif #include "mozilla/unused.h" #include "nsIConsoleListener.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIMemoryReporter.h" #include "nsIMemoryInfoDumper.h" @@ -548,17 +548,17 @@ ContentChild::AllocPImageBridgeChild(moz bool ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs) { ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ? GeckoChildProcessHost::DefaultChildPrivileges() : aPrivs; // If this fails, we die. SetCurrentProcessPrivileges(privs); -#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX) +#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) // SetCurrentProcessSandbox should be moved close to process initialization // time if/when possible. SetCurrentProcessPrivileges should probably be // moved as well. Right now this is set ONLY if we receive the // RecvSetProcessPrivileges message. See bug 880808. SetCurrentProcessSandbox(); #endif return true; }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -2790,28 +2790,28 @@ void nsPluginInstanceOwner::Paint(gfxCon Renderer renderer(window, this, pluginSize, pluginDirtyRect); Display* dpy = mozilla::DefaultXDisplay(); Screen* screen = DefaultScreenOfDisplay(dpy); Visual* visual = DefaultVisualOfScreen(screen); renderer.Draw(aContext, nsIntSize(window->width, window->height), - rendererFlags, screen, visual, nullptr); + rendererFlags, screen, visual); } nsresult -nsPluginInstanceOwner::Renderer::DrawWithXlib(gfxXlibSurface* xsurface, +nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface, nsIntPoint offset, nsIntRect *clipRects, uint32_t numClipRects) { - Screen *screen = cairo_xlib_surface_get_screen(xsurface->CairoSurface()); + Screen *screen = cairo_xlib_surface_get_screen(xsurface); Colormap colormap; Visual* visual; - if (!xsurface->GetColormapAndVisual(&colormap, &visual)) { + if (!gfxXlibSurface::GetColormapAndVisual(xsurface, &colormap, &visual)) { NS_ERROR("Failed to get visual and colormap"); return NS_ERROR_UNEXPECTED; } nsNPAPIPluginInstance *instance = mInstanceOwner->mInstance; if (!instance) return NS_ERROR_FAILURE; @@ -2845,20 +2845,20 @@ nsPluginInstanceOwner::Renderer::DrawWit } else { clipRect.x = offset.x; clipRect.y = offset.y; clipRect.width = mWindow->width; clipRect.height = mWindow->height; // Don't ask the plugin to draw outside the drawable. // This also ensures that the unsigned clip rectangle offsets won't be -ve. - gfxIntSize surfaceSize = xsurface->GetSize(); clipRect.IntersectRect(clipRect, nsIntRect(0, 0, - surfaceSize.width, surfaceSize.height)); + cairo_xlib_surface_get_width(xsurface), + cairo_xlib_surface_get_height(xsurface))); } NPRect newClipRect; newClipRect.left = clipRect.x; newClipRect.top = clipRect.y; newClipRect.right = clipRect.XMost(); newClipRect.bottom = clipRect.YMost(); if (mWindow->clipRect.left != newClipRect.left || @@ -2901,17 +2901,17 @@ nsPluginInstanceOwner::Renderer::DrawWit return NS_OK; { XEvent pluginEvent = XEvent(); XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose; // set the drawing info exposeEvent.type = GraphicsExpose; exposeEvent.display = DisplayOfScreen(screen); - exposeEvent.drawable = xsurface->XDrawable(); + exposeEvent.drawable = cairo_xlib_surface_get_drawable(xsurface); exposeEvent.x = dirtyRect.x; exposeEvent.y = dirtyRect.y; exposeEvent.width = dirtyRect.width; exposeEvent.height = dirtyRect.height; exposeEvent.count = 0; // information not set: exposeEvent.serial = 0; exposeEvent.send_event = False;
--- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -334,18 +334,19 @@ private: #endif { public: Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner, const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect) : mWindow(aWindow), mInstanceOwner(aInstanceOwner), mPluginSize(aPluginSize), mDirtyRect(aDirtyRect) {} - virtual nsresult DrawWithXlib(gfxXlibSurface* surface, nsIntPoint offset, - nsIntRect* clipRects, uint32_t numClipRects); + virtual nsresult DrawWithXlib(cairo_surface_t* surface, + nsIntPoint offset, + nsIntRect* clipRects, uint32_t numClipRects) MOZ_OVERRIDE; private: NPWindow* mWindow; nsPluginInstanceOwner* mInstanceOwner; const nsIntSize& mPluginSize; const nsIntRect& mDirtyRect; }; #endif
--- a/dom/system/gonk/NetworkManager.js +++ b/dom/system/gonk/NetworkManager.js @@ -239,17 +239,19 @@ NetworkManager.prototype = { // Add extra host route. For example, mms proxy or mmsc. this.setExtraHostRoute(network); // Remove pre-created default route and let setAndConfigureActive() // to set default route only on preferred network this.removeDefaultRoute(network.name); this.setAndConfigureActive(); // Update data connection when Wifi connected/disconnected if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) { - this.mRIL.getRadioInterface(0).updateRILNetworkInterface(); + for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) { + this.mRIL.getRadioInterface(i).updateRILNetworkInterface(); + } } this.onConnectionChanged(network); // Probing the public network accessibility after routing table is ready CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active); break; case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED: @@ -267,17 +269,19 @@ NetworkManager.prototype = { } else if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) { this.removeDefaultRoute(network.name); } // Abort ongoing captive portal detection on the wifi interface CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network); this.setAndConfigureActive(); // Update data connection when Wifi connected/disconnected if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) { - this.mRIL.getRadioInterface(0).updateRILNetworkInterface(); + for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) { + this.mRIL.getRadioInterface(i).updateRILNetworkInterface(); + } } break; } break; case TOPIC_INTERFACE_REGISTERED: let regNetwork = subject.QueryInterface(Ci.nsINetworkInterface); // Add extra host route. For example, mms proxy or mmsc. this.setExtraHostRoute(regNetwork);
--- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -313,49 +313,52 @@ MobileCFInfo.prototype = { action: -1, reason: -1, number: null, timeSeconds: 0, serviceClass: -1 }; function CellBroadcastMessage(pdu) { - this.geographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope]; + this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope]; this.messageCode = pdu.messageCode; this.messageId = pdu.messageId; this.language = pdu.language; this.body = pdu.fullBody; this.messageClass = pdu.messageClass; this.timestamp = new Date(pdu.timestamp); if (pdu.etws != null) { this.etws = new CellBroadcastEtwsInfo(pdu.etws); } + + this.cdmaServiceCategory = pdu.serviceCategory; } CellBroadcastMessage.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastMessage]), classID: CELLBROADCASTMESSAGE_CID, classInfo: XPCOMUtils.generateCI({ classID: CELLBROADCASTMESSAGE_CID, classDescription: "CellBroadcastMessage", flags: Ci.nsIClassInfo.DOM_OBJECT, interfaces: [Ci.nsIDOMMozCellBroadcastMessage] }), // nsIDOMMozCellBroadcastMessage - geographicalScope: null, + gsmGeographicalScope: null, messageCode: null, messageId: null, language: null, body: null, messageClass: null, timestamp: null, - etws: null + etws: null, + cdmaServiceCategory: null }; function CellBroadcastEtwsInfo(etwsInfo) { if (etwsInfo.warningType != null) { this.warningType = RIL.CB_ETWS_WARNING_TYPE_NAMES[etwsInfo.warningType]; } this.emergencyUserAlert = etwsInfo.emergencyUserAlert; this.popup = etwsInfo.popup;
--- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -1055,16 +1055,17 @@ RadioInterface.prototype = { this.clientId, message); break; case "sms-received": let ackOk = this.handleSmsReceived(message); if (ackOk) { this.workerMessenger.send("ackSMS", { result: RIL.PDU_FCS_OK }); } return; + case "broadcastsms-received": case "cellbroadcast-received": message.timestamp = Date.now(); gMessageManager.sendCellBroadcastMessage("RIL:CellBroadcastReceived", this.clientId, message); break; case "datacallstatechange": this.handleDataCallState(message); break;
--- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -2758,18 +2758,25 @@ this.PDU_CDMA_MSG_CODING_GSM_DCS = 0x0A; this.PDU_CDMA_MSG_TYPE_DELIVER = 0x01; // Receive this.PDU_CDMA_MSG_TYPE_SUBMIT = 0x02; // Send // SMS User Data Subparameters, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5-1 this.PDU_CDMA_MSG_USERDATA_MSG_ID = 0x00; // Message Identifier this.PDU_CDMA_MSG_USERDATA_BODY = 0x01; // User Data Body this.PDU_CDMA_MSG_USERDATA_TIMESTAMP = 0x03; // Message Center Time Stamp this.PDU_CDMA_REPLY_OPTION = 0x0A; // Reply Option +this.PDU_CDMA_LANGUAGE_INDICATOR = 0x0D; // Language Indicator this.PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER = 0x0E; // Callback Number +// CDMA Language Indicator: Language groups +// see 3GPP2 C.R1001-F table 9.2-1 +this.CB_CDMA_LANG_GROUP = [ + null, "en", "fr", "es", "ja", "ko", "zh", "he" +]; + // IS-91 Message Type, as defined in TIA/EIA/IS-91-A, Table 9 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS = 0x82; this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL = 0x83; this.PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI = 0x84; this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS = 0x85; // CDMA roaming preference mode this.CDMA_ROAMING_PREFERENCE_HOME = 0;
--- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -4215,17 +4215,23 @@ let RIL = { if (message) { message.result = PDU_FCS_OK; if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) { // `MS shall ensure that the message has been to the SMS data field in // the (U)SIM before sending an ACK to the SC.` ~ 3GPP 23.038 clause 4 message.result = PDU_FCS_RESERVED; } - message.rilMessageType = "sms-received"; + + if (message.messageType == PDU_CDMA_MSG_TYPE_BROADCAST) { + message.rilMessageType = "broadcastsms-received"; + } else { + message.rilMessageType = "sms-received"; + } + this.sendChromeMessage(message); // We will acknowledge receipt of the SMS after we try to store it // in the database. return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK; } return PDU_FCS_OK; @@ -8805,35 +8811,38 @@ let CdmaPDUHelper = { message.sender += String.fromCharCode(addrDigit); } // User Data this.decodeUserData(message); // Transform message to GSM msg let msg = { - SMSC: "", - mti: 0, - udhi: 0, - sender: message.sender, - recipient: null, - pid: PDU_PID_DEFAULT, - epid: PDU_PID_DEFAULT, - dcs: 0, - mwi: null, //message[PDU_CDMA_MSG_USERDATA_BODY].header ? message[PDU_CDMA_MSG_USERDATA_BODY].header.mwi : null, - replace: false, - header: message[PDU_CDMA_MSG_USERDATA_BODY].header, - body: message[PDU_CDMA_MSG_USERDATA_BODY].body, - data: null, - timestamp: message[PDU_CDMA_MSG_USERDATA_TIMESTAMP], - status: null, - scts: null, - dt: null, - encoding: message[PDU_CDMA_MSG_USERDATA_BODY].encoding, - messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL] + SMSC: "", + mti: 0, + udhi: 0, + sender: message.sender, + recipient: null, + pid: PDU_PID_DEFAULT, + epid: PDU_PID_DEFAULT, + dcs: 0, + mwi: null, //message[PDU_CDMA_MSG_USERDATA_BODY].header ? message[PDU_CDMA_MSG_USERDATA_BODY].header.mwi : null, + replace: false, + header: message[PDU_CDMA_MSG_USERDATA_BODY].header, + body: message[PDU_CDMA_MSG_USERDATA_BODY].body, + data: null, + timestamp: message[PDU_CDMA_MSG_USERDATA_TIMESTAMP], + language: message[PDU_CDMA_LANGUAGE_INDICATOR], + status: null, + scts: null, + dt: null, + encoding: message[PDU_CDMA_MSG_USERDATA_BODY].encoding, + messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL], + messageType: message.messageType, + serviceCategory: message.service }; return msg; }, /** * Helper for processing received SMS parcel data. @@ -8925,16 +8934,19 @@ let CdmaPDUHelper = { message[id] = this.decodeUserDataMsg(message[PDU_CDMA_MSG_USERDATA_MSG_ID].userHeader); break; case PDU_CDMA_MSG_USERDATA_TIMESTAMP: message[id] = this.decodeUserDataTimestamp(); break; case PDU_CDMA_REPLY_OPTION: message[id] = this.decodeUserDataReplyAction(); break; + case PDU_CDMA_LANGUAGE_INDICATOR: + message[id] = this.decodeLanguageIndicator(); + break; case PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER: message[id] = this.decodeUserDataCallbackNumber(); break; } userDataLength -= (length + 2); userDataBuffer = []; } @@ -9306,16 +9318,27 @@ let CdmaPDUHelper = { readAck: (replyAction & 0x2) ? true : false, report: (replyAction & 0x1) ? true : false }; return result; }, /** + * User data subparameter decoder : Language Indicator + * + * @see 3GGP2 C.S0015-B 2.0, 4.5.14 Language Indicator + */ + decodeLanguageIndicator: function cdma_decodeLanguageIndicator() { + let language = BitBufferHelper.readBits(8); + let result = CB_CDMA_LANG_GROUP[language]; + return result; + }, + + /** * User data subparameter decoder : Call-Back Number * * @see 3GGP2 C.S0015-B 2.0, 4.5.15 Call-Back Number */ decodeUserDataCallbackNumber: function cdma_decodeUserDataCallbackNumber() { let digitMode = BitBufferHelper.readBits(1); if (digitMode) { let numberType = BitBufferHelper.readBits(3),
new file mode 100644 --- /dev/null +++ b/dom/webidl/AppInfo.webidl @@ -0,0 +1,12 @@ +/* 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 dictionnary holds the parameters supporting the app:// protocol. + */ +dictionary AppInfo +{ + DOMString path = ""; + boolean isCoreApp = false; +};
new file mode 100644 --- /dev/null +++ b/dom/webidl/AudioChannel.webidl @@ -0,0 +1,49 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +// AudioChannels are used by: +// * HTMLMediaElement +// * AudioContext (WebAudio) +// When used, it has to throw an exception if the app tries to change the audio +// channel type without the permission (manifest file for B2G apps). +// The supported values are: +// * normal (default value) +// Automatically paused if "notification" or higher priority channel +// is played +// Use case: normal applications +// * content +// Automatically paused if "notification" or higher priority channel +// is played. Also paused if another app starts using "content" +// channel. Using this channel never affects applications using +// the "normal" channel. +// Use case: video/audio players +// * notification +// Automatically paused if "alarm" or higher priority channel is played. +// Use case: New email, incoming SMS +// * alarm +// Automatically paused if "telephony" or higher priority channel is +// played. +// User case: Alarm clock, calendar alarms +// * telephony +// Automatically paused if "ringer" or higher priority +// channel is played. +// Use case: dialer, voip +// * ringer +// Automatically paused if "publicnotification" or higher priority +// channel is played. +// Use case: dialer, voip +// * publicnotification +// Always plays in speaker, even when headphones are plugged in. +// Use case: Camera shutter sound. +enum AudioChannel { + "normal", + "content", + "notification", + "alarm", + "telephony", + "ringer", + "publicnotification", +};
--- a/dom/webidl/AudioContext.webidl +++ b/dom/webidl/AudioContext.webidl @@ -93,24 +93,14 @@ partial interface AudioContext { // Same as createScriptProcessor() [NewObject, Throws, Pref="media.webaudio.legacy.AudioContext"] ScriptProcessorNode createJavaScriptNode(optional unsigned long bufferSize = 0, optional unsigned long numberOfInputChannels = 2, optional unsigned long numberOfOutputChannels = 2); }; -enum AudioChannel { - "normal", - "content", - "notification", - "alarm", - "telephony", - "ringer", - "publicnotification", -}; - // Mozilla extensions partial interface AudioContext { - // Read HTMLMediaElement.webidl for more information about this attribute. + // Read AudioChannel.webidl for more information about this attribute. [Pref="media.useAudioChannelService", SetterThrows] attribute AudioChannel mozAudioChannelType; };
--- a/dom/webidl/DummyBinding.webidl +++ b/dom/webidl/DummyBinding.webidl @@ -22,13 +22,14 @@ interface DummyInterface : EventTarget { void MmsParameters(optional MmsParameters arg); void MmsAttachment(optional MmsAttachment arg); void AsyncScrollEventDetail(optional AsyncScrollEventDetail arg); void OpenWindowEventDetail(optional OpenWindowEventDetail arg); void DOMWindowResizeEventDetail(optional DOMWindowResizeEventDetail arg); void WifiOptions(optional WifiCommandOptions arg1, optional WifiResultOptions arg2); void AppNotificationServiceOptions(optional AppNotificationServiceOptions arg); + void AppInfo(optional AppInfo arg1); }; interface DummyInterfaceWorkers { BlobPropertyBag blobBag(); };
--- a/dom/webidl/HTMLMediaElement.webidl +++ b/dom/webidl/HTMLMediaElement.webidl @@ -128,47 +128,17 @@ partial interface HTMLMediaElement { object? mozGetMetadata(); // Mozilla extension: provides access to the fragment end time if // the media element has a fragment URI for the currentSrc, otherwise // it is equal to the media duration. readonly attribute double mozFragmentEnd; // Mozilla extension: an audio channel type for media elements. - // An exception is thrown if the app tries to change the audio channel type - // without the permission (manifest file for B2G apps). - // The supported values are: - // * normal (default value) - // Automatically paused if "notification" or higher priority channel - // is played - // Use case: normal applications - // * content - // Automatically paused if "notification" or higher priority channel - // is played. Also paused if another app starts using "content" - // channel. Using this channel never affects applications using - // the "normal" channel. - // Use case: video/audio players - // * notification - // Automatically paused if "alarm" or higher priority channel is played. - // Use case: New email, incoming SMS - // * alarm - // Automatically paused if "telephony" or higher priority channel is - // played. - // User case: Alarm clock, calendar alarms - // * telephony - // Automatically paused if "ringer" or higher priority - // channel is played. - // Use case: dialer, voip - // * ringer - // Automatically paused if "publicnotification" or higher priority - // channel is played. - // Use case: dialer, voip - // * publicnotification - // Always plays in speaker, even when headphones are plugged in. - // Use case: Camera shutter sound. + // Read AudioChannel.webidl for more information about this attribute. [SetterThrows] - attribute DOMString mozAudioChannelType; + attribute AudioChannel mozAudioChannelType; // In addition the media element has this new events: // * onmozinterruptbegin - called when the media element is interrupted // because of the audiochannel manager. // * onmozinterruptend - called when the interruption is concluded };
--- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -15,22 +15,24 @@ PREPROCESSED_WEBIDL_FILES = [ 'Navigator.webidl', 'Window.webidl', ] WEBIDL_FILES = [ 'AbstractWorker.webidl', 'AnalyserNode.webidl', 'AnimationEvent.webidl', + 'AppInfo.webidl', 'AppNotificationServiceOptions.webidl', 'ArchiveReader.webidl', 'ArchiveRequest.webidl', 'Attr.webidl', 'AudioBuffer.webidl', 'AudioBufferSourceNode.webidl', + 'AudioChannel.webidl', 'AudioContext.webidl', 'AudioDestinationNode.webidl', 'AudioListener.webidl', 'AudioNode.webidl', 'AudioParam.webidl', 'AudioProcessingEvent.webidl', 'AudioStreamTrack.webidl', 'BarProp.webidl',
--- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -932,16 +932,20 @@ public: class GFX2D_API Factory { public: static bool HasSSE2(); static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize); + static TemporaryRef<SourceSurface> + CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, + SurfaceFormat aFormat); + static TemporaryRef<DrawTarget> CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat); static TemporaryRef<DrawTarget> CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT); static TemporaryRef<DrawTarget> CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
--- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -1056,16 +1056,30 @@ DrawTargetCairo::CreateSourceSurfaceFrom new SourceSurfaceCairo(surf, size, aSurface.mFormat); return source; } } return nullptr; } +TemporaryRef<SourceSurface> +DrawTargetCairo::CreateSourceSurfaceForCairoSurface(cairo_surface_t *aSurface, + SurfaceFormat aFormat) +{ + IntSize size; + if (GetCairoSurfaceSize(aSurface, size)) { + RefPtr<SourceSurfaceCairo> source = + new SourceSurfaceCairo(aSurface, size, aFormat); + return source; + } + + return nullptr; +} + TemporaryRef<DrawTarget> DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext), GfxFormatToCairoContent(aFormat), aSize.width, aSize.height); if (!cairo_surface_status(similar)) {
--- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -152,16 +152,20 @@ public: // Call to set up aContext for drawing (with the current transform, etc). // Pass the path you're going to be using if you have one. // Implicitly calls WillChange(aPath). void PrepareForDrawing(cairo_t* aContext, const Path* aPath = nullptr); static cairo_surface_t *GetDummySurface(); + static TemporaryRef<SourceSurface> + CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, + SurfaceFormat aFormat); + private: // methods // Init cairo surface without doing a cairo_surface_reference() call. bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize); enum DrawPatternType { DRAW_FILL, DRAW_STROKE }; void DrawPattern(const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aOptions,
--- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -549,16 +549,28 @@ Factory::CreateDrawTargetForCairoSurface if (mRecorder && retVal) { RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal); return recordDT; } #endif return retVal; } +TemporaryRef<SourceSurface> +Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, + SurfaceFormat aFormat) +{ + RefPtr<SourceSurface> retVal; + +#ifdef USE_CAIRO + retVal = DrawTargetCairo::CreateSourceSurfaceForCairoSurface(aSurface, aFormat); +#endif + return retVal; +} + #ifdef XP_MACOSX TemporaryRef<DrawTarget> Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize) { RefPtr<DrawTarget> retVal; RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
--- a/gfx/layers/ipc/Axis.cpp +++ b/gfx/layers/ipc/Axis.cpp @@ -58,26 +58,26 @@ static float gAccelerationMultiplier = 1 */ static float gFlingStoppedThreshold = 0.01f; /** * Maximum size of velocity queue. The queue contains last N velocity records. * On touch end we calculate the average velocity in order to compensate * touch/mouse drivers misbehaviour. */ -static int gMaxVelocityQueueSize = 5; +static uint32_t gMaxVelocityQueueSize = 5; static void ReadAxisPrefs() { Preferences::AddFloatVarCache(&gMaxEventAcceleration, "apz.max_event_acceleration", gMaxEventAcceleration); Preferences::AddFloatVarCache(&gFlingFriction, "apz.fling_friction", gFlingFriction); Preferences::AddFloatVarCache(&gVelocityThreshold, "apz.velocity_threshold", gVelocityThreshold); Preferences::AddFloatVarCache(&gAccelerationMultiplier, "apz.acceleration_multiplier", gAccelerationMultiplier); Preferences::AddFloatVarCache(&gFlingStoppedThreshold, "apz.fling_stopped_threshold", gFlingStoppedThreshold); - Preferences::AddIntVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize); + Preferences::AddUintVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize); } class ReadAxisPref MOZ_FINAL : public nsRunnable { public: NS_IMETHOD Run() { ReadAxisPrefs(); return NS_OK;
--- a/gfx/thebes/gfxAlphaRecovery.cpp +++ b/gfx/thebes/gfxAlphaRecovery.cpp @@ -7,86 +7,47 @@ #include "gfxImageSurface.h" #define MOZILLA_SSE_INCLUDE_HEADER_FOR_SSE2 #include "mozilla/SSE.h" /* static */ bool gfxAlphaRecovery::RecoverAlpha(gfxImageSurface* blackSurf, - const gfxImageSurface* whiteSurf, - Analysis* analysis) + const gfxImageSurface* whiteSurf) { gfxIntSize size = blackSurf->GetSize(); if (size != whiteSurf->GetSize() || (blackSurf->Format() != gfxImageFormatARGB32 && blackSurf->Format() != gfxImageFormatRGB24) || (whiteSurf->Format() != gfxImageFormatARGB32 && whiteSurf->Format() != gfxImageFormatRGB24)) return false; #ifdef MOZILLA_MAY_SUPPORT_SSE2 - if (!analysis && mozilla::supports_sse2() && + if (mozilla::supports_sse2() && RecoverAlphaSSE2(blackSurf, whiteSurf)) { return true; } #endif blackSurf->Flush(); whiteSurf->Flush(); unsigned char* blackData = blackSurf->Data(); unsigned char* whiteData = whiteSurf->Data(); - /* Get the alpha value of 'first' */ - uint32_t first; - if (size.width == 0 || size.height == 0) { - first = 0; - } else { - if (!blackData || !whiteData) - return false; - - first = RecoverPixel(*reinterpret_cast<uint32_t*>(blackData), - *reinterpret_cast<uint32_t*>(whiteData)); - } - - uint32_t deltas = 0; for (int32_t i = 0; i < size.height; ++i) { uint32_t* blackPixel = reinterpret_cast<uint32_t*>(blackData); const uint32_t* whitePixel = reinterpret_cast<uint32_t*>(whiteData); for (int32_t j = 0; j < size.width; ++j) { uint32_t recovered = RecoverPixel(blackPixel[j], whitePixel[j]); blackPixel[j] = recovered; - deltas |= (first ^ recovered); } blackData += blackSurf->Stride(); whiteData += whiteSurf->Stride(); } blackSurf->MarkDirty(); - - if (analysis) { - analysis->uniformAlpha = (deltas >> 24) == 0; - analysis->uniformColor = false; - if (analysis->uniformAlpha) { - double d_first_alpha = first >> 24; - analysis->alpha = d_first_alpha/255.0; - /* we only set uniformColor when the alpha is already uniform. - it's only useful in that case ... and if the alpha was nonuniform - then computing whether the color is uniform would require unpremultiplying - every pixel */ - analysis->uniformColor = deltas == 0; - if (analysis->uniformColor) { - if (d_first_alpha == 0.0) { - /* can't unpremultiply, this is OK */ - analysis->r = analysis->g = analysis->b = 0.0; - } else { - analysis->r = (first & 0xFF)/d_first_alpha; - analysis->g = ((first >> 8) & 0xFF)/d_first_alpha; - analysis->b = ((first >> 16) & 0xFF)/d_first_alpha; - } - } - } - } return true; }
--- a/gfx/thebes/gfxAlphaRecovery.h +++ b/gfx/thebes/gfxAlphaRecovery.h @@ -10,23 +10,16 @@ #include "gfxTypes.h" #include "nsRect.h" struct nsIntRect; class gfxImageSurface; class gfxAlphaRecovery { public: - struct Analysis { - bool uniformColor; - bool uniformAlpha; - gfxFloat alpha; - gfxFloat r, g, b; - }; - /** * Some SIMD fast-paths only can be taken if the relative * byte-alignment of images' pointers and strides meets certain * criteria. Aligning image pointers and strides by * |GoodAlignmentLog2()| below will ensure that fast-paths aren't * skipped because of misalignment. Fast-paths may still be taken * even if GoodAlignmentLog2() is not met, in some conditions. */ @@ -34,18 +27,17 @@ public: /* Given two surfaces of equal size with the same rendering, one onto a * black background and the other onto white, recovers alpha values from * the difference and sets the alpha values on the black surface. * The surfaces must have format RGB24 or ARGB32. * Returns true on success. */ static bool RecoverAlpha (gfxImageSurface *blackSurface, - const gfxImageSurface *whiteSurface, - Analysis *analysis = nullptr); + const gfxImageSurface *whiteSurface); #ifdef MOZILLA_MAY_SUPPORT_SSE2 /* This does the same as the previous function, but uses SSE2 * optimizations. Usually this should not be called directly. Be sure to * check mozilla::supports_sse2() before calling this function. */ static bool RecoverAlphaSSE2 (gfxImageSurface *blackSurface, const gfxImageSurface *whiteSurface);
--- a/gfx/thebes/gfxGdkNativeRenderer.cpp +++ b/gfx/thebes/gfxGdkNativeRenderer.cpp @@ -9,28 +9,29 @@ #ifdef MOZ_X11 #include <gdk/gdkx.h> #include "cairo-xlib.h" #include "gfxXlibSurface.h" #if (MOZ_WIDGET_GTK == 2) nsresult -gfxGdkNativeRenderer::DrawWithXlib(gfxXlibSurface* surface, +gfxGdkNativeRenderer::DrawWithXlib(cairo_surface_t* surface, nsIntPoint offset, nsIntRect* clipRects, uint32_t numClipRects) { GdkDrawable *drawable = gfxPlatformGtk::GetGdkDrawable(surface); if (!drawable) { - gfxIntSize size = surface->GetSize(); - int depth = cairo_xlib_surface_get_depth(surface->CairoSurface()); + int depth = cairo_xlib_surface_get_depth(surface); GdkScreen* screen = gdk_colormap_get_screen(mColormap); drawable = - gdk_pixmap_foreign_new_for_screen(screen, surface->XDrawable(), - size.width, size.height, depth); + gdk_pixmap_foreign_new_for_screen(screen, cairo_xlib_surface_get_drawable(surface), + cairo_xlib_surface_get_width(surface), + cairo_xlib_surface_get_height(surface), + depth); if (!drawable) return NS_ERROR_FAILURE; gdk_drawable_set_colormap(drawable, mColormap); gfxPlatformGtk::SetGdkDrawable(surface, drawable); g_object_unref(drawable); // The drawable now belongs to |surface|. } @@ -53,16 +54,16 @@ gfxGdkNativeRenderer::Draw(gfxContext* c { mColormap = colormap; Visual* visual = gdk_x11_visual_get_xvisual(gdk_colormap_get_visual(colormap)); Screen* screen = gdk_x11_screen_get_xscreen(gdk_colormap_get_screen(colormap)); - gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual, nullptr); + gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual); } #else // TODO GTK3 #endif #endif
--- a/gfx/thebes/gfxGdkNativeRenderer.h +++ b/gfx/thebes/gfxGdkNativeRenderer.h @@ -71,19 +71,19 @@ public: #if (MOZ_WIDGET_GTK == 2) void Draw(gfxContext* ctx, nsIntSize size, uint32_t flags, GdkColormap* colormap); #endif private: #ifdef MOZ_X11 // for gfxXlibNativeRenderer: - virtual nsresult DrawWithXlib(gfxXlibSurface* surface, + virtual nsresult DrawWithXlib(cairo_surface_t* surface, nsIntPoint offset, - nsIntRect* clipRects, uint32_t numClipRects); + nsIntRect* clipRects, uint32_t numClipRects) MOZ_OVERRIDE; #if (MOZ_WIDGET_GTK == 2) GdkColormap *mColormap; #endif #endif }; #endif /*GFXGDKNATIVERENDER_H_*/
--- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -859,17 +859,19 @@ gfxPlatform::InitializeSkiaCaches() } already_AddRefed<gfxASurface> gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget) { if (aTarget->GetType() == BACKEND_CAIRO) { cairo_surface_t* csurf = static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE)); - return gfxASurface::Wrap(csurf); + if (csurf) { + return gfxASurface::Wrap(csurf); + } } // The semantics of this part of the function are sort of weird. If we // don't have direct support for the backend, we snapshot the first time // and then return the snapshotted surface for the lifetime of the draw // target. Sometimes it seems like this works out, but it seems like it // might result in no updates ever. RefPtr<SourceSurface> source = aTarget->Snapshot();
--- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -717,51 +717,49 @@ void gfxPlatformGtk::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList) { gPrefFonts->Put(aKey, aFontEntryList); } #endif #if (MOZ_WIDGET_GTK == 2) void -gfxPlatformGtk::SetGdkDrawable(gfxASurface *target, +gfxPlatformGtk::SetGdkDrawable(cairo_surface_t *target, GdkDrawable *drawable) { - if (target->CairoStatus()) + if (cairo_surface_status(target)) return; g_object_ref(drawable); - cairo_surface_set_user_data (target->CairoSurface(), + cairo_surface_set_user_data (target, &cairo_gdk_drawable_key, drawable, g_object_unref); } GdkDrawable * -gfxPlatformGtk::GetGdkDrawable(gfxASurface *target) +gfxPlatformGtk::GetGdkDrawable(cairo_surface_t *target) { - if (target->CairoStatus()) + if (cairo_surface_status(target)) return nullptr; GdkDrawable *result; - result = (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(), + result = (GdkDrawable*) cairo_surface_get_user_data (target, &cairo_gdk_drawable_key); if (result) return result; #ifdef MOZ_X11 - if (target->GetType() != gfxSurfaceTypeXlib) + if (cairo_surface_get_type(target) != CAIRO_SURFACE_TYPE_XLIB) return nullptr; - gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(target); - // try looking it up in gdk's table - result = (GdkDrawable*) gdk_xid_table_lookup(xs->XDrawable()); + result = (GdkDrawable*) gdk_xid_table_lookup(cairo_xlib_surface_get_drawable(target)); if (result) { SetGdkDrawable(target, result); return result; } #endif return nullptr; }
--- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -86,19 +86,19 @@ public: void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList); #endif #ifndef MOZ_PANGO FT_Library GetFTLibrary(); #endif #if (MOZ_WIDGET_GTK == 2) - static void SetGdkDrawable(gfxASurface *target, + static void SetGdkDrawable(cairo_surface_t *target, GdkDrawable *drawable); - static GdkDrawable *GetGdkDrawable(gfxASurface *target); + static GdkDrawable *GetGdkDrawable(cairo_surface_t *target); #endif static int32_t GetDPI(); bool UseXRender() { #if defined(MOZ_X11) if (GetContentBackend() != mozilla::gfx::BACKEND_NONE && GetContentBackend() != mozilla::gfx::BACKEND_CAIRO)
--- a/gfx/thebes/gfxQtNativeRenderer.cpp +++ b/gfx/thebes/gfxQtNativeRenderer.cpp @@ -4,18 +4,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gfxQtNativeRenderer.h" #include "gfxContext.h" #include "gfxXlibSurface.h" nsresult gfxQtNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* output) + uint32_t flags, Screen* screen, Visual* visual) { Display *dpy = DisplayOfScreen(screen); bool isOpaque = (flags & DRAW_IS_OPAQUE) ? true : false; int screenNumber = screen - ScreenOfDisplay(dpy, 0); if (!isOpaque) { int depth = 32; XVisualInfo vinfo;
--- a/gfx/thebes/gfxQtNativeRenderer.h +++ b/gfx/thebes/gfxQtNativeRenderer.h @@ -49,31 +49,23 @@ public: // visual passed in must be the default visual for dpy's default screen DRAW_SUPPORTS_ALTERNATE_VISUAL = 0x10, // If set, then the Screen 'screen' in the callback can be different // from the default Screen of the display passed to 'Draw' and can be // on a different display. DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20 }; - struct DrawOutput { - nsRefPtr<gfxASurface> mSurface; - bool mUniformAlpha; - bool mUniformColor; - gfxRGBA mColor; - }; - /** * @param flags see above * @param size Draw()'s drawing is guaranteed to be restricted to * the rectangle (offset.x,offset.y,size.width,size.height) * @param dpy a display to use for the drawing if ctx doesn't have one * @param resultSurface if non-null, we will try to capture a copy of the * rendered image into a surface similar to the surface of ctx; if * successful, a pointer to the new gfxASurface is stored in *resultSurface, * otherwise *resultSurface is set to nullptr. */ nsresult Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* output); + uint32_t flags, Screen* screen, Visual* visual); }; #endif /*GFXQTNATIVERENDER_H_*/
--- a/gfx/thebes/gfxXlibNativeRenderer.cpp +++ b/gfx/thebes/gfxXlibNativeRenderer.cpp @@ -8,16 +8,17 @@ #include "gfxXlibSurface.h" #include "gfxImageSurface.h" #include "gfxContext.h" #include "gfxPlatform.h" #include "gfxAlphaRecovery.h" #include "cairo-xlib.h" #include "cairo-xlib-xrender.h" #include "mozilla/gfx/BorrowedContext.h" +#include "gfx2DGlue.h" using namespace mozilla; using namespace mozilla::gfx; #if 0 #include <stdio.h> #define NATIVE_DRAWING_NOTE(m) fprintf(stderr, m) #else @@ -250,18 +251,17 @@ gfxXlibNativeRenderer::DrawCairo(cairo_t NATIVE_DRAWING_NOTE("FALLBACK: unsupported Visual"); return false; } } /* we're good to go! */ NATIVE_DRAWING_NOTE("TAKING FAST PATH\n"); cairo_surface_flush (target); - nsRefPtr<gfxASurface> surface = gfxASurface::Wrap(target); - nsresult rv = DrawWithXlib(static_cast<gfxXlibSurface*>(surface.get()), + nsresult rv = DrawWithXlib(target, offset, rectangles, needs_clip ? rect_count : 0); if (NS_SUCCEEDED(rv)) { cairo_surface_mark_dirty (target); return true; } return false; } @@ -304,74 +304,72 @@ FormatConversionIsExact(Screen *screen, // The 3 non-direct strategies described above. // The surface format and strategy are inter-dependent. enum DrawingMethod { eSimple, eCopyBackground, eAlphaExtraction }; -static already_AddRefed<gfxXlibSurface> -CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, +static cairo_surface_t* +CreateTempXlibSurface (cairo_surface_t* cairoTarget, + DrawTarget* drawTarget, + nsIntSize size, bool canDrawOverBackground, uint32_t flags, Screen *screen, Visual *visual, DrawingMethod *method) { + NS_ASSERTION(cairoTarget || drawTarget, "Must have some type"); + bool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0; bool supportsAlternateVisual = (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0; bool supportsAlternateScreen = supportsAlternateVisual && (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN); - cairo_surface_t *target = destination->CairoSurface(); - cairo_surface_type_t target_type = cairo_surface_get_type (target); - cairo_content_t target_content = cairo_surface_get_content (target); + cairo_surface_type_t cairoTargetType = + cairoTarget ? cairo_surface_get_type (cairoTarget) : (cairo_surface_type_t)0xFF; - Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ? - cairo_xlib_surface_get_screen (target) : screen; + Screen *target_screen = cairoTargetType == CAIRO_SURFACE_TYPE_XLIB ? + cairo_xlib_surface_get_screen (cairoTarget) : screen; // When the background has an alpha channel, we need to draw with an alpha // channel anyway, so there is no need to copy the background. If // doCopyBackground is set here, we'll also need to check below that the // background can copied without any loss in format conversions. bool doCopyBackground = !drawIsOpaque && canDrawOverBackground && - target_content == CAIRO_CONTENT_COLOR; + cairoTarget && cairo_surface_get_content (cairoTarget) == CAIRO_CONTENT_COLOR; if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) { // Prefer a visual on the target screen. // (If !drawIsOpaque, we'll need doCopyBackground or an alpha channel.) visual = DefaultVisualOfScreen(target_screen); screen = target_screen; } else if (doCopyBackground || (supportsAlternateVisual && drawIsOpaque)) { // Analyse the pixel formats either to check whether we can // doCopyBackground or to see if we can find a better visual for // opaque drawing. Visual *target_visual = nullptr; XRenderPictFormat *target_format = nullptr; - switch (target_type) { - case CAIRO_SURFACE_TYPE_XLIB: - target_visual = cairo_xlib_surface_get_visual (target); - target_format = cairo_xlib_surface_get_xrender_format (target); - break; - case CAIRO_SURFACE_TYPE_IMAGE: { + if (cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) { + target_visual = cairo_xlib_surface_get_visual (cairoTarget); + target_format = cairo_xlib_surface_get_xrender_format (cairoTarget); + } else if (cairoTargetType == CAIRO_SURFACE_TYPE_IMAGE || drawTarget) { gfxImageFormat imageFormat = - static_cast<gfxImageSurface*>(destination)->Format(); + drawTarget ? SurfaceFormatToImageFormat(drawTarget->GetFormat()) : + (gfxImageFormat)cairo_image_surface_get_format(cairoTarget); target_visual = gfxXlibSurface::FindVisual(screen, imageFormat); Display *dpy = DisplayOfScreen(screen); if (target_visual) { target_format = XRenderFindVisualFormat(dpy, target_visual); } else { target_format = gfxXlibSurface::FindRenderFormat(dpy, imageFormat); } - break; - } - default: - break; } if (supportsAlternateVisual && (supportsAlternateScreen || screen == target_screen)) { if (target_visual) { visual = target_visual; screen = target_screen; } @@ -408,78 +406,75 @@ CreateTempXlibSurface (gfxASurface *dest gfxImageFormatRGB24); if (rgb24Visual) { visual = rgb24Visual; } } } Drawable drawable = - (screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ? - cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen); + (screen == target_screen && cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) ? + cairo_xlib_surface_get_drawable (cairoTarget) : RootWindowOfScreen(screen); - nsRefPtr<gfxXlibSurface> surface = - gfxXlibSurface::Create(screen, visual, - gfxIntSize(size.width, size.height), - drawable); + cairo_surface_t *surface = + gfxXlibSurface::CreateCairoSurface(screen, visual, + gfxIntSize(size.width, size.height), + drawable); + if (!surface) { + return nullptr; + } if (drawIsOpaque || - surface->GetContentType() == GFX_CONTENT_COLOR_ALPHA) { + cairo_surface_get_content(surface) == CAIRO_CONTENT_COLOR_ALPHA) { NATIVE_DRAWING_NOTE(drawIsOpaque ? ", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA"); *method = eSimple; } else if (doCopyBackground) { NATIVE_DRAWING_NOTE(", COPY BACKGROUND\n"); *method = eCopyBackground; } else { NATIVE_DRAWING_NOTE(", SLOW ALPHA EXTRACTION\n"); *method = eAlphaExtraction; } - return surface.forget(); + return surface; } bool -gfxXlibNativeRenderer::DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface, +gfxXlibNativeRenderer::DrawOntoTempSurface(cairo_surface_t *tempXlibSurface, nsIntPoint offset) { - tempXlibSurface->Flush(); + cairo_surface_flush(tempXlibSurface); /* no clipping is needed because the callback can't draw outside the native surface anyway */ nsresult rv = DrawWithXlib(tempXlibSurface, offset, nullptr, 0); - tempXlibSurface->MarkDirty(); + cairo_surface_mark_dirty(tempXlibSurface); return NS_SUCCEEDED(rv); } static already_AddRefed<gfxImageSurface> -CopyXlibSurfaceToImage(gfxXlibSurface *tempXlibSurface, +CopyXlibSurfaceToImage(cairo_surface_t *tempXlibSurface, + gfxIntSize size, gfxImageFormat format) { - nsRefPtr<gfxImageSurface> result = - new gfxImageSurface(tempXlibSurface->GetSize(), format); + nsRefPtr<gfxImageSurface> result = new gfxImageSurface(size, format); - gfxContext copyCtx(result); - copyCtx.SetSource(tempXlibSurface); - copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE); - copyCtx.Paint(); + cairo_t* copyCtx = cairo_create(result->CairoSurface()); + cairo_set_source_surface(copyCtx, tempXlibSurface, 0, 0); + cairo_set_operator(copyCtx, CAIRO_OPERATOR_SOURCE); + cairo_paint(copyCtx); + cairo_destroy(copyCtx); return result.forget(); } void gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen *screen, Visual *visual, - DrawOutput* result) + uint32_t flags, Screen *screen, Visual *visual) { - if (result) { - result->mSurface = nullptr; - result->mUniformAlpha = false; - result->mUniformColor = false; - } - gfxMatrix matrix = ctx->CurrentMatrix(); // We can only draw direct or onto a copied background if pixels align and // native drawing is compatible with the current operator. (The matrix is // actually also pixel-exact for flips and right-angle rotations, which // would permit copying the background but not drawing direct.) bool matrixIsIntegerTranslation = !matrix.HasNonIntegerTranslation(); bool canDrawOverBackground = matrixIsIntegerTranslation && @@ -526,154 +521,115 @@ gfxXlibNativeRenderer::Draw(gfxContext* clipExtents.RoundOut(); nsIntRect intExtents(int32_t(clipExtents.X()), int32_t(clipExtents.Y()), int32_t(clipExtents.Width()), int32_t(clipExtents.Height())); drawingRect.IntersectRect(drawingRect, intExtents); - if (ctx->IsCairo()) { - nsRefPtr<gfxASurface> target(ctx->CurrentSurface()); - DrawFallback(nullptr, ctx, target, size, drawingRect, canDrawOverBackground, - flags, screen, visual, result); - } else { - DrawTarget* drawTarget = ctx->GetDrawTarget(); - if (!drawTarget) { - return; - } - - nsRefPtr<gfxASurface> target = gfxPlatform::GetPlatform()-> - GetThebesSurfaceForDrawTarget(drawTarget); - if (!target) { - return; - } - DrawFallback(drawTarget, ctx, target, size, drawingRect, canDrawOverBackground, - flags, screen, visual, result); - } -} - -void -gfxXlibNativeRenderer::DrawFallback(DrawTarget* drawTarget, gfxContext* ctx, gfxASurface* target, - nsIntSize& size, nsIntRect& drawingRect, - bool canDrawOverBackground, uint32_t flags, - Screen* screen, Visual* visual, DrawOutput* result) -{ gfxPoint offset(drawingRect.x, drawingRect.y); DrawingMethod method; - nsRefPtr<gfxXlibSurface> tempXlibSurface = - CreateTempXlibSurface(target, drawingRect.Size(), + cairo_surface_t* cairoTarget = nullptr; + DrawTarget* drawTarget = nullptr; + if (ctx->IsCairo()) { + cairoTarget = cairo_get_group_target(ctx->GetCairo()); + } else { + drawTarget = ctx->GetDrawTarget(); + cairoTarget = static_cast<cairo_surface_t*> + (drawTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE)); + } + + cairo_surface_t* tempXlibSurface = + CreateTempXlibSurface(cairoTarget, drawTarget, size, canDrawOverBackground, flags, screen, visual, &method); if (!tempXlibSurface) return; - if (drawingRect.Size() != size || method == eCopyBackground) { - // Only drawing a portion, or copying background, - // so won't return a result. - result = nullptr; - } - - nsRefPtr<gfxContext> tmpCtx; bool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0; if (!drawIsOpaque) { - tmpCtx = new gfxContext(tempXlibSurface); + cairo_t* tmpCtx = cairo_create(tempXlibSurface); if (method == eCopyBackground) { - tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpCtx->SetSource(target, -(offset + ctx->CurrentMatrix().GetTranslation())); + NS_ASSERTION(cairoTarget, "eCopyBackground only used when there's a cairoTarget"); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE); + gfxPoint pt = -(offset + ctx->CurrentMatrix().GetTranslation()); + cairo_set_source_surface(tmpCtx, cairoTarget, pt.x, pt.y); // The copy from the tempXlibSurface to the target context should // use operator SOURCE, but that would need a mask to bound the // operation. Here we only copy opaque backgrounds so operator // OVER will behave like SOURCE masked by the surface. - NS_ASSERTION(tempXlibSurface->GetContentType() - == GFX_CONTENT_COLOR, + NS_ASSERTION(cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR, "Don't copy background with a transparent surface"); } else { - tmpCtx->SetOperator(gfxContext::OPERATOR_CLEAR); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_CLEAR); } - tmpCtx->Paint(); + cairo_paint(tmpCtx); + cairo_destroy(tmpCtx); } if (!DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft())) { + cairo_surface_destroy(tempXlibSurface); return; } + SurfaceFormat moz2DFormat = + cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR ? + FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8; if (method != eAlphaExtraction) { if (drawTarget) { - RefPtr<SourceSurface> sourceSurface = gfxPlatform::GetPlatform()-> - GetSourceSurfaceForSurface(drawTarget, tempXlibSurface); - drawTarget->DrawSurface(sourceSurface, - Rect(offset.x, offset.y, size.width, size.height), - Rect(0, 0, size.width, size.height)); + // It doesn't matter if moz2DFormat doesn't exactly match the format + // of tempXlibSurface, since this DrawTarget just wraps the cairo + // drawing. + RefPtr<SourceSurface> sourceSurface = + Factory::CreateSourceSurfaceForCairoSurface(tempXlibSurface, + moz2DFormat); + if (sourceSurface) { + drawTarget->DrawSurface(sourceSurface, + Rect(offset.x, offset.y, size.width, size.height), + Rect(0, 0, size.width, size.height)); + } } else { - ctx->SetSource(tempXlibSurface, offset); + nsRefPtr<gfxASurface> tmpSurf = gfxASurface::Wrap(tempXlibSurface); + ctx->SetSource(tmpSurf, offset); ctx->Paint(); } - if (result) { - result->mSurface = tempXlibSurface; - /* fill in the result with what we know, which is really just what our - assumption was */ - result->mUniformAlpha = true; - result->mColor.a = 1.0; - } + cairo_surface_destroy(tempXlibSurface); return; } nsRefPtr<gfxImageSurface> blackImage = - CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatARGB32); + CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatARGB32); - tmpCtx->SetDeviceColor(gfxRGBA(1.0, 1.0, 1.0)); - tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpCtx->Paint(); + cairo_t* tmpCtx = cairo_create(tempXlibSurface); + cairo_set_source_rgba(tmpCtx, 1.0, 1.0, 1.0, 1.0); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE); + cairo_paint(tmpCtx); + cairo_destroy(tmpCtx); DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft()); nsRefPtr<gfxImageSurface> whiteImage = - CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatRGB24); + CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatRGB24); if (blackImage->CairoStatus() == CAIRO_STATUS_SUCCESS && whiteImage->CairoStatus() == CAIRO_STATUS_SUCCESS) { - gfxAlphaRecovery::Analysis analysis; - if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage, - result ? &analysis : nullptr)) + if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) { + cairo_surface_destroy(tempXlibSurface); return; + } gfxASurface* paintSurface = blackImage; - /* if the caller wants to retrieve the rendered image, put it into - a 'similar' surface, and use that as the source for the drawing right - now. This means we always return a surface similar to the surface - used for 'cr', which is ideal if it's going to be cached and reused. - We do not return an image if the result has uniform color (including - alpha). */ - if (result) { - if (analysis.uniformAlpha) { - result->mUniformAlpha = true; - result->mColor.a = analysis.alpha; + if (drawTarget) { + RefPtr<SourceSurface> sourceSurface = + Factory::CreateSourceSurfaceForCairoSurface(paintSurface->CairoSurface(), + moz2DFormat); + if (sourceSurface) { + drawTarget->DrawSurface(sourceSurface, + Rect(offset.x, offset.y, size.width, size.height), + Rect(0, 0, size.width, size.height)); } - if (analysis.uniformColor) { - result->mUniformColor = true; - result->mColor.r = analysis.r; - result->mColor.g = analysis.g; - result->mColor.b = analysis.b; - } else { - result->mSurface = target-> - CreateSimilarSurface(GFX_CONTENT_COLOR_ALPHA, - gfxIntSize(size.width, size.height)); - - gfxContext copyCtx(result->mSurface); - copyCtx.SetSource(blackImage); - copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE); - copyCtx.Paint(); - - paintSurface = result->mSurface; - } - } - if (drawTarget) { - RefPtr<SourceSurface> sourceSurface = gfxPlatform::GetPlatform()-> - GetSourceSurfaceForSurface(drawTarget, paintSurface); - drawTarget->DrawSurface(sourceSurface, - Rect(offset.x, offset.y, size.width, size.height), - Rect(0, 0, size.width, size.height)); } else { ctx->SetSource(paintSurface, offset); ctx->Paint(); } } + cairo_surface_destroy(tempXlibSurface); }
--- a/gfx/thebes/gfxXlibNativeRenderer.h +++ b/gfx/thebes/gfxXlibNativeRenderer.h @@ -1,57 +1,56 @@ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- * 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 GFXXLIBNATIVERENDER_H_ #define GFXXLIBNATIVERENDER_H_ -#include "gfxColor.h" -#include "nsAutoPtr.h" +#include "nsPoint.h" +#include "nsRect.h" #include <X11/Xlib.h> namespace mozilla { namespace gfx { class DrawTarget; } } class gfxASurface; -class gfxXlibSurface; class gfxContext; struct nsIntRect; struct nsIntPoint; struct nsIntSize; typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; /** * This class lets us take code that draws into an X drawable and lets us * use it to draw into any Thebes context. The user should subclass this class, * override DrawWithXib, and then call Draw(). The drawing will be subjected * to all Thebes transformations, clipping etc. */ class gfxXlibNativeRenderer { public: /** * Perform the native drawing. - * @param surface the drawable for drawing. + * @param surface the cairo_surface_t for drawing. Must be a cairo_xlib_surface_t. * The extents of this surface do not necessarily cover the * entire rectangle with size provided to Draw(). - * @param offsetX draw at this offset into the given drawable - * @param offsetY draw at this offset into the given drawable + * @param offset draw at this offset into the given drawable * @param clipRects an array of rectangles; clip to the union. * Any rectangles provided will be contained by the * rectangle with size provided to Draw and by the * surface extents. * @param numClipRects the number of rects in the array, or zero if * no clipping is required. */ - virtual nsresult DrawWithXlib(gfxXlibSurface* surface, + virtual nsresult DrawWithXlib(cairo_surface_t* surface, nsIntPoint offset, nsIntRect* clipRects, uint32_t numClipRects) = 0; enum { // If set, then Draw() is opaque, i.e., every pixel in the intersection // of the clipRect and (offset.x,offset.y,bounds.width,bounds.height) // will be set and there is no dependence on what the existing pixels // in the drawable are set to. @@ -66,50 +65,41 @@ public: // passed to 'Draw'. DRAW_SUPPORTS_ALTERNATE_VISUAL = 0x10, // If set, then the Screen 'screen' in the callback can be different // from the default Screen of the display passed to 'Draw' and can be // on a different display. DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20 }; - struct DrawOutput { - nsRefPtr<gfxASurface> mSurface; - bool mUniformAlpha; - bool mUniformColor; - gfxRGBA mColor; - }; - /** * @param flags see above * @param size the size of the rectangle being drawn; * the caller guarantees that drawing will not extend beyond the rectangle * (0,0,size.width,size.height). * @param screen a Screen to use for the drawing if ctx doesn't have one. * @param visual a Visual to use for the drawing if ctx doesn't have one. * @param result if non-null, we will try to capture a copy of the * rendered image into a surface similar to the surface of ctx; if * successful, a pointer to the new gfxASurface is stored in *resultSurface, * otherwise *resultSurface is set to nullptr. */ void Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen *screen, Visual *visual, - DrawOutput* result); + uint32_t flags, Screen *screen, Visual *visual); private: bool DrawDirect(gfxContext *ctx, nsIntSize bounds, uint32_t flags, Screen *screen, Visual *visual); bool DrawCairo(cairo_t* cr, nsIntSize size, uint32_t flags, Screen *screen, Visual *visual); void DrawFallback(mozilla::gfx::DrawTarget* dt, gfxContext* ctx, gfxASurface* aSurface, nsIntSize& size, nsIntRect& drawingRect, bool canDrawOverBackground, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* result); + uint32_t flags, Screen* screen, Visual* visual); - bool DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface, + bool DrawOntoTempSurface(cairo_surface_t *tempXlibSurface, nsIntPoint offset); }; #endif /*GFXXLIBNATIVERENDER_H_*/
--- a/gfx/thebes/gfxXlibSurface.cpp +++ b/gfx/thebes/gfxXlibSurface.cpp @@ -130,16 +130,58 @@ gfxXlibSurface::TakePixmap() Drawable gfxXlibSurface::ReleasePixmap() { NS_ASSERTION(mPixmapTaken, "I don't own the Pixmap!"); mPixmapTaken = false; RecordMemoryFreed(); return mDrawable; } +static cairo_user_data_key_t gDestroyPixmapKey; + +struct DestroyPixmapClosure { + DestroyPixmapClosure(Drawable d, Screen *s) : mPixmap(d), mScreen(s) {} + Drawable mPixmap; + Screen *mScreen; +}; + +static void +DestroyPixmap(void *data) +{ + DestroyPixmapClosure *closure = static_cast<DestroyPixmapClosure*>(data); + XFreePixmap(DisplayOfScreen(closure->mScreen), closure->mPixmap); + delete closure; +} + +/* static */ +cairo_surface_t * +gfxXlibSurface::CreateCairoSurface(Screen *screen, Visual *visual, + const gfxIntSize& size, Drawable relatedDrawable) +{ + Drawable drawable = + CreatePixmap(screen, size, DepthOfVisual(screen, visual), + relatedDrawable); + if (!drawable) + return nullptr; + + cairo_surface_t* surface = + cairo_xlib_surface_create(DisplayOfScreen(screen), drawable, visual, + size.width, size.height); + if (cairo_surface_status(surface)) { + cairo_surface_destroy(surface); + XFreePixmap(DisplayOfScreen(screen), drawable); + return nullptr; + } + + DestroyPixmapClosure *closure = new DestroyPixmapClosure(drawable, screen); + cairo_surface_set_user_data(surface, &gDestroyPixmapKey, + closure, DestroyPixmap); + return surface; +} + /* static */ already_AddRefed<gfxXlibSurface> gfxXlibSurface::Create(Screen *screen, Visual *visual, const gfxIntSize& size, Drawable relatedDrawable) { Drawable drawable = CreatePixmap(screen, size, DepthOfVisual(screen, visual), relatedDrawable); @@ -396,29 +438,37 @@ DisplayTable::DisplayClosing(Display *di sDisplayTable->mDisplays.RemoveElement(display, FindDisplay()); if (sDisplayTable->mDisplays.Length() == 0) { delete sDisplayTable; sDisplayTable = nullptr; } return 0; } +/* static */ +bool +gfxXlibSurface::GetColormapAndVisual(cairo_surface_t* aXlibSurface, + Colormap* aColormap, Visual** aVisual) +{ + XRenderPictFormat* format = + cairo_xlib_surface_get_xrender_format(aXlibSurface); + Screen* screen = cairo_xlib_surface_get_screen(aXlibSurface); + Visual* visual = cairo_xlib_surface_get_visual(aXlibSurface); + + return DisplayTable::GetColormapAndVisual(screen, format, visual, + aColormap, aVisual); +} + bool gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual) { if (!mSurfaceValid) return false; - XRenderPictFormat* format = - cairo_xlib_surface_get_xrender_format(CairoSurface()); - Screen* screen = cairo_xlib_surface_get_screen(CairoSurface()); - Visual* visual = cairo_xlib_surface_get_visual(CairoSurface()); - - return DisplayTable::GetColormapAndVisual(screen, format, visual, - aColormap, aVisual); + return GetColormapAndVisual(CairoSurface(), aColormap, aVisual); } /* static */ int gfxXlibSurface::DepthOfVisual(const Screen* screen, const Visual* visual) { for (int d = 0; d < screen->ndepths; d++) { const Depth& d_info = screen->depths[d];
--- a/gfx/thebes/gfxXlibSurface.h +++ b/gfx/thebes/gfxXlibSurface.h @@ -36,16 +36,19 @@ public: // create a new Pixmap and wrapper surface. // |relatedDrawable| provides a hint to the server for determining whether // the pixmap should be in video or system memory. It must be on // |screen| (if specified). static already_AddRefed<gfxXlibSurface> Create(Screen *screen, Visual *visual, const gfxIntSize& size, Drawable relatedDrawable = None); + static cairo_surface_t * + CreateCairoSurface(Screen *screen, Visual *visual, const gfxIntSize& size, + Drawable relatedDrawable = None); static already_AddRefed<gfxXlibSurface> Create(Screen* screen, XRenderPictFormat *format, const gfxIntSize& size, Drawable relatedDrawable = None); virtual ~gfxXlibSurface(); virtual already_AddRefed<gfxASurface> CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize); @@ -56,16 +59,17 @@ public: Display* XDisplay() { return mDisplay; } Screen* XScreen(); Drawable XDrawable() { return mDrawable; } XRenderPictFormat* XRenderFormat(); static int DepthOfVisual(const Screen* screen, const Visual* visual); static Visual* FindVisual(Screen* screen, gfxImageFormat format); static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format); + static bool GetColormapAndVisual(cairo_surface_t* aXlibSurface, Colormap* colormap, Visual **visual); // take ownership of a passed-in Pixmap, calling XFreePixmap on it // when the gfxXlibSurface is destroyed. void TakePixmap(); // Release ownership of this surface's Pixmap. This is only valid // on gfxXlibSurfaces for which the user called TakePixmap(), or // on those created by a Create() factory method.
--- a/ipc/ipdl/Makefile.in +++ b/ipc/ipdl/Makefile.in @@ -3,18 +3,16 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. GARBAGE_DIRS += _ipdlheaders GARBAGE += ipdl_lextab.py ipdl_yacctab.py $(wildcard *.pyc $(srcdir)/ipdl/*.pyc $(srcdir)/ipdl/cxx/*.pyc) # This file is generated by the moz.build backend. include ipdlsrcs.mk -GARBAGE += $(CPPSRCS) - LOCAL_INCLUDES += -I$(DEPTH)/ipc/ipdl/_ipdlheaders include $(topsrcdir)/config/rules.mk # NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself, # which is why we don't have explicit .h/.cpp targets here
--- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -364,17 +364,17 @@ ifndef HAVE_DTRACE endif endif DIST_GARBAGE = config.cache config.log config.status* \ config/autoconf.mk config/emptyvars.mk \ $(JS_CONFIG_NAME) js-config.h js-confdefs.h \ backend.mk config/backend.mk devtools/backend.mk editline/backend.mk \ gdb/backend.mk jsapi-tests/backend.mk shell/backend.mk tests/backend.mk \ - backend.RecursiveMakeBackend.built backend.RecursiveMakeBackend.built.pp \ + backend.RecursiveMakeBackend backend.RecursiveMakeBackend.pp \ devtools/rootAnalysis/Makefile distclean:: $(RM) $(DIST_GARBAGE) DEFINES += -DEXPORT_JS_API INCLUDES += -I$(srcdir)
--- a/js/src/build/ConfigStatus.py +++ b/js/src/build/ConfigStatus.py @@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo from mozbuild.frontend.emitter import TreeMetadataEmitter from mozbuild.frontend.reader import BuildReader from mozbuild.mozinfo import write_mozinfo log_manager = LoggingManager() -def config_status(topobjdir = '.', topsrcdir = '.', - defines = [], non_global_defines = [], substs = [], - files = [], headers = []): +def config_status(topobjdir='.', topsrcdir='.', + defines=[], non_global_defines=[], substs=[]): '''Main function, providing config.status functionality. Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS - variables, but like config.status from autoconf 2.6, single files may be - generated with the --file and --header options. Several such options can - be given to generate several files at the same time. + variables. Without the -n option, this program acts as config.status and considers the current directory as the top object directory, even when config.status is in a different directory. It will, however, treat the directory - containing config.status as the top object directory with the -n option, - while files given to the --file and --header arguments are considered - relative to the current directory. + containing config.status as the top object directory with the -n option. The --recheck option, like with the original config.status, runs configure again, with the options given in the "ac_configure_args" subst. The options to this function are passed when creating the - ConfigEnvironment, except for files and headers, which contain the list - of files and headers to be generated by default. These lists, as well as - the actual wrapper script around this function, are meant to be generated - by configure. See build/autoconf/config.status.m4. - - Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS, - but like config.status behaviour with --file and --header, providing - files or headers on the command line inhibits the default generation of - files when given headers and headers when given files. - - Unlike config.status, the FILE:TEMPLATE syntax is not supported for - files and headers. The template is always the filename suffixed with - '.in', in the corresponding directory under the top source directory. + ConfigEnvironment. These lists, as well as the actual wrapper script + around this function, are meant to be generated by configure. + See build/autoconf/config.status.m4. ''' if 'CONFIG_FILES' in os.environ: - raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.' + raise Exception('Using the CONFIG_FILES environment variable is not ' + 'supported.') if 'CONFIG_HEADERS' in os.environ: - raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.' + raise Exception('Using the CONFIG_HEADERS environment variable is not ' + 'supported.') + + if not os.path.isabs(topsrcdir): + raise Exception('topsrcdir must be defined as an absolute directory: ' + '%s' % topsrcdir) parser = OptionParser() parser.add_option('--recheck', dest='recheck', action='store_true', help='update config.status by reconfiguring in the same conditions') - parser.add_option('--file', dest='files', metavar='FILE', action='append', - help='instantiate the configuration file FILE') - parser.add_option('--header', dest='headers', metavar='FILE', action='append', - help='instantiate the configuration header FILE') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='display verbose output') parser.add_option('-n', dest='not_topobjdir', action='store_true', help='do not consider current directory as top object directory') (options, args) = parser.parse_args() # Without -n, the current directory is meant to be the top object directory if not options.not_topobjdir: @@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr reader = BuildReader(env) emitter = TreeMetadataEmitter(env) backend = RecursiveMakeBackend(env) # This won't actually do anything because of the magic of generators. definitions = emitter.emit(reader.read_topsrcdir()) if options.recheck: # Execute configure from the top object directory - if not os.path.isabs(topsrcdir): - topsrcdir = relpath(topsrcdir, topobjdir) os.chdir(topobjdir) os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion'])) - if options.files: - files = options.files - headers = [] - if options.headers: - headers = options.headers - if not options.files: - files = [] - # Default to display messages when giving --file or --headers on the - # command line. - log_level = logging.INFO - - if options.files or options.headers or options.verbose: - log_level = logging.DEBUG - + log_level = logging.DEBUG if options.verbose else logging.INFO log_manager.add_terminal_logging(level=log_level) log_manager.enable_unstructured() - if not options.files and not options.headers: - print('Reticulating splines...', file=sys.stderr) - summary = backend.consume(definitions) - - for line in summary.summaries(): - print(line, file=sys.stderr) + print('Reticulating splines...', file=sys.stderr) + summary = backend.consume(definitions) - files = [os.path.join(topobjdir, f) for f in files] - headers = [os.path.join(topobjdir, f) for f in headers] - - for file in files: - env.create_config_file(file) - for header in headers: - env.create_config_header(header) + for line in summary.summaries(): + print(line, file=sys.stderr)
--- a/js/src/build/autoconf/config.status.m4 +++ b/js/src/build/autoconf/config.status.m4 @@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([ define([AC_DEFINE_UNQUOTED], [cat >> confdefs.pytmp <<EOF (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 ')) EOF ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl ]) dnl Replace AC_OUTPUT to create and call a python config.status -define([AC_OUTPUT], +define([_MOZ_AC_OUTPUT], [dnl Top source directory in Windows format (as opposed to msys format). WIN_TOP_SRC= encoding=utf-8 case "$host_os" in mingw*) WIN_TOP_SRC=`cd $srcdir; pwd -W` encoding=mbcs ;; @@ -116,57 +116,30 @@ dnl Add in the output from the subconfig for ac_subst_arg in $_subconfigure_ac_subst_args; do variable='$'$ac_subst_arg echo " (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS done cat >> $CONFIG_STATUS <<\EOF ] ] -dnl List of files to apply AC_SUBSTs to. This is the list of files given -dnl as an argument to AC_OUTPUT ($1) -files = [ -EOF - -for out in $1; do - echo " '$out'," >> $CONFIG_STATUS -done - -cat >> $CONFIG_STATUS <<\EOF -] - -dnl List of header files to apply AC_DEFINEs to. This is stored in the -dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER. -headers = [ -EOF - -ifdef(<<<AC_LIST_HEADER>>>, <<< -HEADERS="AC_LIST_HEADER" -for header in $HEADERS; do - echo " '$header'," >> $CONFIG_STATUS -done ->>>)dnl - -cat >> $CONFIG_STATUS <<\EOF -] - dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES non_global_defines = [ EOF if test -n "$_NON_GLOBAL_ACDEFINES"; then for var in $_NON_GLOBAL_ACDEFINES; do echo " '$var'," >> $CONFIG_STATUS done fi cat >> $CONFIG_STATUS <<EOF ] -__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers'] +__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs'] dnl Do the actual work if __name__ == '__main__': args = dict([(name, globals()[name]) for name in __all__]) import sys dnl Don't rely on virtualenv here. Standalone js doesn't use it. sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build')) from ConfigStatus import config_status @@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files dnl Execute config.status, unless --no-create was passed to configure. if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then trap '' EXIT exit 1 fi ]) +define([m4_fatal],[ +errprint([$1 +]) +m4exit(1) +]) + +define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()], +[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])] +)]) + +define([AC_CONFIG_HEADER], +[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.]) +]) + AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/js/src/config/moz.build +++ b/js/src/config/moz.build @@ -1,14 +1,19 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. +CONFIGURE_SUBST_FILES += [ + 'autoconf.mk', + 'emptyvars.mk', +] + NO_DIST_INSTALL = True # For sanity's sake, we compile nsinstall without the wrapped system # headers, so that we can use it to set up the wrapped system headers. NO_VISIBILITY_FLAGS = True if CONFIG['HOST_OS_ARCH'] != 'WINNT': HOST_SOURCES += [ 'nsinstall.c',
--- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -597,36 +597,31 @@ ifndef MOZBUILD_BACKEND_CHECKED # Since Makefile is listed as a global dependency, this has the # unfortunate side-effect of invalidating all targets if it is executed. # So e.g. if you are in /dom/bindings and /foo/moz.build changes, # /dom/bindings will get invalidated. The upside is if the current # Makefile/backend.mk is updated as a result of backend regeneration, we # actually pick up the changes. This should reduce the amount of # required clobbers and is thus the lesser evil. -Makefile: $(DEPTH)/backend.RecursiveMakeBackend.built +Makefile: $(DEPTH)/backend.RecursiveMakeBackend @$(TOUCH) $@ -$(DEPTH)/backend.RecursiveMakeBackend.built: +$(DEPTH)/backend.RecursiveMakeBackend: @echo "Build configuration changed. Regenerating backend." @cd $(DEPTH) && $(PYTHON) ./config.status @$(TOUCH) $@ -include $(DEPTH)/backend.RecursiveMakeBackend.built.pp +include $(DEPTH)/backend.RecursiveMakeBackend.pp -default:: $(DEPTH)/backend.RecursiveMakeBackend.built +default:: $(DEPTH)/backend.RecursiveMakeBackend export MOZBUILD_BACKEND_CHECKED=1 endif - -# SUBMAKEFILES: List of Makefiles for next level down. -# This is used to update or create the Makefiles before invoking them. -SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS)) - # The root makefile doesn't want to do a plain export/libs, because # of the tiers and because of libxul. Suppress the default rules in favor # of something else. Makefiles which use this var *must* provide a sensible # default rule before including rules.mk ifndef SUPPRESS_DEFAULT_RULES default all:: $(MAKE) export ifdef MOZ_PSEUDO_DERECURSE @@ -644,35 +639,24 @@ ECHO := true QUIET := -q endif # Do everything from scratch everything:: $(MAKE) clean $(MAKE) all -# Target to only regenerate makefiles -makefiles: $(SUBMAKEFILES) -ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS)) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS))) $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only) endif HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS)) # Dependencies which, if modified, should cause everything to rebuild GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk -ifndef NO_MAKEFILE_RULE -GLOBAL_DEPS += Makefile.in -endif ############################################## OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS) compile:: $(OBJ_TARGETS) include $(topsrcdir)/config/makefiles/target_libs.mk @@ -737,30 +721,30 @@ endif endif # NO_PROFILE_GUIDED_OPTIMIZE ############################################## checkout: $(MAKE) -C $(topsrcdir) -f client.mk checkout -clean clobber realclean clobber_all:: $(SUBMAKEFILES) +clean clobber realclean clobber_all:: -$(RM) $(ALL_TRASH) -$(RM) -r $(ALL_TRASH_DIRS) ifdef TIERS clean clobber realclean clobber_all distclean:: $(foreach dir, \ $(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \ -$(call SUBMAKE,$@,$(dir))) else clean clobber realclean clobber_all distclean:: $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) -distclean:: $(SUBMAKEFILES) +distclean:: $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) endif distclean:: -$(RM) -r $(ALL_TRASH_DIRS) -$(RM) $(ALL_TRASH) \ Makefile .HSancillary \ $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \ @@ -1158,44 +1142,16 @@ endif ############################################################################### # Java rules ############################################################################### ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS)) include $(topsrcdir)/config/makefiles/java-build.mk endif ############################################################################### -# Update Files Managed by Build Backend -############################################################################### - -ifndef NO_MAKEFILE_RULE -Makefile: Makefile.in - @$(PYTHON) $(DEPTH)/config.status -n --file=Makefile - @$(TOUCH) $@ -endif - -ifndef NO_SUBMAKEFILES_RULE -ifdef SUBMAKEFILES -# VPATH does not work on some machines in this case, so add $(srcdir) -$(SUBMAKEFILES): % : $(srcdir)/%.in - $(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@" - @$(TOUCH) "$@" -endif -endif - -ifdef AUTOUPDATE_CONFIGURE -$(topsrcdir)/configure: $(topsrcdir)/configure.in - (cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck -endif - -$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in - $(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk - $(TOUCH) $@ - -############################################################################### # Bunch of things that extend the 'export' rule (in order): ############################################################################### ifneq ($(XPI_NAME),) $(FINAL_TARGET): $(NSINSTALL) -D $@ export:: $(FINAL_TARGET) @@ -1620,34 +1576,34 @@ endif # Used as a dependency to force targets to rebuild FORCE: # Delete target if error occurs when building target .DELETE_ON_ERROR: tags: TAGS -TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h) +TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h) -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h) $(LOOP_OVER_PARALLEL_DIRS) $(LOOP_OVER_DIRS) ifndef INCLUDED_DEBUGMAKE_MK #{ ## Only parse when an echo* or show* target is requested ifneq (,$(call isTargetStem,echo,show)) include $(topsrcdir)/config/makefiles/debugmake.mk endif #} endif #} documentation: @cd $(DEPTH) $(DOXYGEN) $(DEPTH)/config/doxygen.cfg ifdef ENABLE_TESTS -check:: $(SUBMAKEFILES) +check:: $(LOOP_OVER_PARALLEL_DIRS) $(LOOP_OVER_DIRS) $(LOOP_OVER_TOOL_DIRS) endif FREEZE_VARIABLES = \ CSRCS \
--- a/js/src/configure.in +++ b/js/src/configure.in @@ -5,17 +5,16 @@ dnl License, v. 2.0. If a copy of the MP dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. dnl Process this file with autoconf to produce a configure script. dnl ======================================================== AC_PREREQ(2.13) AC_INIT(jsapi.h) AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf) -AC_CONFIG_HEADER(js-config.h) AC_CANONICAL_SYSTEM TARGET_CPU="${target_cpu}" TARGET_VENDOR="${target_vendor}" TARGET_OS="${target_os}" dnl ======================================================== dnl = dnl = Don't change the following two lines. Doing so breaks: @@ -4262,17 +4261,17 @@ AC_HAVE_FUNCS(localeconv) AC_SUBST(MOZILLA_VERSION) AC_SUBST(ac_configure_args) dnl Spit out some output dnl ======================================================== -AC_OUTPUT([js-confdefs.h config/autoconf.mk config/emptyvars.mk]) +AC_OUTPUT() # Produce the js-config script at configure time; see the comments for # 'js*-config' in Makefile.in. AC_MSG_RESULT(invoking $MAKE to create $JS_CONFIG_NAME script) $MAKE $JS_CONFIG_NAME # Build jsctypes if it's enabled. if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
--- a/js/src/devtools/rootAnalysis/analyze.py +++ b/js/src/devtools/rootAnalysis/analyze.py @@ -119,27 +119,32 @@ JOBS = { 'dbs': (('%(js)s', '%(analysis_scriptdir)s/computeGCTypes.js',), 'gcTypes.txt'), 'allFunctions': (('%(sixgill_bin)s/xdbkeys', 'src_body.xdb',), 'allFunctions.txt'), 'hazards': - (generate_hazards, 'rootingHazards.txt') + (generate_hazards, 'rootingHazards.txt'), + + 'explain': + (('python', '%(analysis_scriptdir)s/explain.py', + '--expect-file=%(analysis_scriptdir)s/expect.json', + '%(hazards)s', '%(gcFunctions)s', + '[explained_hazards]', '[unnecessary]', '[refs]'), + ('hazards.txt', 'unnecessary.txt', 'refs.txt')) } - def out_indexes(command): for i in range(len(command)): m = re.match(r'^\[(.*)\]$', command[i]) if m: yield (i, m.group(1)) - def run_job(name, config): cmdspec, outfiles = JOBS[name] print("Running " + name + " to generate " + str(outfiles)) if hasattr(cmdspec, '__call__'): cmdspec(config, outfiles) else: temp_map = {} cmdspec = fill(cmdspec, config) @@ -227,17 +232,18 @@ if 'ANALYZED_OBJDIR' in os.environ: if 'SOURCE' in os.environ: data['source'] = os.environ['SOURCE'] steps = [ 'dbs', 'callgraph', 'gcTypes', 'gcFunctions', 'allFunctions', - 'hazards' ] + 'hazards', + 'explain' ] if args.list: for step in steps: command, outfilename = JOBS[step] if outfilename: print("%s -> %s" % (step, outfilename)) else: print(step) @@ -247,17 +253,17 @@ for step in steps: command, outfiles = JOBS[step] if isinstance(outfiles, basestring): data[step] = outfiles else: outfile = 0 for (i, name) in out_indexes(command): data[name] = outfiles[outfile] outfile += 1 - assert len(outfiles) == outfile, 'step %s: mismatched number of output files and params' % step + assert len(outfiles) == outfile, 'step \'%s\': mismatched number of output files and params' % step if args.step: steps = steps[steps.index(args.step):] if args.upto: steps = steps[:steps.index(args.upto)+1] for step in steps:
--- a/js/src/devtools/rootAnalysis/annotations.js +++ b/js/src/devtools/rootAnalysis/annotations.js @@ -60,16 +60,17 @@ var ignoreClasses = { // Ignore calls through TYPE.FIELD, where TYPE is the class or struct name containing // a function pointer field named FIELD. var ignoreCallees = { "js::Class.trace" : true, "js::Class.finalize" : true, "JSRuntime.destroyPrincipals" : true, "nsISupports.AddRef" : true, "nsISupports.Release" : true, // makes me a bit nervous; this is a bug but can happen + "nsIGlobalObject.GetGlobalJSObject" : true, // virtual but no implementation can GC "nsAXPCNativeCallContext.GetJSContext" : true, "js::jit::MDefinition.op" : true, // macro generated virtuals just return a constant "js::jit::MDefinition.opName" : true, // macro generated virtuals just return a constant "js::jit::LInstruction.getDef" : true, // virtual but no implementation can GC "js::jit::IonCache.kind" : true, // macro generated virtuals just return a constant "icu_50::UObject.__deleting_dtor" : true, // destructors in ICU code can't cause GC "mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC. "mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC.
new file mode 100644 --- /dev/null +++ b/js/src/devtools/rootAnalysis/expect.json @@ -0,0 +1,3 @@ +{ + "expect-hazards": 13 +}
new file mode 100755 --- /dev/null +++ b/js/src/devtools/rootAnalysis/explain.py @@ -0,0 +1,120 @@ +#!/usr/bin/python + +import re +import argparse +import sys + +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('rootingHazards', nargs='?', default='rootingHazards.txt') +parser.add_argument('gcFunctions', nargs='?', default='gcFunctions.txt') +parser.add_argument('hazards', nargs='?', default='hazards.txt') +parser.add_argument('extra', nargs='?', default='unnecessary.txt') +parser.add_argument('refs', nargs='?', default='refs.txt') +parser.add_argument('--expect-hazards', type=int, default=None) +parser.add_argument('--expect-refs', type=int, default=None) +parser.add_argument('--expect-file', type=str, default=None) +args = parser.parse_args() + +if args.expect_file: + import json + data = json.load(file(args.expect_file, 'r')) + args.expect_hazards = args.expect_hazards or data.get('expect-hazards') + args.expect_refs = args.expect_refs or data.get('expect-refs') + +num_hazards = 0 +num_refs = 0 +try: + with open(args.rootingHazards) as rootingHazards, \ + open(args.hazards, 'w') as hazards, \ + open(args.extra, 'w') as extra, \ + open(args.refs, 'w') as refs: + current_gcFunction = None + + # Map from a GC function name to the list of hazards resulting from + # that GC function + hazardousGCFunctions = {} + + # List of tuples (gcFunction, index of hazard) used to maintain the + # ordering of the hazards + hazardOrder = [] + + for line in rootingHazards: + m = re.match(r'^Time: (.*)', line) + mm = re.match(r'^Run on:', line) + if m or mm: + print >>hazards, line + print >>extra, line + print >>refs, line + continue + + m = re.match(r'^Function.*has unnecessary root', line) + if m: + print >>extra, line + continue + + m = re.match(r'^Function.*takes unsafe address of unrooted', line) + if m: + num_refs += 1 + print >>refs, line + continue + + m = re.match(r"^Function.*has unrooted.*of type.*live across GC call '(.*?)'", line) + if m: + current_gcFunction = m.group(1) + hazardousGCFunctions.setdefault(current_gcFunction, []).append(line); + hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1)) + num_hazards += 1 + continue + + if current_gcFunction: + if not line.strip(): + # Blank line => end of this hazard + current_gcFunction = None + else: + hazardousGCFunctions[current_gcFunction][-1] += line + + with open(args.gcFunctions) as gcFunctions: + gcExplanations = {} # gcFunction => stack showing why it can GC + + current_func = None + for line in gcFunctions: + m = re.match(r'^GC Function: (.*)', line) + if m: + if current_func: + gcExplanations[current_func] = explanation + current_func = None + if m.group(1) in hazardousGCFunctions: + current_func = m.group(1) + explanation = line + elif current_func: + explanation += line + if current_func: + gcExplanations[current_func] = explanation + + for gcFunction, index in hazardOrder: + gcHazards = hazardousGCFunctions[gcFunction] + print >>hazards, (gcHazards[index] + gcExplanations[gcFunction]) + +except IOError as e: + print 'Failed: %s' % str(e) + +print("Wrote %s" % args.hazards) +print("Wrote %s" % args.extra) +print("Wrote %s" % args.refs) +print("Found %d hazards and %d unsafe references" % (num_hazards, num_refs)) + +if args.expect_hazards is not None and args.expect_hazards != num_hazards: + if args.expect_hazards < num_hazards: + print("TEST-UNEXPECTED-FAILURE: %d more hazards than expected (expected %d, saw %d)" % (num_hazards - args.expect_hazards, args.expect_hazards, num_hazards)) + sys.exit(1) + else: + print("%d fewer hazards than expected! (expected %d, saw %d)" % (args.expect_hazards - num_hazards, args.expect_hazards, num_hazards)) + +if args.expect_refs is not None and args.expect_refs != num_refs: + if args.expect_refs < num_refs: + print("TEST-UNEXPECTED-FAILURE: %d more unsafe refs than expected (expected %d, saw %d)" % (num_refs - args.expect_refs, args.expect_refs, num_refs)) + sys.exit(1) + else: + print("%d fewer unsafe refs than expected! (expected %d, saw %d)" % (args.expect_refs - num_refs, args.expect_refs, num_refs)) + +sys.exit(0)
--- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -236,34 +236,16 @@ class SourceHook { */ extern JS_FRIEND_API(void) SetSourceHook(JSRuntime *rt, SourceHook *hook); /* Remove |rt|'s source hook, and return it. The caller now owns the hook. */ extern JS_FRIEND_API(SourceHook *) ForgetSourceHook(JSRuntime *rt); -inline JSRuntime * -GetRuntime(const JSContext *cx) -{ - return ContextFriendFields::get(cx)->runtime_; -} - -inline JSCompartment * -GetContextCompartment(const JSContext *cx) -{ - return ContextFriendFields::get(cx)->compartment_; -} - -inline JS::Zone * -GetContextZone(const JSContext *cx) -{ - return ContextFriendFields::get(cx)->zone_; -} - extern JS_FRIEND_API(JS::Zone *) GetCompartmentZone(JSCompartment *comp); typedef bool (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj); typedef enum { CollectNurseryBeforeDump,
--- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -354,16 +354,44 @@ struct ContextFriendFields /* Stack of thread-stack-allocated GC roots. */ JS::AutoGCRooter *autoGCRooters; friend JSRuntime *GetRuntime(const JSContext *cx); friend JSCompartment *GetContextCompartment(const JSContext *cx); friend JS::Zone *GetContextZone(const JSContext *cx); }; +/* + * Inlinable accessors for JSContext. + * + * - These must not be available on the more restricted superclasses of + * JSContext, so we can't simply define them on ContextFriendFields. + * + * - They're perfectly ordinary JSContext functionality, so ought to be + * usable without resorting to jsfriendapi.h, and when JSContext is an + * incomplete type. + */ +inline JSRuntime * +GetRuntime(const JSContext *cx) +{ + return ContextFriendFields::get(cx)->runtime_; +} + +inline JSCompartment * +GetContextCompartment(const JSContext *cx) +{ + return ContextFriendFields::get(cx)->compartment_; +} + +inline JS::Zone * +GetContextZone(const JSContext *cx) +{ + return ContextFriendFields::get(cx)->zone_; +} + class PerThreadData; struct PerThreadDataFriendFields { private: // Note: this type only exists to permit us to derive the offset of // the perThread data within the real JSRuntime* type in a portable // way.
--- a/js/src/moz.build +++ b/js/src/moz.build @@ -20,17 +20,24 @@ TEST_DIRS += ['jsapi-tests', 'tests', 'g MODULE = 'js' if CONFIG['JS_STANDALONE']: LIBRARY_NAME = 'mozjs-%s.%s%s' % (CONFIG['MOZJS_MAJOR_VERSION'], CONFIG['MOZJS_MINOR_VERSION'], CONFIG['MOZJS_ALPHA']) else: LIBRARY_NAME = 'mozjs' -CONFIGURE_SUBST_FILES += ['devtools/rootAnalysis/Makefile'] +CONFIGURE_SUBST_FILES += [ + 'devtools/rootAnalysis/Makefile', + 'js-confdefs.h', +] + +CONFIGURE_DEFINE_FILES += [ + 'js-config.h', +] # Changes to internal header files, used externally, massively slow down # browser builds. Don't add new files here unless you know what you're # doing! EXPORTS += [ 'js.msg', 'jsalloc.h', 'jsapi.h',
--- a/js/src/vm/OldDebugAPI.cpp +++ b/js/src/vm/OldDebugAPI.cpp @@ -1024,21 +1024,29 @@ class AutoPropertyDescArray } /* anonymous namespace */ static const char * FormatValue(JSContext *cx, const Value &vArg, JSAutoByteString &bytes) { RootedValue v(cx, vArg); - mozilla::Maybe<AutoCompartment> ac; - if (v.isObject()) - ac.construct(cx, &v.toObject()); + /* + * We could use Maybe<AutoCompartment> here, but G++ can't quite follow + * that, and warns about uninitialized members being used in the + * destructor. + */ + RootedString str(cx); + if (v.isObject()) { + AutoCompartment ac(cx, &v.toObject()); + str = ToString<CanGC>(cx, v); + } else { + str = ToString<CanGC>(cx, v); + } - JSString *str = ToString<CanGC>(cx, v); if (!str) return nullptr; const char *buf = bytes.encodeLatin1(cx, str); if (!buf) return nullptr; const char *found = strstr(buf, "function "); if (found && (found - buf <= 2)) return "[function]";
--- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -1626,23 +1626,27 @@ JS_StructuredClone(JSContext *cx, JS::Ha const JSStructuredCloneCallbacks *callbacks = optionalCallbacks ? optionalCallbacks : cx->runtime()->structuredCloneCallbacks; JSAutoStructuredCloneBuffer buf; { - mozilla::Maybe<AutoCompartment> ac; + // If we use Maybe<AutoCompartment> here, G++ can't tell that the + // destructor is only called when Maybe::construct was called, and + // we get warnings about using uninitialized variables. if (value.isObject()) { - ac.construct(cx, &value.toObject()); + AutoCompartment ac(cx, &value.toObject()); + if (!buf.write(cx, value, callbacks, closure)) + return false; + } else { + if (!buf.write(cx, value, callbacks, closure)) + return false; } - - if (!buf.write(cx, value, callbacks, closure)) - return false; } return buf.read(cx, vp, callbacks, closure); } void JSAutoStructuredCloneBuffer::clear() {
--- a/layout/base/PositionedEventTargeting.cpp +++ b/layout/base/PositionedEventTargeting.cpp @@ -169,16 +169,26 @@ IsElementClickable(nsIFrame* aFrame, nsI if (content->IsHTML()) { if (tag == nsGkAtoms::button || tag == nsGkAtoms::input || tag == nsGkAtoms::select || tag == nsGkAtoms::textarea || tag == nsGkAtoms::label) { return true; } + // Bug 921928: we don't have access to the content of remote iframe. + // So fluffing won't go there. We do an optimistic assumption here: + // that the content of the remote iframe needs to be a target. + if (tag == nsGkAtoms::iframe && + content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozbrowser, + nsGkAtoms::_true, eIgnoreCase) && + content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote, + nsGkAtoms::_true, eIgnoreCase)) { + return true; + } } else if (content->IsXUL()) { nsIAtom* tag = content->Tag(); // See nsCSSFrameConstructor::FindXULTagData. This code is not // really intended to be used with XUL, though. if (tag == nsGkAtoms::button || tag == nsGkAtoms::checkbox || tag == nsGkAtoms::radio || tag == nsGkAtoms::autorepeatbutton ||
--- a/layout/base/tests/Makefile.in +++ b/layout/base/tests/Makefile.in @@ -110,16 +110,18 @@ MOCHITEST_FILES = \ test_bug582181-2.html \ test_bug588174.html \ test_bug607529.html \ file_bug607529.html \ test_bug667512.html \ test_bug677878.html \ test_bug696020.html \ test_event_target_radius.html \ + test_event_target_iframe_oop.html \ + bug921928_event_target_iframe_apps_oop.html \ test_mozPaintCount.html \ test_scroll_event_ordering.html \ test_scroll_selection_into_view.html \ test_bug583889.html \ bug583889_inner1.html \ bug583889_inner2.html \ test_bug582771.html \ test_bug603550.html \
new file mode 100644 --- /dev/null +++ b/layout/base/tests/bug921928_event_target_iframe_apps_oop.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test companion for bug 921928</title> +</head> +<body> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/layout/base/tests/test_event_target_iframe_oop.html @@ -0,0 +1,178 @@ +<!DOCTYPE HTML> +<html id="html" style="height:100%"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=921928 +--> +<head> + <title>Test for bug 921928</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + #dialer { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 50px; + background: green; + } + + #apps { + position: absolute; + left: 0; + top: 51px; + width: 100%; + height: 100px; + background: blue; + } + + .hit { + position: absolute; + width: 3px; + height: 3px; + z-index: 20; + background: red; + border: 1px solid red; + } + </style> +</head> +<body id="body" style="margin:0; width:100%; height:100%"> +<script type="application/javascript"> +SimpleTest.waitForExplicitFinish(); + +var prefs = [ + ["ui.mouse.radius.enabled", true], + ["ui.mouse.radius.inputSource.touchOnly", false], + ["ui.mouse.radius.leftmm", 12], + ["ui.mouse.radius.topmm", 8], + ["ui.mouse.radius.rightmm", 4], + ["ui.mouse.radius.bottommm", 4], + ["ui.mouse.radius.visitedweight", 50], + ["dom.mozBrowserFramesEnabled", true] +]; + +var eventTarget; +var debugHit = []; + +function endTest() { + SimpleTest.finish(); + SpecialPowers.removePermission("browser", location.href); + for (var pref in prefs) { + SpecialPowers.pushPrefEnv({"clear": pref[0]}, function() {}); + } +} + +function testMouseClick(idPosition, dx, dy, idTarget, msg, options) { + eventTarget = null; + synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {}); + try { + is(eventTarget.id, idTarget, + "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]"); + } catch (ex) { + ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget); + } +} + +function showDebug() { + for (var i = 0; i < debugHit.length; i++) { + document.body.appendChild(debugHit[i]); + } + + var screenshot = SpecialPowers.snapshotWindow(window, true); + dump('IMAGE:' + screenshot.toDataURL() + '\n'); +} + +/* + Setup the test environment: enabling event fluffing (all ui.* preferences), + and enabling remote process. +*/ +function setupTest(cont) { + SpecialPowers.addPermission("browser", true, document); + SpecialPowers.pushPrefEnv({"set": prefs}, cont); +} + +function execTest() { + /* + Creating two iframes that mimics the attention screen behavior on the + device: + - the 'dialer' iframe is the attention screen you have when a call is + in place. it is a green bar, so we copy it as green here too + - the 'apps' iframe mimics another application that is being run, be it + dialer, sms, ..., anything that the user might want to trigger during + a call + + The bug we intent to reproduce here is that in this case, if the user taps + onto the top of the 'apps', the event fluffing code will in fact redirect + the event to the 'dialer' iframe. In practice, this is bug 921928 where + during a call the user wants to place a second call, and while typing the + phone number, wants to tap onto the 'delete' key to erase a digit, but ends + tapping and activating the dialer. + */ + var dialer = document.createElement('iframe'); + dialer.id = 'dialer'; + dialer.src = ''; + // Force OOP + dialer.setAttribute('mozbrowser', 'true'); + dialer.setAttribute('remote', 'true'); + document.body.appendChild(dialer); + + var apps = document.createElement('iframe'); + apps.id = 'apps'; + apps.src = 'bug921928_event_target_iframe_apps_oop.html'; + // Force OOP + apps.setAttribute('mozbrowser', 'true'); + apps.setAttribute('remote', 'true'); + document.body.appendChild(apps); + + var handleEvent = function(event) { + eventTarget = event.target; + + // We draw a small red div to show where the event has tapped + var hit = document.createElement('div'); + hit.style.left = (event.clientX - 1.5) + 'px'; + hit.style.top = (event.clientY - 1.5) + 'px'; + hit.classList.add('hit'); + debugHit.push(hit); + }; + + // In real life, the 'dialer' has a 'mousedown', so we mimic one too, + // to reproduce the same behavior + dialer.addEventListener('mousedown', function(e) {}); + + // This event listener is just here to record what iframe has been hit, + // and sets the 'eventTarget' to the iframe's id value so that the + // testMouseClick() code can correctly check. We cannot add it on the + // 'apps' otherwise it will alter the behavior of the test. + document.addEventListener('mousedown', handleEvent); + + // In the following, the coordinates are relative to the iframe + + // First, we check that tapping onto the 'dialer' correctly triggers the + // dialer. + testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with mouse input"); + testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with touch input", { + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH + }); + + // Now this is it: we tap inside 'apps', but very close to the border between + // 'apps' and 'dialer'. Without the fix from this bug, this test will fail. + testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for mouse input"); + testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for touch input", { + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH + }); + + // Show small red spots of where the click happened + // showDebug(); + + endTest(); +} + +function runTest() { + setupTest(execTest); +} + +addEventListener('load', function() { SimpleTest.executeSoon(runTest); }); +</script> +</body> +</html>
--- a/layout/reftests/forms/input/color/custom-style-1.html +++ b/layout/reftests/forms/input/color/custom-style-1.html @@ -1,11 +1,10 @@ <!DOCTYPE html> <html> - <link rel='stylesheet' type='text/css' href='testcase-style.css'> <style> input[type="color"] { -moz-appearance: button; } input[type="color"]::-moz-color-swatch { margin-top: 3px; margin-bottom: 3px; }
--- a/layout/reftests/forms/input/color/input-color-1.html +++ b/layout/reftests/forms/input/color/input-color-1.html @@ -1,10 +1,9 @@ <!DOCTYPE html> <html> - <link rel='stylesheet' type='text/css' href='testcase-style.css'> <body> <input type="color" /> <input type="color" value="#000000" /> <input type="color" value="#00ff00" /> <input type="color" value="#123456" /> </body> </html>
--- a/layout/reftests/forms/input/color/reference-style.css +++ b/layout/reftests/forms/input/color/reference-style.css @@ -1,21 +1,9 @@ -button.input-color { - /* For now, input[type="color"] is styled like a textfield, because it takes - the default 'input' styles in forms.css. Once we're ready to enable it by - default, that will change (and so should these styles here). */ - -moz-appearance: textfield; - padding: 1px 0px 1px 0px; -} -button.input-color::-moz-focus-inner { - padding: 0; - border: 0; -} - div.input-color-swatch { /* This should match the styling for ::-moz-color-swatch in forms.css. */ width: 100%; height: 100%; - min-width: 50px; - min-height: 1em; + min-width: 40px; + min-height: 15px; display: block; background-color:#000000; /* default color for input type color */ }
--- a/layout/reftests/forms/input/color/reftest.list +++ b/layout/reftests/forms/input/color/reftest.list @@ -1,7 +1,13 @@ +# Simple test. Should fail on platforms where input type color isn't activated +# yet. Missing platforms are B2G (bug 875751), Android (bug 875750) and Metro +# (bug 895464). +fails-if(B2G||Android) == input-color-1.html input-color-1-ref.html + default-preferences pref(dom.forms.color,true) -fails-if(B2G) == input-color-1.html input-color-1-ref.html # bug 928877 -fails-if(B2G) == margin-padding-1.html margin-padding-1-ref.html # bug 928877 +# Despite the "default-preferences" line above, B2G and Android are still +# excluded from some style in forms.css, which makes the following tests fail. +fails-if(B2G||Android) == margin-padding-1.html margin-padding-1-ref.html == block-invalidate-1.html block-invalidate-1-ref.html -fails-if(B2G) == transformations-1.html transformations-1-ref.html # bug 928877 -fails-if(B2G) == custom-style-1.html custom-style-1-ref.html # bug 928877 +fails-if(B2G||Android) == transformations-1.html transformations-1-ref.html +fails-if(B2G||Android) == custom-style-1.html custom-style-1-ref.html
deleted file mode 100644 --- a/layout/reftests/forms/input/color/testcase-style.css +++ /dev/null @@ -1,17 +0,0 @@ -input[type=color] { - /* This matches the "padding" declaration for 'input' in forms.css, but we - need to specify it here as well in order for the testcases to match the - reference cases' renderings on Windows. This is because - nsNativeThemeWin.cpp checks HasAuthorSpecifiedRules() when deciding - whether to apply some bonus theme-dependent widget padding. (And that - function only considers *author* style rules - not forms.css.) So, to make - sure the testcase and reference case get equivalent amounts of bonus - padding, we need to specify an *author*-level declaration for "padding" - for any testcase whose reference case has such a declaration. - - Ultimately, when we pref on input[type="color"] by default, we can just - ensure that it uses the same padding as <button> in forms.css, at which - point we can drop the "padding" declaration from the testcases and the - reference cases (and probably drop this file altogether). */ - padding: 1px 0px 1px 0px; -}
--- a/layout/reftests/forms/input/color/transformations-1.html +++ b/layout/reftests/forms/input/color/transformations-1.html @@ -1,11 +1,10 @@ <!DOCTYPE html> <html> - <link rel='stylesheet' type='text/css' href='testcase-style.css'> <style> input[type=color]:nth-child(1) { -moz-transform: matrix(1, -0.2, 0, 1, 0, 0); } input[type=color]:nth-child(2) { -moz-transform: translateX(15em) matrix(1, 0, 0.6, 1, 0, 0); } input[type=color]:nth-child(3) { -moz-transform: rotate(30deg); } input[type=color]:nth-child(4) { -moz-transform: scale(2, 4); } input[type=color]:nth-child(5) { -moz-transform: scale(0.1, 0.4); } input[type=color]:nth-child(6) { -moz-transform: scale(1, 0.4); } input[type=color]:nth-child(7) { -moz-transform: scale(0.1, 1); }
--- a/layout/style/forms.css +++ b/layout/style/forms.css @@ -5,16 +5,22 @@ /** Styles for old GFX form widgets **/ @namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */ @namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul); +%ifdef ANDROID +%define INPUT_TYPE_COLOR_UNSUPPORTED +%elifdef MOZ_WIDGET_GONK +%define INPUT_TYPE_COLOR_UNSUPPORTED +%endif + *|*::-moz-fieldset-content { display: block; unicode-bidi: inherit; text-overflow: inherit; overflow: inherit; padding: inherit; position: inherit; height: 100%; /* Need this so percentage heights of kids work right */ @@ -451,18 +457,18 @@ input[type="file"] > button[type="button letter-spacing: inherit; cursor: inherit; } /* colored part of the color selector button */ input[type="color"]::-moz-color-swatch { width: 100%; height: 100%; - min-width: 50px; - min-height: 1em; + min-width: 40px; + min-height: 15px; margin-left: auto; margin-right: auto; display: block; } /* Try to make RTL <input type='file'> look nicer. */ /* TODO: use text-align: match-parent when bug 645642 is fixed. */ input[type="file"]:-moz-dir(rtl) > xul|label { @@ -533,38 +539,48 @@ input[type="radio"]:hover:active { border-style: inset !important; } /* buttons */ /* Note: Values in nsNativeTheme IsWidgetStyled function need to match button background/border values here */ -/* TODO: Once we're getting ready to turn on 'dom.forms.color' by default, we - probably want to add input[type="color"] to this selector list, so that it - gets the same styling as other form buttons. */ -button, +/* Non text-related properties for buttons: these ones are shared with + input[type="color"] */ +button, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"], +%endif input[type="reset"], input[type="button"], -input[type="submit"] { +input[type="submit"] { -moz-appearance: button; /* The sum of border-top, border-bottom, padding-top, padding-bottom must be the same here, for text inputs, and for <select>. For buttons, make sure to include the -moz-focus-inner border/padding. */ padding: 0px 6px 0px 6px; border: 2px outset ButtonFace; background-color: ButtonFace; + cursor: default; + -moz-box-sizing: border-box; + -moz-user-select: none; + -moz-binding: none; +} + +/* Text-related properties for buttons: these ones are not shared with + input[type="color"] */ +button, +input[type="reset"], +input[type="button"], +input[type="submit"] { color: ButtonText; font: -moz-button; line-height: normal; white-space: pre; - cursor: default; - -moz-box-sizing: border-box; - -moz-user-select: none; - -moz-binding: none; text-align: center; text-shadow: none; } button { /* Buttons should lay out like "normal" html, mostly */ white-space: inherit; text-indent: 0; @@ -572,65 +588,103 @@ button { display: inline-block; } *|*::-moz-button-content { display: block; } button:hover, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"]:hover, +%endif input[type="reset"]:hover, input[type="button"]:hover, input[type="submit"]:hover { background-color: -moz-buttonhoverface; +} + +button:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +input[type="submit"]:hover { color: -moz-buttonhovertext; } button:active:hover, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"]:active:hover, +%endif +input[type="reset"]:active:hover, +input[type="button"]:active:hover, +input[type="submit"]:active:hover { + padding: 0px 5px 0px 7px; + border-style: inset; + background-color: ButtonFace; +} + +button:active:hover, input[type="reset"]:active:hover, input[type="button"]:active:hover, input[type="submit"]:active:hover { - padding: 0px 5px 0px 7px; - border-style: inset; - background-color: ButtonFace; color: ButtonText; } button::-moz-focus-inner, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"]::-moz-focus-inner, +%endif input[type="reset"]::-moz-focus-inner, input[type="button"]::-moz-focus-inner, input[type="submit"]::-moz-focus-inner, input[type="file"] > button[type="button"]::-moz-focus-inner { padding: 0px 2px 0px 2px; border: 1px dotted transparent; } button:-moz-focusring::-moz-focus-inner, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"]:-moz-focusring::-moz-focus-inner, +%endif input[type="reset"]:-moz-focusring::-moz-focus-inner, input[type="button"]:-moz-focusring::-moz-focus-inner, input[type="submit"]:-moz-focusring::-moz-focus-inner, input[type="file"] > button[type="button"]:-moz-focusring::-moz-focus-inner { border-color: ButtonText; } button:disabled:active, button:disabled, +%ifndef INPUT_TYPE_COLOR_UNSUPPORTED +input[type="color"]:disabled:active, +input[type="color"]:disabled, +%endif input[type="reset"]:disabled:active, input[type="reset"]:disabled, input[type="button"]:disabled:active, input[type="button"]:disabled, select:disabled > button, select:disabled > button, input[type="submit"]:disabled:active, input[type="submit"]:disabled { /* The sum of border-top, border-bottom, padding-top, padding-bottom must be the same here and for text inputs */ padding: 0px 6px 0px 6px; border: 2px outset ButtonFace; + cursor: inherit; +} + +input[type="reset"]:disabled:active, +input[type="reset"]:disabled, +input[type="button"]:disabled:active, +input[type="button"]:disabled, +select:disabled > button, +select:disabled > button, +input[type="submit"]:disabled:active, +input[type="submit"]:disabled { color: GrayText; - cursor: inherit; } /* * Make form controls inherit 'unicode-bidi' transparently as required by * their various anonymous descendants and pseudo-elements: * * <textarea> and <input type="text">: * inherit into the XULScroll frame with class 'anonymous-div' which is a
deleted file mode 100644 --- a/media/mtransport/third_party/Makefile.in +++ /dev/null @@ -1,6 +0,0 @@ -# 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/. - - -NO_SUBMAKEFILES_RULE = 1
deleted file mode 100644 --- a/media/webrtc/Makefile.in +++ /dev/null @@ -1,6 +0,0 @@ -# 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/. - -# These Makefiles don't have corresponding Makefile.ins -NO_SUBMAKEFILES_RULE = 1
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py +++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py @@ -34,19 +34,16 @@ topsrcdir = %(topsrcdir)s srcdir = %(srcdir)s VPATH = %(srcdir)s EXTERNALLY_MANAGED_MAKE_FILE := 1 """ COMMON_FOOTER = """ -# Skip rules that deal with regenerating Makefiles from Makefile.in files. -NO_MAKEFILE_RULE = 1 -NO_SUBMAKEFILES_RULE = 1 include %(common_mk_path)s """ COMMON_MK = """# This file was generated by mozmake.py. Do not edit it directly. ifndef COMMON_MK_INCLUDED COMMON_MK_INCLUDED := 1
--- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -159,16 +159,19 @@ pref("findhelper.autozoom", true); pref("browser.formfill.enable", true); /* spellcheck */ pref("layout.spellcheckDefault", 0); /* new html5 forms */ pref("dom.experimental_forms", true); pref("dom.forms.number", true); +// Don't enable <input type=color> yet as we don't have a color picker +// implemented for Android (bug 875750) +pref("dom.forms.color", false); /* extension manager and xpinstall */ pref("xpinstall.whitelist.add", "addons.mozilla.org"); pref("xpinstall.whitelist.add.180", "marketplace.firefox.com"); pref("extensions.enabledScopes", 1); pref("extensions.autoupdate.enabled", true); pref("extensions.autoupdate.interval", 86400);
--- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -1156,36 +1156,28 @@ public class LocalBrowserDB implements B final long now = System.currentTimeMillis(); values.put(Bookmarks.TITLE, title); values.put(Bookmarks.URL, url); values.put(Bookmarks.PARENT, Bookmarks.FIXED_PINNED_LIST_ID); values.put(Bookmarks.DATE_MODIFIED, now); values.put(Bookmarks.POSITION, position); values.put(Bookmarks.IS_DELETED, 0); - // If this site is already pinned, unpin it - cr.delete(mBookmarksUriWithProfile, - Bookmarks.PARENT + " == ? AND " + Bookmarks.URL + " == ?", - new String[] { - String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID), - url - }); - - // If something is already pinned in this spot update it - int updated = cr.update(mBookmarksUriWithProfile, - values, - Bookmarks.POSITION + " = ? AND " + - Bookmarks.PARENT + " = ?", - new String[] { Integer.toString(position), - String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) }); - - // Otherwise just insert a new item - if (updated == 0) { - cr.insert(mBookmarksUriWithProfile, values); - } + // We do an update-and-replace here without deleting any existing pins for the given URL. + // That means if the user pins a URL, then edits another thumbnail to use the same URL, + // we'll end up with two pins for that site. This is the intended behavior, which + // incidentally saves us a delete query. + Uri uri = mBookmarksUriWithProfile.buildUpon() + .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build(); + cr.update(uri, + values, + Bookmarks.POSITION + " = ? AND " + + Bookmarks.PARENT + " = ?", + new String[] { Integer.toString(position), + String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) }); } @Override public Cursor getPinnedSites(ContentResolver cr, int limit) { return cr.query(bookmarksUriWithLimit(limit), new String[] { Bookmarks._ID, Bookmarks.URL, Bookmarks.TITLE,
--- a/mobile/android/components/SessionStore.idl +++ b/mobile/android/components/SessionStore.idl @@ -9,17 +9,17 @@ interface nsIDOMNode; /** * nsISessionStore keeps track of the current browsing state. * * The nsISessionStore API operates mostly on browser windows and the browser * tabs contained in them. */ -[scriptable, uuid(15152edf-6c99-4277-9020-076be4653c69)] +[scriptable, uuid(fe116b56-0226-4562-b52a-a623dad07ead)] interface nsISessionStore : nsISupports { /** * Get the current browsing state. * @returns a JSON string representing the session state. */ AString getBrowserState();
--- a/mobile/android/config/mozconfigs/android-armv6/release +++ b/mobile/android/config/mozconfigs/android-armv6/release @@ -1,32 +1,18 @@ . "$topsrcdir/mobile/android/config/mozconfigs/common" -# Build Fennec -ac_add_options --enable-application=mobile/android - -# Android ac_add_options --target=arm-linux-androideabi ac_add_options --with-arch=armv6 -if test `uname -m` = 'x86_64'; then - ac_add_options --with-android-ndk="$topsrcdir/android-ndk" - ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16" -else - ac_add_options --with-android-ndk="/tools/android-ndk-r8c" - ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16" -fi +export MOZ_PKG_SPECIAL=armv6 -ac_add_options --with-android-gnu-compiler-version=4.7 -ac_add_options --with-android-version=9 -ac_add_options --with-system-zlib +ac_add_options --with-branding=mobile/android/branding/beta + ac_add_options --enable-updater -ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 -export MOZ_PKG_SPECIAL=armv6 ac_add_options --enable-official-branding -ac_add_options --with-branding=mobile/android/branding/beta . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86/release +++ b/mobile/android/config/mozconfigs/android-x86/release @@ -1,30 +1,16 @@ . "$topsrcdir/mobile/android/config/mozconfigs/common" -# Build Fennec -ac_add_options --enable-application=mobile/android - # Android ac_add_options --target=i386-linux-android -if test `uname -m` = 'x86_64'; then - ac_add_options --with-android-ndk="$topsrcdir/android-ndk" - ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16" -else - ac_add_options --with-android-ndk="/tools/android-ndk-r8c" - ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16" -fi +ac_add_options --enable-updater -ac_add_options --with-android-gnu-compiler-version=4.7 -ac_add_options --with-android-version=9 -ac_add_options --with-system-zlib -ac_add_options --enable-updater -ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +ac_add_options --with-branding=mobile/android/branding/beta export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 ac_add_options --enable-official-branding -ac_add_options --with-branding=mobile/android/branding/beta . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android/release +++ b/mobile/android/config/mozconfigs/android/release @@ -1,30 +1,13 @@ . "$topsrcdir/mobile/android/config/mozconfigs/common" -# Build Fennec -ac_add_options --enable-application=mobile/android - -# Android -ac_add_options --target=arm-linux-androideabi +ac_add_options --enable-updater -if test `uname -m` = 'x86_64'; then - ac_add_options --with-android-ndk="$topsrcdir/android-ndk" - ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16" -else - ac_add_options --with-android-ndk="/tools/android-ndk-r8c" - ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16" -fi - -ac_add_options --with-android-gnu-compiler-version=4.7 -ac_add_options --with-android-version=9 -ac_add_options --with-system-zlib -ac_add_options --enable-updater -ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +ac_add_options --with-branding=mobile/android/branding/beta export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 ac_add_options --enable-official-branding -ac_add_options --with-branding=mobile/android/branding/beta . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -382,18 +382,16 @@ @BINPATH@/components/nsPrompter.manifest @BINPATH@/components/nsPrompter.js @BINPATH@/components/TelemetryPing.js @BINPATH@/components/TelemetryPing.manifest @BINPATH@/components/Webapps.js @BINPATH@/components/Webapps.manifest @BINPATH@/components/AppsService.js @BINPATH@/components/AppsService.manifest -@BINPATH@/components/AppProtocolHandler.js -@BINPATH@/components/AppProtocolHandler.manifest @BINPATH@/components/Push.js @BINPATH@/components/Push.manifest @BINPATH@/components/SystemMessageInternal.js @BINPATH@/components/SystemMessageManager.js @BINPATH@/components/SystemMessageManager.manifest
--- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -848,18 +848,19 @@ pref("dom.send_after_paint_to_content", pref("dom.min_timeout_value", 4); // And for background windows pref("dom.min_background_timeout_value", 1000); // Don't use new input types pref("dom.experimental_forms", false); pref("dom.forms.number", false); -// Don't enable <input type=color> yet: -pref("dom.forms.color", false); +// Enable <input type=color> by default. It will be turned off for remaining +// platforms which don't have a color picker implemented yet. +pref("dom.forms.color", true); // Enables system messages and activities pref("dom.sysmsg.enabled", false); // Enable pre-installed applications. pref("dom.webapps.useCurrentProfile", false); // Parsing perf prefs. For now just mimic what the old code did.
--- a/moz.build +++ b/moz.build @@ -1,15 +1,18 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. -CONFIGURE_SUBST_FILES += ['tools/update-packaging/Makefile'] +CONFIGURE_SUBST_FILES += [ + 'mozilla-config.h', + 'tools/update-packaging/Makefile', +] if CONFIG['ENABLE_CLANG_PLUGIN']: add_tier_dir('base', 'build/clang-plugin', external=True) add_tier_dir('base', ['config', 'build', 'probes', 'mfbt', 'python']) if not CONFIG['LIBXUL_SDK']: if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
--- a/netwerk/base/public/security-prefs.js +++ b/netwerk/base/public/security-prefs.js @@ -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/. */ pref("security.tls.version.min", 0); -pref("security.tls.version.max", 1); +pref("security.tls.version.max", 2); pref("security.enable_md5_signatures", false); pref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", false); pref("security.ssl.renego_unrestricted_hosts", ""); pref("security.ssl.treat_unsafe_negotiation_as_broken", false); pref("security.ssl.require_safe_negotiation", false); pref("security.ssl.warn_missing_rfc5746", 1); pref("security.ssl.enable_ocsp_stapling", true);
--- a/netwerk/build/Makefile.in +++ b/netwerk/build/Makefile.in @@ -64,16 +64,17 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../base/src \ -I$(srcdir)/../dns \ -I$(srcdir)/../socket \ -I$(srcdir)/../streamconv/src \ -I$(srcdir)/../streamconv/converters \ -I$(srcdir)/../mime \ -I$(srcdir)/../cache \ -I$(srcdir)/../protocol/about \ + -I$(srcdir)/../protocol/app \ -I../dns \ $(foreach d,$(filter-out about,$(NECKO_PROTOCOLS)), \ -I$(srcdir)/../protocol/$(d)) \ $(NULL) ifeq ($(OS_ARCH),WINNT) LOCAL_INCLUDES += -I$(srcdir)/../system/win32 endif
--- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -609,16 +609,28 @@ { /* fbc81170-1f69-11d3-9344-00104ba0fd40 */ \ 0xfbc81170, \ 0x1f69, \ 0x11d3, \ {0x93, 0x44, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \ } /****************************************************************************** + * netwerk/protocol/app/ classes + */ + +#define NS_APPPROTOCOLHANDLER_CID \ +{ /* {B6ED3030-9999-11d3-A178-0050041CAF44} */ \ + 0xb6ed3030, \ + 0x9999, \ + 0x11d3, \ + {0xa1, 0x78, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ +} + +/****************************************************************************** * netwerk/protocol/data/ classes */ #define NS_DATAPROTOCOLHANDLER_CID \ { /* {B6ED3030-6183-11d3-A178-0050041CAF44} */ \ 0xb6ed3030, \ 0x6183, \ 0x11d3, \
--- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -239,16 +239,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpDig #endif // !NECKO_PROTOCOL_http #include "mozilla/net/Dashboard.h" namespace mozilla { namespace net { NS_GENERIC_FACTORY_CONSTRUCTOR(Dashboard) } } +#include "AppProtocolHandler.h" #ifdef NECKO_PROTOCOL_res // resource #include "nsResProtocolHandler.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsResProtocolHandler, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsResURL) #endif @@ -768,16 +769,17 @@ NS_DEFINE_NAMED_CID(NS_ABOUT_CACHE_ENTRY #endif NS_DEFINE_NAMED_CID(NS_SOCKSSOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_SOCKS4SOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_UDPSOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_CACHESERVICE_CID); NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHESERVICE_CID); NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHENAMESPACE_CID); NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHE_CID); +NS_DEFINE_NAMED_CID(NS_APPPROTOCOLHANDLER_CID); #ifdef NECKO_COOKIES NS_DEFINE_NAMED_CID(NS_COOKIEMANAGER_CID); NS_DEFINE_NAMED_CID(NS_COOKIESERVICE_CID); #endif #ifdef NECKO_WIFI NS_DEFINE_NAMED_CID(NS_WIFI_MONITOR_COMPONENT_CID); #endif #ifdef NECKO_PROTOCOL_data @@ -907,16 +909,17 @@ static const mozilla::Module::CIDEntry k #endif { &kNS_SOCKSSOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV5 }, { &kNS_SOCKS4SOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV4 }, { &kNS_UDPSOCKETPROVIDER_CID, false, nullptr, nsUDPSocketProviderConstructor }, { &kNS_CACHESERVICE_CID, false, nullptr, nsCacheService::Create }, { &kNS_APPLICATIONCACHESERVICE_CID, false, nullptr, nsApplicationCacheServiceConstructor }, { &kNS_APPLICATIONCACHENAMESPACE_CID, false, nullptr, nsApplicationCacheNamespaceConstructor }, { &kNS_APPLICATIONCACHE_CID, false, nullptr, nsApplicationCacheConstructor }, + { &kNS_APPPROTOCOLHANDLER_CID, false, nullptr, AppProtocolHandler::Create }, #ifdef NECKO_COOKIES { &kNS_COOKIEMANAGER_CID, false, nullptr, nsICookieServiceConstructor }, { &kNS_COOKIESERVICE_CID, false, nullptr, nsICookieServiceConstructor }, #endif #ifdef NECKO_WIFI { &kNS_WIFI_MONITOR_COMPONENT_CID, false, nullptr, nsWifiMonitorConstructor }, #endif #ifdef NECKO_PROTOCOL_data @@ -1053,16 +1056,17 @@ static const mozilla::Module::ContractID #endif { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks", &kNS_SOCKSSOCKETPROVIDER_CID }, { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks4", &kNS_SOCKS4SOCKETPROVIDER_CID }, { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "udp", &kNS_UDPSOCKETPROVIDER_CID }, { NS_CACHESERVICE_CONTRACTID, &kNS_CACHESERVICE_CID }, { NS_APPLICATIONCACHESERVICE_CONTRACTID, &kNS_APPLICATIONCACHESERVICE_CID }, { NS_APPLICATIONCACHENAMESPACE_CONTRACTID, &kNS_APPLICATIONCACHENAMESPACE_CID }, { NS_APPLICATIONCACHE_CONTRACTID, &kNS_APPLICATIONCACHE_CID }, + { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "app", &kNS_APPPROTOCOLHANDLER_CID }, #ifdef NECKO_COOKIES { NS_COOKIEMANAGER_CONTRACTID, &kNS_COOKIEMANAGER_CID }, { NS_COOKIESERVICE_CONTRACTID, &kNS_COOKIESERVICE_CID }, #endif #ifdef NECKO_WIFI { NS_WIFI_MONITOR_CONTRACTID, &kNS_WIFI_MONITOR_COMPONENT_CID }, #endif #ifdef NECKO_PROTOCOL_data
--- a/netwerk/moz.build +++ b/netwerk/moz.build @@ -31,8 +31,10 @@ PARALLEL_DIRS += ['locales'] if CONFIG['MOZ_DASH']: PARALLEL_DIRS += ['dash'] DIRS += ['build'] TEST_TOOL_DIRS += ['test'] MODULE = 'necko' + +CONFIGURE_DEFINE_FILES += ['necko-config.h']
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/app/AppProtocolHandler.cpp @@ -0,0 +1,423 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set expandtab ts=2 sw=2 sts=2 cin: */ +/* 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 "AppProtocolHandler.h" +#include "nsBaseChannel.h" +#include "nsJARChannel.h" +#include "nsNetCID.h" +#include "nsIAppsService.h" +#include "nsCxPusher.h" +#include "nsXULAppAPI.h" + +/** + * This dummy channel implementation only provides enough functionality + * to return a fake 404 error when the caller asks for an app:// URL + * containing an unknown appId. + */ +class DummyChannel : public nsIJARChannel + , nsRunnable +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIREQUEST + NS_DECL_NSICHANNEL + NS_DECL_NSIJARCHANNEL + + DummyChannel(); + + NS_IMETHODIMP Run(); + +private: + bool mPending; + uint32_t mSuspendCount; + nsCOMPtr<nsISupports> mListenerContext; + nsCOMPtr<nsIStreamListener> mListener; + nsCOMPtr<nsILoadGroup> mLoadGroup; + nsLoadFlags mLoadFlags; +}; + +NS_IMPL_ISUPPORTS3(DummyChannel, nsIRequest, nsIChannel, nsIJARChannel) + +DummyChannel::DummyChannel() : mPending(false) + , mSuspendCount(0) + , mLoadFlags(LOAD_NORMAL) +{ +} + +NS_IMETHODIMP DummyChannel::GetName(nsACString &result) +{ + result = "dummy_app_channel"; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus) +{ + *aStatus = NS_ERROR_FILE_NOT_FOUND; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::IsPending(bool *aResult) +{ + *aResult = mPending; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::Suspend() +{ + mSuspendCount++; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::Resume() +{ + if (mSuspendCount <= 0) { + return NS_ERROR_UNEXPECTED; + } + + if (--mSuspendCount == 0) { + NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); + } + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::Open(nsIInputStream**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext) +{ + mListener = aListener; + mListenerContext = aContext; + mPending = true; + + if (mLoadGroup) { + mLoadGroup->AddRequest(this, aContext); + } + + if (mSuspendCount == 0) { + NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); + } + + return NS_OK; +} + +// nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into +// a 404 error. +NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult) +{ + *aResult = false; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::Run() +{ + nsresult rv = mListener->OnStartRequest(this, mListenerContext); + NS_ENSURE_SUCCESS(rv, rv); + mPending = false; + rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); + NS_ENSURE_SUCCESS(rv, rv); + if (mLoadGroup) { + mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); + } + + mListener = nullptr; + mListenerContext = nullptr; + rv = SetNotificationCallbacks(nullptr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::Cancel(nsresult) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup) +{ + *aLoadGroup = mLoadGroup; + NS_IF_ADDREF(*aLoadGroup); + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) +{ + mLoadGroup = aLoadGroup; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags) +{ + *aLoadFlags = mLoadFlags; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags) +{ + mLoadFlags = aLoadFlags; + return NS_OK; +} + +NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentType(nsACString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetContentLength(int64_t) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetURI(nsIURI**) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/** + * app:// protocol implementation. + */ + +AppProtocolHandler::AppProtocolHandler() { +} + +AppProtocolHandler::~AppProtocolHandler() { + mAppInfoCache.Clear(); +} + +NS_IMPL_ISUPPORTS1(AppProtocolHandler, nsIProtocolHandler) + +/* static */ +nsresult +AppProtocolHandler::Create(nsISupports* aOuter, + const nsIID& aIID, + void* *aResult) +{ + // Instantiate the service here since that intializes gJarHandler, which we + // use indirectly (via our new JarChannel) in NewChannel. + nsCOMPtr<nsIProtocolHandler> jarInitializer( + do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar")); + AppProtocolHandler* ph = new AppProtocolHandler(); + if (ph == nullptr) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(ph); + nsresult rv = ph->QueryInterface(aIID, aResult); + NS_RELEASE(ph); + return rv; +} + +NS_IMETHODIMP +AppProtocolHandler::GetScheme(nsACString &aResult) +{ + aResult.AssignLiteral("app"); + return NS_OK; +} + +NS_IMETHODIMP +AppProtocolHandler::GetDefaultPort(int32_t *aResult) +{ + // No ports for the app protocol. + *aResult = -1; + return NS_OK; +} + +NS_IMETHODIMP +AppProtocolHandler::GetProtocolFlags(uint32_t *aResult) +{ + *aResult = URI_NOAUTH | + URI_DANGEROUS_TO_LOAD | + URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM; + return NS_OK; +} + +NS_IMETHODIMP +AppProtocolHandler::NewURI(const nsACString &aSpec, + const char *aCharset, // ignore charset info + nsIURI *aBaseURI, + nsIURI **result) +{ + nsresult rv; + nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + url.forget(result); + return NS_OK; +} + +// We map app://ABCDEF/path/to/file.ext to +// jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext +NS_IMETHODIMP +AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult) +{ + NS_ENSURE_ARG_POINTER(aUri); + nsRefPtr<nsJARChannel> channel = new nsJARChannel(); + + nsAutoCString host; + nsresult rv = aUri->GetHost(host); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString fileSpec; + nsCOMPtr<nsIURL> url = do_QueryInterface(aUri); + rv = url->GetFilePath(fileSpec); + NS_ENSURE_SUCCESS(rv, rv); + + mozilla::dom::AppInfo *appInfo; + + if (!mAppInfoCache.Get(host, &appInfo)) { + nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); + if (!appsService) { + return NS_ERROR_FAILURE; + } + + mozilla::AutoSafeJSContext cx; + JS::RootedValue jsInfo(cx); + rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), jsInfo.address()); + if (NS_FAILED(rv) || !jsInfo.isObject()) { + // Return a DummyChannel. + printf_stderr("!! Creating a dummy channel for %s (no appInfo)\n", host.get()); + NS_IF_ADDREF(*aResult = new DummyChannel()); + return NS_OK; + } + + appInfo = new mozilla::dom::AppInfo(); + JSAutoCompartment ac(cx, &jsInfo.toObject()); + if (!appInfo->Init(cx, jsInfo) || appInfo->mPath.IsEmpty()) { + // Return a DummyChannel. + printf_stderr("!! Creating a dummy channel for %s (invalid appInfo)\n", host.get()); + NS_IF_ADDREF(*aResult = new DummyChannel()); + return NS_OK; + } + mAppInfoCache.Put(host, appInfo); + } + + bool noRemote = (appInfo->mIsCoreApp || + XRE_GetProcessType() == GeckoProcessType_Default); + + // In-parent and CoreApps can directly access files, so use jar:file:// + nsAutoCString jarSpec(noRemote ? "jar:file://" + : "jar:remoteopenfile://"); + jarSpec += NS_ConvertUTF16toUTF8(appInfo->mPath) + + NS_LITERAL_CSTRING("/application.zip!") + + fileSpec; + + nsCOMPtr<nsIURI> jarURI; + rv = NS_NewURI(getter_AddRefs(jarURI), + jarSpec, nullptr, nullptr); + NS_ENSURE_SUCCESS(rv, rv); + + rv = channel->Init(jarURI); + NS_ENSURE_SUCCESS(rv, rv); + + rv = channel->SetAppURI(aUri); + NS_ENSURE_SUCCESS(rv, rv); + + rv = channel->SetOriginalURI(aUri); + NS_ENSURE_SUCCESS(rv, rv); + + channel.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval) +{ + // No port allowed for this scheme. + *aRetval = false; + return NS_OK; +} +
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/app/AppProtocolHandler.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set expandtab ts=4 sw=4 sts=4 cin: */ +/* 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 AppProtocolHandler_ +#define AppProtocolHandler_ + +#include "nsIProtocolHandler.h" +#include "nsClassHashtable.h" +#include "mozilla/dom/AppInfoBinding.h" + +class AppProtocolHandler : public nsIProtocolHandler +{ +public: + NS_DECL_ISUPPORTS + + // nsIProtocolHandler methods: + NS_DECL_NSIPROTOCOLHANDLER + + // AppProtocolHandler methods: + AppProtocolHandler(); + virtual ~AppProtocolHandler(); + + // Define a Create method to be used with a factory: + static nsresult Create(nsISupports* aOuter, + const nsIID& aIID, + void* *aResult); + +private: + nsClassHashtable<nsCStringHashKey, mozilla::dom::AppInfo> mAppInfoCache; +}; + +#endif /* AppProtocolHandler_ */
deleted file mode 100644 --- a/netwerk/protocol/app/AppProtocolHandler.js +++ /dev/null @@ -1,197 +0,0 @@ -/* 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/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cu = Components.utils; -const Cr = Components.results; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "appsService", - "@mozilla.org/AppsService;1", - "nsIAppsService"); - -function AppProtocolHandler() { - this._appInfo = []; - this._runningInParent = Cc["@mozilla.org/xre/runtime;1"] - .getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; -} - -AppProtocolHandler.prototype = { - classID: Components.ID("{b7ad6144-d344-4687-b2d0-b6b9dce1f07f}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]), - - scheme: "app", - defaultPort: -1, - // Don't allow loading from other protocols, and only from app:// if webapps is granted - protocolFlags: Ci.nsIProtocolHandler.URI_NOAUTH | - Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD | - Ci.nsIProtocolHandler.URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM, - - getAppInfo: function app_phGetAppInfo(aId) { - - if (!this._appInfo[aId]) { - this._appInfo[aId] = appsService.getAppInfo(aId); - } - return this._appInfo[aId]; - }, - - newURI: function app_phNewURI(aSpec, aOriginCharset, aBaseURI) { - let uri = Cc["@mozilla.org/network/standard-url;1"] - .createInstance(Ci.nsIStandardURL); - uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, -1, aSpec, aOriginCharset, - aBaseURI); - return uri.QueryInterface(Ci.nsIURI); - }, - - newChannel: function app_phNewChannel(aURI) { - // We map app://ABCDEF/path/to/file.ext to - // jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext - let url = aURI.QueryInterface(Ci.nsIURL); - let appId = aURI.host; - let fileSpec = url.filePath; - - // Build a jar channel and masquerade as an app:// URI. - let appInfo = this.getAppInfo(appId); - if (!appInfo) { - // That should not happen, so dump() inconditionnally. - // We create a dummy channel instead of throwing to let the - // downstream user get a 404 error. - dump("!! got no appInfo for " + appId + "\n"); - return new DummyChannel(); - } - - let uri; - if (this._runningInParent || appInfo.isCoreApp) { - // In-parent and CoreApps can directly access files, so use jar:file:// - uri = "jar:file://" + appInfo.path + "/application.zip!" + fileSpec; - } else { - // non-CoreApps in child need to ask parent for file handle, use jar:ipcfile:// - uri = "jar:remoteopenfile://" + appInfo.path + "/application.zip!" + fileSpec; - } - let channel = Services.io.newChannel(uri, null, null); - channel.QueryInterface(Ci.nsIJARChannel).setAppURI(aURI); - channel.QueryInterface(Ci.nsIChannel).originalURI = aURI; - - return channel; - }, - - allowPort: function app_phAllowPort(aPort, aScheme) { - return false; - } -}; - -/** - * This dummy channel implementation only provides enough functionality - * to return a fake 404 error when the caller asks for an app:// URL - * containing an unknown appId. - */ -function DummyChannel() { - this.originalURI = Services.io.newURI("app://unknown/nothing.html", null, null); - this.URI = Services.io.newURI("app://unknown/nothing.html", null, null); -} - -DummyChannel.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequest, - Ci.nsIChannel, - Ci.nsIJARChannel]), - - // nsIRequest - name: "dummy_app_channel", - - isPending: function dc_isPending() { - return this._pending; - }, - - status: Cr.NS_ERROR_FILE_NOT_FOUND, - - cancel: function dc_cancel() { - }, - - suspend: function dc_suspend() { - this._suspendCount++; - }, - - resume: function dc_resume() { - if (this._suspendCount <= 0) - throw Cr.NS_ERROR_UNEXPECTED; - - if (--this._suspendCount == 0 && this._pending) { - this._dispatch(); - } - }, - - loadGroup: null, - loadFlags: Ci.nsIRequest.LOAD_NORMAL, - - // nsIChannel - owner: null, - notificationCallbacks: null, - securityInfo: null, - contentType: null, - contentCharset: null, - contentLength: 0, - contentDisposition: Ci.nsIChannel.DISPOSITION_INLINE, - contentDispositionFilename: "", - - _pending: false, - _suspendCount: 0, - _listener: null, - _context: null, - - open: function dc_open() { - return Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - - _dispatch: function dc_dispatch() { - let request = this; - - Services.tm.currentThread.dispatch( - { - run: function dc_run() { - request._listener.onStartRequest(request, request._context); - request._listener.onStopRequest(request, request._context, - Cr.NS_ERROR_FILE_NOT_FOUND); - if (request.loadGroup) { - request.loadGroup.removeRequest(request, request._context, - Cr.NS_ERROR_FILE_NOT_FOUND); - } - request._pending = false; - request.notificationCallbacks = null; - request._listener = null; - request._context = null; - } - }, - Ci.nsIThread.DISPATCH_NORMAL); - }, - - asyncOpen: function dc_asyncopenfunction(aListener, aContext) { - if (this.loadGroup) { - this.loadGroup.addRequest(this, aContext); - } - - this._listener = aListener; - this._context = aContext; - this._pending = true; - - if (!this._suspended) { - this._dispatch(); - } - }, - - // nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into - // a 404 error. - isUnsafe: false, - - setAppURI: function(aURI) { - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AppProtocolHandler]);
deleted file mode 100644 --- a/netwerk/protocol/app/AppProtocolHandler.manifest +++ /dev/null @@ -1,3 +0,0 @@ -# AppProtocolHander.js -component {b7ad6144-d344-4687-b2d0-b6b9dce1f07f} AppProtocolHandler.js -contract @mozilla.org/network/protocol;1?name=app {b7ad6144-d344-4687-b2d0-b6b9dce1f07f}
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/app/Makefile.in @@ -0,0 +1,9 @@ +# +# 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/. + +LOCAL_INCLUDES = \ + -I$(srcdir)/../../base/src \ + -I$(srcdir)/../../../modules/libjar \ + $(NULL)
--- a/netwerk/protocol/app/moz.build +++ b/netwerk/protocol/app/moz.build @@ -1,10 +1,18 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. -EXTRA_COMPONENTS += [ - 'AppProtocolHandler.js', - 'AppProtocolHandler.manifest', +MODULE = 'necko' + +SOURCES += [ + 'AppProtocolHandler.cpp', ] + +LIBRARY_NAME = 'nkapp_s' + +FAIL_ON_WARNINGS = True + +LIBXUL_LIBRARY = True +
--- a/netwerk/protocol/http/HttpDataUsage.js +++ b/netwerk/protocol/http/HttpDataUsage.js @@ -30,18 +30,17 @@ var gDataUsage; function HttpDataUsage() {} HttpDataUsage.prototype = { classID: Components.ID("{6d72bfca-2747-4859-887f-6f06d4ce6787}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), contractID: "@mozilla.org/network/HttpDataUsage;1", _isIdleObserver: false, _locked : false, - _do_telemetry : false, - _idle_timeout : 60 * 3, + _idle_timeout : 15, _quanta : 86400000, // per day _logtime : new Date(), _ethernetRead : 0, _ethernetWritten : 0, _cellRead : 0, _cellWritten : 0, @@ -69,34 +68,33 @@ HttpDataUsage.prototype = { // this isn't important enough to worry about getting a // runtime telemetry config change for if (!enabled) return; if (this._dataUsage == null) return; + Services.obs.addObserver(this, "quit-application", false); idleService.addIdleObserver(this, this._idle_timeout); this._isIdleObserver = true; }, shutdown: function shutdown() { - if (this._isIdleObserver) + if (this._isIdleObserver) { idleService.removeIdleObserver(this, this._idle_timeout); + Services.obs.removeObserver(this, "quit-application"); + } this._isIdleObserver = false; }, sUpdateStats2: function sUpdateStats2(stream, result) { gDataUsage.updateStats2(stream, result); }, - sGatherTelemetry2: function sGatherTelemetry2(stream, result) { - gDataUsage.gatherTelemetry2(stream, result); - }, - readCounters: function readCounters(stream, result) { if (Components.isSuccessCode(result)) { let count = stream.available(); let data = NetUtil.readInputStreamToString(stream, count); var list = data.split(","); if (list.length == 5) { this._logtime = new Date(Number(list[0])); this._ethernetRead = Number(list[1]); @@ -108,17 +106,16 @@ HttpDataUsage.prototype = { this._ethernetRead += this._dataUsage.ethernetBytesRead; this._ethernetWritten += this._dataUsage.ethernetBytesWritten; this._cellRead += this._dataUsage.cellBytesRead; this._cellWritten += this._dataUsage.cellBytesWritten; this._dataUsage.resetHttpDataUsage(); }, - // writeCounters also releases the lock writeCounters: function writeCounters() { var dataout = this._logtime.getTime().toString() + "," + this._ethernetRead.toString() + "," + this._ethernetWritten.toString() + "," + this._cellRead.toString() + "," + this._cellWritten.toString() + "\n"; var buffer = new this._pipe(true, false, 4096, 1, null); @@ -127,27 +124,25 @@ HttpDataUsage.prototype = { var fileOut = new this._outputStream(this._dataFile, -1, -1, 0); NetUtil.asyncCopy(buffer.inputStream, fileOut, function (result) { gDataUsage.finishedWriting(); }); }, updateStats2: function updateStats2(stream, result) { this.readCounters(stream, result); - this.writeCounters(); + this.submitTelemetry(); }, - gatherTelemetry2: function gatherTelemetry2(stream, result) { - this.readCounters(stream, result); - + submitTelemetry: function submitTelemetry() { var now = new Date(); var elapsed = now.getTime() - this._logtime.getTime(); - // make sure we have at least 1 day of data + // make sure we have at least 1 day of data.. if not just write new data out if (elapsed < this._quanta) { - this.finishedWriting(); + this.writeCounters(); return; } var days = elapsed / this._quanta; var eInPerQuanta = Math.floor(this._ethernetRead / days); var eOutPerQuanta = Math.floor(this._ethernetWritten / days); var cInPerQuanta = Math.floor(this._cellRead / days); var cOutPerQuanta = Math.floor(this._cellWritten / days); @@ -166,57 +161,42 @@ HttpDataUsage.prototype = { elapsed -= this._quanta; this._ethernetRead -= eInPerQuanta; this._ethernetWritten -= eOutPerQuanta; this._cellRead -= cInPerQuanta; this._cellWritten -= cOutPerQuanta; } this._logtime = new Date(now.getTime() - elapsed); - + + // need to write back the decremented counters this.writeCounters(); }, finishedWriting : function finishedWriting() { - this._locked = false; - if (this._do_telemetry) { - this._do_telemetry = false; - this.gatherTelemetry(); - } + this._locked = false; // all done }, updateStats: function updateStats() { if (this._locked) return; this._locked = true; NetUtil.asyncFetch(this._dataFile, this.sUpdateStats2); }, - gatherTelemetry: function gatherTelemetry() { - if (this._locked) - return; // oh well, maybe next time - this._locked = true; - - NetUtil.asyncFetch(this._dataFile, this.sGatherTelemetry2); - }, - observe: function (aSubject, aTopic, aData) { switch (aTopic) { case "profile-after-change": this.setup(); break; - case "gather-telemetry": - this._do_telemetry = true; - this.updateStats(); - break; case "idle": this.updateStats(); break; - case "profile-change-net-teardown": + case "quit-application": + this.updateStats(); this.shutdown(); break; } }, - }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HttpDataUsage]);
--- a/parser/htmlparser/src/nsScanner.cpp +++ b/parser/htmlparser/src/nsScanner.cpp @@ -1,16 +1,18 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sw=2 et tw=78: */ /* 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/. */ //#define __INCREMENTAL 1 +#include "mozilla/DebugOnly.h" + #include "nsScanner.h" #include "nsDebug.h" #include "nsIServiceManager.h" #include "nsICharsetConverterManager.h" #include "nsReadableUtils.h" #include "nsIInputStream.h" #include "nsIFile.h" #include "nsNetUtil.h" @@ -113,37 +115,34 @@ nsScanner::nsScanner(nsString& aFilename mHasInvalidCharacter = false; mReplacementCharacter = PRUnichar(0x0); // XML defaults to UTF-8 and about:blank is UTF-8, too. SetDocumentCharset(NS_LITERAL_CSTRING("UTF-8"), kCharsetFromDocTypeDefault); } nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , int32_t aSource) { - if (aSource < mCharsetSource) // priority is lower the the current one , just + if (aSource < mCharsetSource) // priority is lower than the current one return NS_OK; + mCharsetSource = aSource; + nsCString charsetName; - bool valid = EncodingUtils::FindEncodingForLabel(aCharset, charsetName); + mozilla::DebugOnly<bool> valid = + EncodingUtils::FindEncodingForLabel(aCharset, charsetName); MOZ_ASSERT(valid, "Should never call with a bogus aCharset."); - if (!mCharset.IsEmpty()) - { - if (charsetName.Equals(mCharset)) - { - mCharsetSource = aSource; - return NS_OK; // no difference, don't change it - } + + if (!mCharset.IsEmpty() && charsetName.Equals(mCharset)) { + return NS_OK; // no difference, don't change it } // different, need to change it mCharset.Assign(charsetName); - mCharsetSource = aSource; - NS_ASSERTION(nsParser::GetCharsetConverterManager(), "Must have the charset converter manager!"); nsresult res = nsParser::GetCharsetConverterManager()-> GetUnicodeDecoderRaw(mCharset.get(), getter_AddRefs(mUnicodeDecoder)); if (NS_SUCCEEDED(res) && mUnicodeDecoder) { // We need to detect conversion error of character to support XML
--- a/python/mozbuild/mozbuild/backend/base.py +++ b/python/mozbuild/mozbuild/backend/base.py @@ -4,16 +4,17 @@ from __future__ import unicode_literals from abc import ( ABCMeta, abstractmethod, ) +import errno import os import sys import time from contextlib import contextmanager from mach.mixin.logging import LoggingMixin @@ -33,28 +34,28 @@ class BackendConsumeSummary(object): """ def __init__(self): # How many moz.build files were read. This includes included files. self.mozbuild_count = 0 # The number of derived objects from the read moz.build files. self.object_count = 0 - # The number of backend files managed. - self.managed_count = 0 - # The number of backend files created. self.created_count = 0 # The number of backend files updated. self.updated_count = 0 # The number of unchanged backend files. self.unchanged_count = 0 + # The number of deleted backend files. + self.deleted_count = 0 + # The total wall time this backend spent consuming objects. If # the iterable passed into consume() is a generator, this includes the # time spent to read moz.build files. self.wall_time = 0.0 # CPU time spent by during the interval captured by wall_time. self.cpu_time = 0.0 @@ -118,16 +119,27 @@ class BuildBackend(LoggingMixin): self.environment = environment self.summary = BackendConsumeSummary() # Files whose modification should cause a new read and backend # generation. self.backend_input_files = set() + # Files generated by the backend. + self._backend_output_files = set() + + # Previously generated files. + self._backend_output_list_file = os.path.join(environment.topobjdir, + 'backend.%s' % self.__class__.__name__) + self._backend_output_list = set() + if os.path.exists(self._backend_output_list_file): + self._backend_output_list.update(open(self._backend_output_list_file) \ + .read().split('\n')) + # Pull in Python files for this package as dependencies so backend # regeneration occurs if any of the code affecting it changes. for name, module in sys.modules.items(): if not module or not name.startswith('mozbuild'): continue p = module.__file__ @@ -196,28 +208,44 @@ class BuildBackend(LoggingMixin): if isinstance(obj, SandboxDerived): self.backend_input_files |= obj.sandbox_all_paths if isinstance(obj, ReaderSummary): self.summary.mozbuild_count = obj.total_file_count self.summary.mozbuild_execution_time = obj.total_execution_time - # Write out a file indicating when this backend was last generated. - age_file = os.path.join(self.environment.topobjdir, - 'backend.%s.built' % self.__class__.__name__) - if self.summary.updated_count or self.summary.created_count or \ - not os.path.exists(age_file): - with open(age_file, 'a'): - os.utime(age_file, None) - finished_start = time.time() self.consume_finished() backend_time += time.time() - finished_start + # Purge backend files created in previous run, but not created anymore + delete_files = self._backend_output_list - self._backend_output_files + for path in delete_files: + try: + os.unlink(os.path.join(self.environment.topobjdir, path)) + self.summary.deleted_count += 1 + except OSError: + pass + # Remove now empty directories + for dir in set(os.path.dirname(d) for d in delete_files): + try: + os.removedirs(dir) + except OSError: + pass + + # Write out the list of backend files generated, if it changed. + if self.summary.deleted_count or self.summary.created_count or \ + not os.path.exists(self._backend_output_list_file): + with open(self._backend_output_list_file, 'w') as fh: + fh.write('\n'.join(sorted(self._backend_output_files))) + elif self.summary.updated_count: + with open(self._backend_output_list_file, 'a'): + os.utime(self._backend_output_list_file, None) + self.summary.cpu_time = time.clock() - cpu_start self.summary.wall_time = time.time() - time_start self.summary.backend_execution_time = backend_time self.summary.other_time = self.summary.wall_time - \ self.summary.mozbuild_execution_time - \ self.summary.backend_execution_time return self.summary @@ -229,30 +257,43 @@ class BuildBackend(LoggingMixin): This is the main method used by child classes to react to build metadata. """ def consume_finished(self): """Called when consume() has completed handling all objects.""" @contextmanager - def _write_file(self, path): + def _write_file(self, path=None, fh=None): """Context manager to write a file. This is a glorified wrapper around FileAvoidWrite with integration to update the BackendConsumeSummary on this instance. Example usage: with self._write_file('foo.txt') as fh: fh.write('hello world') """ - fh = FileAvoidWrite(path) + if path is not None: + assert fh is None + fh = FileAvoidWrite(path) + else: + assert fh is not None + + dirname = os.path.dirname(fh.name) + try: + os.makedirs(dirname) + except OSError as error: + if error.errno != errno.EEXIST: + raise + yield fh + self._backend_output_files.add(os.path.relpath(fh.name, self.environment.topobjdir)) existed, updated = fh.close() if not existed: self.summary.created_count += 1 elif updated: self.summary.updated_count += 1 else: self.summary.unchanged_count += 1
--- a/python/mozbuild/mozbuild/backend/configenvironment.py +++ b/python/mozbuild/mozbuild/backend/configenvironment.py @@ -190,87 +190,86 @@ class ConfigEnvironment(object): def get_input(self, file): '''Returns the input file path in the source tree that can be used to create the given config file or header. ''' assert(isinstance(file, basestring)) return os.path.normpath(os.path.join(self.topsrcdir, "%s.in" % relpath(file, self.topobjdir))) - def create_config_file(self, path, extra=None): + def create_config_file(self, output, extra=None): '''Creates the given config file. A config file is generated by taking the corresponding source file and replacing occurences of "@VAR@" by the value corresponding to "VAR" in the substs dict. Additional substs are defined according to the file being treated: "srcdir" for its the path to its source directory "relativesrcdir" for its source directory relative to the top "DEPTH" for the path to the top object directory ''' + path = output.name if os.path.basename(path) == 'Makefile': - return self.create_makefile(path, extra=extra) - pp = self._get_preprocessor(path, extra) + return self.create_makefile(output, extra=extra) + pp = self._get_preprocessor(output, extra) pp.do_include(self.get_input(path)) - return pp.out.close() - def create_makefile(self, path, stub=False, extra=None): + def create_makefile(self, output, stub=False, extra=None): '''Creates the given makefile. Makefiles are treated the same as config files, but some additional header and footer is added to the output. When the stub argument is True, no source file is used, and a stub makefile with the default header and footer only is created. ''' - pp = self._get_preprocessor(path, extra) + pp = self._get_preprocessor(output, extra) pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n'); pp.handleLine('DEPTH := @DEPTH@\n') pp.handleLine('topsrcdir := @top_srcdir@\n') pp.handleLine('srcdir := @srcdir@\n') pp.handleLine('VPATH := @srcdir@\n') pp.handleLine('relativesrcdir := @relativesrcdir@\n') pp.handleLine('include $(DEPTH)/config/autoconf.mk\n') if not stub: - pp.do_include(self.get_input(path)) + pp.do_include(self.get_input(output.name)) # Empty line to avoid failures when last line in Makefile.in ends # with a backslash. pp.handleLine('\n') pp.handleLine('include $(topsrcdir)/config/recurse.mk\n') - return pp.out.close() - def _get_preprocessor(self, path, extra): + def _get_preprocessor(self, output, extra): '''Returns a preprocessor for use by create_config_file and create_makefile. ''' + path = output.name pp = Preprocessor() pp.context.update(self.substs) pp.context.update(top_srcdir = self.get_top_srcdir(path)) pp.context.update(srcdir = self.get_file_srcdir(path)) pp.context.update(relativesrcdir = self.get_relative_srcdir(path)) pp.context.update(DEPTH = self.get_depth(path)) if extra: pp.context.update(extra) pp.do_filter('attemptSubstitution') pp.setMarker(None) - pp.out = FileAvoidWrite(path) + pp.out = output return pp - def create_config_header(self, path): + def create_config_header(self, output): '''Creates the given config header. A config header is generated by taking the corresponding source file and replacing some #define/#undef occurences: "#undef NAME" is turned into "#define NAME VALUE" "#define NAME" is unchanged "#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE" "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */" Whitespaces are preserved. ''' - with open(self.get_input(path), 'rU') as input: - ensureParentDir(path) - output = FileAvoidWrite(path) + with open(self.get_input(output.name), 'rU') as input: + ensureParentDir(output.name) r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U) for l in input: m = r.match(l) if m: cmd = m.group('cmd') name = m.group('name') value = m.group('value') if name: @@ -278,9 +277,8 @@ class ConfigEnvironment(object): if cmd == 'define' and value: l = l[:m.start('value')] + str(self.defines[name]) + l[m.end('value'):] elif cmd == 'undef': l = l[:m.start('cmd')] + 'define' + l[m.end('cmd'):m.end('name')] + ' ' + str(self.defines[name]) + l[m.end('name'):] elif cmd == 'undef': l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):] output.write(l) - return output.close()
--- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -1,15 +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/. from __future__ import unicode_literals -import errno import itertools import logging import os import re import types from collections import namedtuple @@ -24,16 +23,17 @@ from .common import CommonBackend from ..frontend.data import ( ConfigFileSubstitution, Defines, DirectoryTraversal, Exports, GeneratedEventWebIDLFile, GeneratedInclude, GeneratedWebIDLFile, + HeaderFileSubstitution, InstallationTarget, IPDLFile, JavaJarData, LocalInclude, PreprocessedTestWebIDLFile, PreprocessedWebIDLFile, Program, SandboxDerived, @@ -45,17 +45,16 @@ from ..frontend.data import ( WebIDLFile, ) from ..util import ( ensureParentDir, FileAvoidWrite, ) from ..makeutil import Makefile - class BackendMakeFile(object): """Represents a generated backend.mk file. This is both a wrapper around a file handle as well as a container that holds accumulated state. It's worth taking a moment to explain the make dependencies. The generated backend.mk as well as the Makefile.in (if it exists) are in the @@ -77,40 +76,34 @@ class BackendMakeFile(object): actually change. We use FileAvoidWrite to accomplish this. """ def __init__(self, srcdir, objdir, environment): self.srcdir = srcdir self.objdir = objdir self.relobjdir = objdir[len(environment.topobjdir) + 1:] self.environment = environment - self.path = os.path.join(objdir, 'backend.mk') + self.name = os.path.join(objdir, 'backend.mk') # XPIDLFiles attached to this file. self.idls = [] self.xpt_name = None - self.fh = FileAvoidWrite(self.path) + self.fh = FileAvoidWrite(self.name) self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n') self.fh.write('\n') self.fh.write('MOZBUILD_DERIVED := 1\n') - # The global rule to incur backend generation generates Makefiles. - self.fh.write('NO_MAKEFILE_RULE := 1\n') - - # We can't blindly have a SUBMAKEFILES rule because some of the - # Makefile may not have a corresponding Makefile.in. For the case - # where a new directory is added, the mozbuild file referencing that - # new directory will need updated. This will cause a full backend - # scan and build, installing the new Makefile. - self.fh.write('NO_SUBMAKEFILES_RULE := 1\n') - def write(self, buf): self.fh.write(buf) + # For compatibility with makeutil.Makefile + def add_statement(self, stmt): + self.write('%s\n' % stmt) + def close(self): if self.xpt_name: self.fh.write('XPT_NAME := %s\n' % self.xpt_name) # We just recompile all xpidls because it's easier and less error # prone. self.fh.write('NONRECURSIVE_TARGETS += export\n') self.fh.write('NONRECURSIVE_TARGETS_export += xpidl\n') @@ -274,19 +267,23 @@ class RecursiveMakeBackend(CommonBackend self._webidl_sources = set() self._generated_events_webidl_sources = set() self._test_webidl_sources = set() self._preprocessed_test_webidl_sources = set() self._preprocessed_webidl_sources = set() self._generated_webidl_sources = set() def detailed(summary): - return '{:d} total backend files. {:d} created; {:d} updated; {:d} unchanged'.format( - summary.managed_count, summary.created_count, + s = '{:d} total backend files. {:d} created; {:d} updated; {:d} unchanged'.format( + summary.created_count + summary.updated_count + + summary.unchanged_count, summary.created_count, summary.updated_count, summary.unchanged_count) + if summary.deleted_count: + s+= '; {:d} deleted'.format(summary.deleted_count) + return s # This is a little kludgy and could be improved with a better API. self.summary.backend_detailed_summary = types.MethodType(detailed, self.summary) self._test_manifests = {} self.backend_input_files.add(os.path.join(self.environment.topobjdir, @@ -315,51 +312,60 @@ class RecursiveMakeBackend(CommonBackend derecurse = self.environment.substs.get('MOZ_PSEUDO_DERECURSE', '').split(',') self._parallel_export = False self._no_skip = False if derecurse != ['']: self._parallel_export = 'no-parallel-export' not in derecurse self._no_skip = 'no-skip' in derecurse - def _update_from_avoid_write(self, result): - existed, updated = result - - if not existed: - self.summary.created_count += 1 - elif updated: - self.summary.updated_count += 1 - else: - self.summary.unchanged_count += 1 - def consume_object(self, obj): """Write out build files necessary to build with recursive make.""" CommonBackend.consume_object(self, obj) if not isinstance(obj, SandboxDerived): return - backend_file = self._backend_files.get(obj.srcdir, - BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj))) + if obj.srcdir not in self._backend_files: + self._backend_files[obj.srcdir] = \ + BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj)) + backend_file = self._backend_files[obj.srcdir] if isinstance(obj, DirectoryTraversal): self._process_directory_traversal(obj, backend_file) elif isinstance(obj, ConfigFileSubstitution): - self._update_from_avoid_write( - backend_file.environment.create_config_file(obj.output_path)) + with self._write_file(obj.output_path) as fh: + backend_file.environment.create_config_file(fh) self.backend_input_files.add(obj.input_path) - self.summary.managed_count += 1 + elif isinstance(obj, HeaderFileSubstitution): + with self._write_file(obj.output_path) as fh: + backend_file.environment.create_config_header(fh) + self.backend_input_files.add(obj.input_path) elif isinstance(obj, XPIDLFile): backend_file.idls.append(obj) backend_file.xpt_name = '%s.xpt' % obj.module elif isinstance(obj, VariablePassthru): + unified_suffixes = dict( + UNIFIED_CSRCS='c', + UNIFIED_CPPSRCS='cpp', + ) # Sorted so output is consistent and we don't bump mtimes. for k, v in sorted(obj.variables.items()): - if isinstance(v, list): + if k in unified_suffixes.keys(): + self._add_unified_build_rules(backend_file, v, + backend_file.objdir, + unified_prefix='Unified_%s_%s' % + (unified_suffixes[k], + backend_file.relobjdir.replace('/', '_')), + unified_suffix=unified_suffixes[k], + unified_files_makefile_variable=k, + include_curdir_build_rules=False) + backend_file.write('%s += $(%s)\n' % (k[len('UNIFIED_'):], k)) + elif isinstance(v, list): for item in v: backend_file.write('%s += %s\n' % (k, item)) elif isinstance(v, bool): if v: backend_file.write('%s := 1\n' % k) else: backend_file.write('%s := %s\n' % (k, v)) @@ -539,38 +545,38 @@ class RecursiveMakeBackend(CommonBackend else: # Output the list of filtered directories for each tier/subtier # pair. root_mk.add_statement('%s_subtier_%s := %s' % (tier, subtier, ' '.join(subtier_dirs))) root_mk.add_statement('$(call include_deps,root-deps.mk)') - root = FileAvoidWrite( - os.path.join(self.environment.topobjdir, 'root.mk')) - root_deps = FileAvoidWrite( - os.path.join(self.environment.topobjdir, 'root-deps.mk')) - root_mk.dump(root, removal_guard=False) - root_deps_mk.dump(root_deps, removal_guard=False) - self._update_from_avoid_write(root.close()) - self._update_from_avoid_write(root_deps.close()) + with self._write_file( + os.path.join(self.environment.topobjdir, 'root.mk')) as root: + root_mk.dump(root, removal_guard=False) + + with self._write_file( + os.path.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps: + root_deps_mk.dump(root_deps, removal_guard=False) def _add_unified_build_rules(self, makefile, files, output_directory, unified_prefix='Unified', + unified_suffix='cpp', extra_dependencies=[], unified_files_makefile_variable='unified_files', include_curdir_build_rules=True): files_per_unified_file = 16 explanation = "\n" \ "# We build files in 'unified' mode by including several files\n" \ "# together into a single source file. This cuts down on\n" \ "# compilation times and debug information size. %d was chosen as\n" \ "# a reasonable compromise between clobber rebuild time, incremental\n" \ - "# rebuild time, and compiler memory usage.\n" % files_per_unified_file + "# rebuild time, and compiler memory usage." % files_per_unified_file makefile.add_statement(explanation) def unified_files(): "Return an iterator of (unified_filename, source_filenames) tuples." # Our last returned list of source filenames may be short, and we # don't want the fill value inserted by izip_longest to be an # issue. So we do a little dance to filter it out ourselves. dummy_fill_value = ("dummy",) @@ -582,103 +588,89 @@ class RecursiveMakeBackend(CommonBackend def grouper(n, iterable): "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return itertools.izip_longest(fillvalue=dummy_fill_value, *args) for i, unified_group in enumerate(grouper(files_per_unified_file, sorted(files))): just_the_filenames = list(filter_out_dummy(unified_group)) - yield '%s%d.cpp' % (unified_prefix, i), just_the_filenames + yield '%s%d.%s' % (unified_prefix, i, unified_suffix), just_the_filenames all_sources = ' '.join(source for source, _ in unified_files()) - makefile.add_statement('%s := %s\n' % (unified_files_makefile_variable, + makefile.add_statement('%s := %s' % (unified_files_makefile_variable, all_sources)) - regen_cmds = ['for f in $(filter %.cpp,$^); do echo "#include \\"$$f\\""; done > $@'] for unified_file, source_filenames in unified_files(): - rule = makefile.create_rule([unified_file]) - rule.add_dependencies(extra_dependencies + source_filenames) - rule.add_commands(regen_cmds) + if extra_dependencies: + rule = makefile.create_rule([unified_file]) + rule.add_dependencies(extra_dependencies) # The rule we just defined is only for cases where the cpp files get # blown away and we need to regenerate them. The rule doesn't correctly # handle source files being added/removed/renamed. Therefore, we # generate them here also to make sure everything's up-to-date. - with FileAvoidWrite(os.path.join(output_directory, unified_file)) as f: + with self._write_file(os.path.join(output_directory, unified_file)) as f: f.write('\n'.join(['#include "%s"' % s for s in source_filenames])) if include_curdir_build_rules: makefile.add_statement('\n' '# Make sometimes gets confused between "foo" and "$(CURDIR)/foo".\n' '# Help it out by explicitly specifiying dependencies.') makefile.add_statement('all_absolute_unified_files := \\\n' ' $(addprefix $(CURDIR)/,$(%s))' % unified_files_makefile_variable) rule = makefile.create_rule(['$(all_absolute_unified_files)']) rule.add_dependencies(['$(CURDIR)/%: %']) def consume_finished(self): CommonBackend.consume_finished(self) for srcdir in sorted(self._backend_files.keys()): - bf = self._backend_files[srcdir] - - if not os.path.exists(bf.objdir): - try: - os.makedirs(bf.objdir) - except OSError as error: - if error.errno != errno.EEXIST: - raise + with self._write_file(fh=self._backend_files[srcdir]) as bf: + makefile_in = os.path.join(srcdir, 'Makefile.in') + makefile = os.path.join(bf.objdir, 'Makefile') - makefile_in = os.path.join(srcdir, 'Makefile.in') - makefile = os.path.join(bf.objdir, 'Makefile') - - # If Makefile.in exists, use it as a template. Otherwise, create a - # stub. - stub = not os.path.exists(makefile_in) - if not stub: - self.log(logging.DEBUG, 'substitute_makefile', - {'path': makefile}, 'Substituting makefile: {path}') + # If Makefile.in exists, use it as a template. Otherwise, + # create a stub. + stub = not os.path.exists(makefile_in) + if not stub: + self.log(logging.DEBUG, 'substitute_makefile', + {'path': makefile}, 'Substituting makefile: {path}') - # Adding the Makefile.in here has the desired side-effect that - # if the Makefile.in disappears, this will force moz.build - # traversal. This means that when we remove empty Makefile.in - # files, the old file will get replaced with the autogenerated - # one automatically. - self.backend_input_files.add(makefile_in) + # Adding the Makefile.in here has the desired side-effect + # that if the Makefile.in disappears, this will force + # moz.build traversal. This means that when we remove empty + # Makefile.in files, the old file will get replaced with + # the autogenerated one automatically. + self.backend_input_files.add(makefile_in) - for skiplist in self._may_skip.values(): - if bf.relobjdir in skiplist: - skiplist.remove(bf.relobjdir) - else: - self.log(logging.DEBUG, 'stub_makefile', - {'path': makefile}, 'Creating stub Makefile: {path}') + for skiplist in self._may_skip.values(): + if bf.relobjdir in skiplist: + skiplist.remove(bf.relobjdir) + else: + self.log(logging.DEBUG, 'stub_makefile', + {'path': makefile}, 'Creating stub Makefile: {path}') - # Can't skip directories with a jar.mn for the 'libs' tier. - if bf.relobjdir in self._may_skip['libs'] and \ - os.path.exists(os.path.join(srcdir, 'jar.mn')): - self._may_skip['libs'].remove(bf.relobjdir) + # Can't skip directories with a jar.mn for the 'libs' tier. + if bf.relobjdir in self._may_skip['libs'] and \ + os.path.exists(os.path.join(srcdir, 'jar.mn')): + self._may_skip['libs'].remove(bf.relobjdir) - self._update_from_avoid_write( - bf.environment.create_makefile(makefile, stub=stub)) - self.summary.managed_count += 1 - - self._update_from_avoid_write(bf.close()) - self.summary.managed_count += 1 + with self._write_file(makefile) as fh: + bf.environment.create_makefile(fh, stub=stub) self._fill_root_mk() # Write out a master list of all IPDL source files. ipdl_dir = os.path.join(self.environment.topobjdir, 'ipc', 'ipdl') - ipdls = FileAvoidWrite(os.path.join(ipdl_dir, 'ipdlsrcs.mk')) mk = mozmakeutil.Makefile() sorted_ipdl_sources = list(sorted(self._ipdl_sources)) - mk.add_statement('ALL_IPDLSRCS := %s\n' % ' '.join(sorted_ipdl_sources)) + mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources)) def files_from(ipdl): base = os.path.basename(ipdl) root, ext = os.path.splitext(base) # Both .ipdl and .ipdlh become .cpp files files = ['%s.cpp' % root] if ext == '.ipdl': @@ -687,33 +679,30 @@ class RecursiveMakeBackend(CommonBackend '%sParent.cpp' % root]) return files ipdl_cppsrcs = list(itertools.chain(*[files_from(p) for p in sorted_ipdl_sources])) self._add_unified_build_rules(mk, ipdl_cppsrcs, ipdl_dir, unified_prefix='UnifiedProtocols', unified_files_makefile_variable='CPPSRCS') - mk.add_statement('IPDLDIRS := %s\n' % ' '.join(sorted(set(os.path.dirname(p) + mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(os.path.dirname(p) for p in self._ipdl_sources)))) - mk.dump(ipdls, removal_guard=False) - - self._update_from_avoid_write(ipdls.close()) - self.summary.managed_count += 1 + with self._write_file(os.path.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls: + mk.dump(ipdls, removal_guard=False) # Write out master lists of WebIDL source files. bindings_dir = os.path.join(self.environment.topobjdir, 'dom', 'bindings') - webidls = FileAvoidWrite(os.path.join(bindings_dir, 'webidlsrcs.mk')) mk = mozmakeutil.Makefile() def write_var(variable, sources): files = [os.path.basename(f) for f in sorted(sources)] - mk.add_statement('%s += %s\n' % (variable, ' '.join(files))) + mk.add_statement('%s += %s' % (variable, ' '.join(files))) write_var('webidl_files', self._webidl_sources) write_var('generated_events_webidl_files', self._generated_events_webidl_sources) write_var('test_webidl_files', self._test_webidl_sources) write_var('preprocessed_test_webidl_files', self._preprocessed_test_webidl_sources) write_var('generated_webidl_files', self._generated_webidl_sources) write_var('preprocessed_webidl_files', self._preprocessed_webidl_sources) all_webidl_files = itertools.chain(iter(self._webidl_sources), @@ -725,38 +714,31 @@ class RecursiveMakeBackend(CommonBackend self._add_unified_build_rules(mk, all_webidl_sources, bindings_dir, unified_prefix='UnifiedBindings', unified_files_makefile_variable='unified_binding_cpp_files') # Assume that Somebody Else has responsibility for correctly # specifying removal dependencies for |all_webidl_sources|. - mk.dump(webidls, removal_guard=False) - - self._update_from_avoid_write(webidls.close()) - self.summary.managed_count += 1 + with self._write_file(os.path.join(bindings_dir, 'webidlsrcs.mk')) as webidls: + mk.dump(webidls, removal_guard=False) # Write out a dependency file used to determine whether a config.status # re-run is needed. - backend_built_path = os.path.join(self.environment.topobjdir, - 'backend.%s.built' % self.__class__.__name__).replace(os.sep, '/') - backend_deps = FileAvoidWrite('%s.pp' % backend_built_path) inputs = sorted(p.replace(os.sep, '/') for p in self.backend_input_files) # We need to use $(DEPTH) so the target here matches what's in # rules.mk. If they are different, the dependencies don't get pulled in # properly. - backend_deps.write('$(DEPTH)/backend.RecursiveMakeBackend.built: %s\n' % - ' '.join(inputs)) - for path in inputs: - backend_deps.write('%s:\n' % path) - - self._update_from_avoid_write(backend_deps.close()) - self.summary.managed_count += 1 + with self._write_file('%s.pp' % self._backend_output_list_file) as backend_deps: + backend_deps.write('$(DEPTH)/backend.%s: %s\n' % + (self.__class__.__name__, ' '.join(inputs))) + for path in inputs: + backend_deps.write('%s:\n' % path) # Make the master test manifest files. for flavor, t in self._test_manifests.items(): install_prefix, manifests = t manifest_stem = os.path.join(install_prefix, '%s.ini' % flavor) self._write_master_test_manifest(os.path.join( self.environment.topobjdir, '_tests', manifest_stem), manifests) @@ -953,22 +935,21 @@ class RecursiveMakeBackend(CommonBackend # Create dependency for output header so we force regeneration if the # header was deleted. This ideally should not be necessary. However, # some processes (such as PGO at the time this was implemented) wipe # out dist/include without regard to our install manifests. out_path = os.path.join(self.environment.topobjdir, 'config', 'makefiles', 'xpidl', 'Makefile') - result = self.environment.create_config_file(out_path, extra=dict( - xpidl_rules='\n'.join(rules), - xpidl_modules=' '.join(xpt_modules), - )) - self._update_from_avoid_write(result) - self.summary.managed_count += 1 + with self._write_file(out_path) as fh: + self.environment.create_config_file(fh, extra=dict( + xpidl_rules='\n'.join(rules), + xpidl_modules=' '.join(xpt_modules), + )) # The Makefile can't regenerate itself because of custom substitution. # We need to list it here to ensure changes cause regeneration. self.backend_input_files.add(os.path.join(self.environment.topsrcdir, 'config', 'makefiles', 'xpidl', 'Makefile.in')) def _process_program(self, program, backend_file): backend_file.write('PROGRAM = %s\n' % program) @@ -1038,24 +1019,20 @@ class RecursiveMakeBackend(CommonBackend # We have a purger for the manifests themselves to ensure legacy # manifests are deleted. purger = FilePurger() for k, manifest in manifests.items(): purger.add(k) - fh = FileAvoidWrite(os.path.join(man_dir, k)) - manifest.write(fileobj=fh) - self._update_from_avoid_write(fh.close()) + with self._write_file(os.path.join(man_dir, k)) as fh: + manifest.write(fileobj=fh) purger.purge(man_dir) def _write_master_test_manifest(self, path, manifests): - master = FileAvoidWrite(path) - master.write( - '; THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n\n') + with self._write_file(path) as master: + master.write( + '; THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n\n') - for manifest in sorted(manifests): - master.write('[include:%s]\n' % manifest) - - self._update_from_avoid_write(master.close()) - self.summary.managed_count += 1 + for manifest in sorted(manifests): + master.write('[include:%s]\n' % manifest)
--- a/python/mozbuild/mozbuild/frontend/data.py +++ b/python/mozbuild/mozbuild/frontend/data.py @@ -99,36 +99,41 @@ class DirectoryTraversal(SandboxDerived) self.test_dirs = [] self.test_tool_dirs = [] self.tier_dirs = OrderedDict() self.tier_static_dirs = OrderedDict() self.external_make_dirs = [] self.parallel_external_make_dirs = [] -class ConfigFileSubstitution(SandboxDerived): - """Describes a config file that will be generated using substitutions. +class BaseConfigSubstitution(SandboxDerived): + """Base class describing autogenerated files as part of config.status.""" - The output_path attribute defines the relative path from topsrcdir of the - output file to generate. - """ __slots__ = ( 'input_path', 'output_path', 'relpath', ) def __init__(self, sandbox): SandboxDerived.__init__(self, sandbox) self.input_path = None self.output_path = None self.relpath = None +class ConfigFileSubstitution(BaseConfigSubstitution): + """Describes a config file that will be generated using substitutions.""" + + +class HeaderFileSubstitution(BaseConfigSubstitution): + """Describes a header file that will be generated using substitutions.""" + + class VariablePassthru(SandboxDerived): """A dict of variables to pass through to backend.mk unaltered. The purpose of this object is to facilitate rapid transitioning of variables from Makefile.in to moz.build. In the ideal world, this class does not exist and every variable has a richer class representing it. As long as we rely on this class, we lose the ability to have flexibility in our build backends since we will continue to be tied to our rules.mk.
--- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -20,16 +20,17 @@ from mozpack.files import FileFinder from .data import ( ConfigFileSubstitution, Defines, DirectoryTraversal, Exports, GeneratedEventWebIDLFile, GeneratedInclude, GeneratedWebIDLFile, + HeaderFileSubstitution, InstallationTarget, IPDLFile, LocalInclude, PreprocessedTestWebIDLFile, PreprocessedWebIDLFile, Program, ReaderSummary, SandboxWrapped, @@ -94,24 +95,22 @@ class TreeMetadataEmitter(LoggingMixin): This is a generator of mozbuild.frontend.data.SandboxDerived instances. """ # We always emit a directory traversal descriptor. This is needed by # the recursive make backend. for o in self._emit_directory_traversal_from_sandbox(sandbox): yield o for path in sandbox['CONFIGURE_SUBST_FILES']: - if os.path.isabs(path): - path = path[1:] + yield self._create_substitution(ConfigFileSubstitution, sandbox, + path) - sub = ConfigFileSubstitution(sandbox) - sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path) - sub.output_path = os.path.join(sandbox['OBJDIR'], path) - sub.relpath = path - yield sub + for path in sandbox['CONFIGURE_DEFINE_FILES']: + yield self._create_substitution(HeaderFileSubstitution, sandbox, + path) # XPIDL source files get processed and turned into .h and .xpt files. # If there are multiple XPIDL files in a directory, they get linked # together into a final .xpt, which has the name defined by either # MODULE or XPIDL_MODULE (if the latter is defined). xpidl_module = sandbox['MODULE'] if sandbox['XPIDL_MODULE']: xpidl_module = sandbox['XPIDL_MODULE'] @@ -124,17 +123,17 @@ class TreeMetadataEmitter(LoggingMixin): self.log(logging.WARN, 'mozbuild_warning', dict( path=sandbox.main_path), '{path}: NO_DIST_INSTALL has no effect on XPIDL_SOURCES.') for idl in sandbox['XPIDL_SOURCES']: yield XPIDLFile(sandbox, mozpath.join(sandbox['SRCDIR'], idl), xpidl_module) - for symbol in ('SOURCES', 'GTEST_SOURCES', 'HOST_SOURCES'): + for symbol in ('SOURCES', 'GTEST_SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'): for src in (sandbox[symbol] or []): if not os.path.exists(os.path.join(sandbox['SRCDIR'], src)): raise SandboxValidationError('Reference to a file that ' 'doesn\'t exist in %s (%s) in %s' % (symbol, src, sandbox['RELATIVEDIR'])) # Proxy some variables as-is until we have richer classes to represent # them. We should aim to keep this set small because it violates the @@ -181,16 +180,18 @@ class TreeMetadataEmitter(LoggingMixin): CMMSRCS=('SOURCES', '.mm'), CPPSRCS=('SOURCES', ('.cc', '.cpp')), SSRCS=('SOURCES', '.S'), HOST_CPPSRCS=('HOST_SOURCES', ('.cc', '.cpp')), HOST_CSRCS=('HOST_SOURCES', '.c'), GTEST_CMMSRCS=('GTEST_SOURCES', '.mm'), GTEST_CPPSRCS=('GTEST_SOURCES', ('.cc', '.cpp')), GTEST_CSRCS=('GTEST_SOURCES', '.c'), + UNIFIED_CSRCS=('UNIFIED_SOURCES', '.c'), + UNIFIED_CPPSRCS=('UNIFIED_SOURCES', ('.cc', '.cpp')), ) for mak, (moz, ext) in varmap.items(): if sandbox[moz]: filtered = [f for f in sandbox[moz] if f.endswith(ext)] if filtered: passthru.variables[mak] = filtered if passthru.variables: @@ -261,16 +262,27 @@ class TreeMetadataEmitter(LoggingMixin): for prefix, info in test_manifests.items(): for path in sandbox.get('%s_MANIFESTS' % prefix, []): for obj in self._process_test_manifest(sandbox, info, path): yield obj for name, jar in sandbox.get('JAVA_JAR_TARGETS', {}).items(): yield SandboxWrapped(sandbox, jar) + def _create_substitution(self, cls, sandbox, path): + if os.path.isabs(path): + path = path[1:] + + sub = cls(sandbox) + sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path) + sub.output_path = os.path.join(sandbox['OBJDIR'], path) + sub.relpath = path + + return sub + def _process_test_manifest(self, sandbox, info, manifest_path): flavor, install_prefix, filter_inactive = info manifest_path = os.path.normpath(manifest_path) path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path)) manifest_dir = mozpath.dirname(path) manifest_reldir = mozpath.dirname(mozpath.relpath(path, sandbox['TOPSRCDIR']))
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -73,16 +73,25 @@ VARIABLES = { 'SOURCES': (StrictOrderingOnAppendList, list, [], """Source code files. This variable contains a list of source code files to compile. Accepts assembler, C, C++, Objective C/C++. """, 'compile'), + 'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [], + """Source code files that can be compiled together. + + This variable contains a list of source code files to compile, + that can be concatenated all together and built as a single source + file. This can help make the build faster and reduce the debug info + size. + """, 'compile'), + 'DEFINES': (OrderedDict, dict, OrderedDict(), """Dictionary of compiler defines to declare. These are passed in to the compiler as ``-Dkey='value'`` for string values, ``-Dkey=value`` for numeric values, or ``-Dkey`` if the value is True. Note that for string values, the outer-level of single-quotes will be consumed by the shell. If you want to have a string-literal in the program, the value needs to have @@ -345,16 +354,24 @@ VARIABLES = { This is a substitute for ``AC_OUTPUT`` in autoconf. For each path in this list, we will search for a file in the srcdir having the name ``{path}.in``. The contents of this file will be read and variable patterns like ``@foo@`` will be substituted with the values of the ``AC_SUBST`` variables declared during configure. """, None), + 'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list, [], + """Output files generated from configure/config.status. + + This is a substitute for ``AC_CONFIG_HEADER`` in autoconf. This is very + similar to ``CONFIGURE_SUBST_FILES`` except the generation logic takes + into account the values of ``AC_DEFINE`` instead of ``AC_SUBST``. + """, None), + 'MODULE': (unicode, unicode, "", """Module name. Historically, this variable was used to describe where to install header files, but that feature is now handled by ``EXPORTS_NAMESPACES``. ``MODULE`` will likely be removed in the future. """, None),
--- a/python/mozbuild/mozbuild/test/backend/test_configenvironment.py +++ b/python/mozbuild/mozbuild/test/backend/test_configenvironment.py @@ -65,17 +65,18 @@ qux =''') def test_config_file(self): '''Test the creation of config files. ''' with MockedOpen({'file.in': '''#ifdef foo @foo@ @bar@ '''}): env = ConfigEnvironment('.', '.', substs = [ ('foo', 'bar baz') ]) - env.create_config_file('file') + with open('file', 'w') as fh: + env.create_config_file(fh) self.assertEqual(open('file', 'r').read(), '''#ifdef foo bar baz @bar@ ''') def test_config_header(self): '''Test the creation of config headers. ''' @@ -92,17 +93,18 @@ bar baz #ifdef foo # undef foo # define foo 42 # define foo 42 #endif '''}): env = ConfigEnvironment('.', '.', defines = [ ('foo', 'baz qux'), ('baz', 1) ]) - env.create_config_header('file') + with open('file', 'w') as fh: + env.create_config_header(fh) self.assertEqual(open('file','r').read(), ''' /* Comment */ #define foo #define foo baz qux #define foo baz qux #define bar #define bar 42 /* #undef bar */
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -148,19 +148,19 @@ class TestRecursiveMakeTraversal(unittes 'I': ('G', 'H'), }) class TestRecursiveMakeBackend(BackendTester): def test_basic(self): """Ensure the RecursiveMakeBackend works without error.""" env = self._consume('stub0', RecursiveMakeBackend) self.assertTrue(os.path.exists(os.path.join(env.topobjdir, - 'backend.RecursiveMakeBackend.built'))) + 'backend.RecursiveMakeBackend'))) self.assertTrue(os.path.exists(os.path.join(env.topobjdir, - 'backend.RecursiveMakeBackend.built.pp'))) + 'backend.RecursiveMakeBackend.pp'))) def test_output_files(self): """Ensure proper files are generated.""" env = self._consume('stub0', RecursiveMakeBackend) expected = ['', 'dir1', 'dir2'] for d in expected: @@ -206,18 +206,16 @@ class TestRecursiveMakeBackend(BackendTe """Ensure backend.mk file is written out properly.""" env = self._consume('stub0', RecursiveMakeBackend) p = os.path.join(env.topobjdir, 'backend.mk') lines = [l.strip() for l in open(p, 'rt').readlines()[2:]] self.assertEqual(lines, [ 'MOZBUILD_DERIVED := 1', - 'NO_MAKEFILE_RULE := 1', - 'NO_SUBMAKEFILES_RULE := 1', 'DIRS := dir1', 'PARALLEL_DIRS := dir2', 'TEST_DIRS := dir3', ]) def test_mtime_no_change(self): """Ensure mtime is not updated if file content does not change.""" @@ -239,18 +237,16 @@ class TestRecursiveMakeBackend(BackendTe def test_external_make_dirs(self): """Ensure we have make recursion into external make directories.""" env = self._consume('external_make_dirs', RecursiveMakeBackend) backend_path = os.path.join(env.topobjdir, 'backend.mk') lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]] self.assertEqual(lines, [ 'MOZBUILD_DERIVED := 1', - 'NO_MAKEFILE_RULE := 1', - 'NO_SUBMAKEFILES_RULE := 1', 'DIRS := dir', 'PARALLEL_DIRS := p_dir', 'DIRS += external', 'PARALLEL_DIRS += p_external', ]) def test_substitute_config_files(self): """Ensure substituted config files are produced."""
--- a/python/mozbuild/mozbuild/util.py +++ b/python/mozbuild/mozbuild/util.py @@ -113,44 +113,44 @@ class FileAvoidWrite(StringIO): We create an instance from an existing filename. New content is written to it. When we close the file object, if the content in the in-memory buffer differs from what is on disk, then we write out the new content. Otherwise, the original file is untouched. """ def __init__(self, filename): StringIO.__init__(self) - self.filename = filename + self.name = filename def close(self): """Stop accepting writes, compare file contents, and rewrite if needed. Returns a tuple of bools indicating what action was performed: (file existed, file updated) """ buf = self.getvalue() StringIO.close(self) existed = False try: - existing = open(self.filename, 'rU') + existing = open(self.name, 'rU') existed = True except IOError: pass else: try: if existing.read() == buf: return True, False except IOError: pass finally: existing.close() - ensureParentDir(self.filename) - with open(self.filename, 'w') as file: + ensureParentDir(self.name) + with open(self.name, 'w') as file: file.write(buf) return existed, True def __enter__(self): return self def __exit__(self, type, value, traceback): self.close()
--- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -955,24 +955,25 @@ void nsNSSComponent::setValidationOption /* * The new defaults might change the validity of already established SSL sessions, * let's not reuse them. */ SSL_ClearSessionCache(); } -// Enable the TLS versions given in the prefs, defaulting to SSL 3.0 and -// TLS 1.0 when the prefs aren't set or when they are set to invalid values. +// Enable the TLS versions given in the prefs, defaulting to SSL 3.0 (min +// version) and TLS 1.1 (max version) when the prefs aren't set or set to +// invalid values. nsresult nsNSSComponent::setEnabledTLSVersions() { - // keep these values in sync with security-prefs.js and firefox.js + // keep these values in sync with security-prefs.js static const int32_t PSM_DEFAULT_MIN_TLS_VERSION = 0; - static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 1; + static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 2; int32_t minVersion = Preferences::GetInt("security.tls.version.min", PSM_DEFAULT_MIN_TLS_VERSION); int32_t maxVersion = Preferences::GetInt("security.tls.version.max", PSM_DEFAULT_MAX_TLS_VERSION); // 0 means SSL 3.0, 1 means TLS 1.0, 2 means TLS 1.1, etc. minVersion += SSL_LIBRARY_VERSION_3_0;
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js +++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js @@ -71,16 +71,18 @@ function run_test() { add_ocsp_test("ocsp-stapling-trylater.example.com", getXPCOMStatusFromNSS(122), true); // SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = (SEC_ERROR_BASE + 123) add_ocsp_test("ocsp-stapling-needssig.example.com", getXPCOMStatusFromNSS(123), true); // SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = (SEC_ERROR_BASE + 124) add_ocsp_test("ocsp-stapling-unauthorized.example.com", getXPCOMStatusFromNSS(124), true); // SEC_ERROR_OCSP_UNKNOWN_CERT = (SEC_ERROR_BASE + 126) add_ocsp_test("ocsp-stapling-unknown.example.com", getXPCOMStatusFromNSS(126), true); add_ocsp_test("ocsp-stapling-good-other.example.com", getXPCOMStatusFromNSS(126), true); + // If the server doesn't send an OCSP response, we continue as normal. + add_ocsp_test("ocsp-stapling-none.example.com", Cr.NS_OK, true); // SEC_ERROR_OCSP_MALFORMED_RESPONSE = (SEC_ERROR_BASE + 129) - add_ocsp_test("ocsp-stapling-none.example.com", getXPCOMStatusFromNSS(129), true); + add_ocsp_test("ocsp-stapling-empty.example.com", getXPCOMStatusFromNSS(129), true); // SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132) add_ocsp_test("ocsp-stapling-expired.example.com", getXPCOMStatusFromNSS(132), true); add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com", getXPCOMStatusFromNSS(132), true); run_next_test(); }
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp @@ -26,16 +26,17 @@ enum OCSPStapleResponseType OSRTGood, // the certificate is good OSRTRevoked, // the certificate has been revoked OSRTUnknown, // the responder doesn't know if the cert is good OSRTGoodOtherCert, // the response references a different certificate OSRTGoodOtherCA, // the wrong CA has signed the response OSRTExpired, // the signature on the response has expired OSRTExpiredFreshCA, // fresh signature, but old validity period OSRTNone, // no stapled response + OSRTEmpty, // an empty stapled response OSRTMalformed, // the response from the responder was malformed OSRTSrverr, // the response indicates there was a server error OSRTTryLater, // the responder replied with "try again later" OSRTNeedsSig, // the response needs a signature OSRTUnauthorized // the responder is not authorized for this certificate }; struct OCSPHost @@ -49,28 +50,37 @@ const OCSPHost sOCSPHosts[] = { "ocsp-stapling-good.example.com", OSRTGood }, { "ocsp-stapling-revoked.example.com", OSRTRevoked }, { "ocsp-stapling-unknown.example.com", OSRTUnknown }, { "ocsp-stapling-good-other.example.com", OSRTGoodOtherCert }, { "ocsp-stapling-good-other-ca.example.com", OSRTGoodOtherCA }, { "ocsp-stapling-expired.example.com", OSRTExpired }, { "ocsp-stapling-expired-fresh-ca.example.com", OSRTExpiredFreshCA }, { "ocsp-stapling-none.example.com", OSRTNone }, + { "ocsp-stapling-empty.example.com", OSRTEmpty }, { "ocsp-stapling-malformed.example.com", OSRTMalformed }, { "ocsp-stapling-srverr.example.com", OSRTSrverr }, { "ocsp-stapling-trylater.example.com", OSRTTryLater }, { "ocsp-stapling-needssig.example.com", OSRTNeedsSig }, { "ocsp-stapling-unauthorized.example.com", OSRTUnauthorized }, { nullptr, OSRTNull } }; SECItemArray * GetOCSPResponseForType(OCSPStapleResponseType aOSRT, CERTCertificate *aCert, PLArenaPool *aArena) { + if (aOSRT == OSRTNone) { + if (gDebugLevel >= DEBUG_WARNINGS) { + fprintf(stderr, "GetOCSPResponseForType called with type OSRTNone, " + "which makes no sense.\n"); + } + return nullptr; + } + PRTime now = PR_Now(); ScopedCERTOCSPCertID id(CERT_CreateOCSPCertID(aCert, now)); if (!id) { PrintPRError("CERT_CreateOCSPCertID failed"); return nullptr; } PRTime nextUpdate = now + 10 * PR_USEC_PER_SEC; PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC; @@ -132,28 +142,28 @@ GetOCSPResponseForType(OCSPStapleRespons sr = CERT_CreateOCSPSingleResponseGood(aArena, otherID, now, &nextUpdate); if (!sr) { PrintPRError("CERT_CreateOCSPSingleResponseGood failed"); return nullptr; } otherID.forget(); // owned by sr now break; } - case OSRTNone: + case OSRTEmpty: case OSRTMalformed: case OSRTSrverr: case OSRTTryLater: case OSRTNeedsSig: case OSRTUnauthorized: break; default: if (gDebugLevel >= DEBUG_ERRORS) { fprintf(stderr, "bad ocsp response type: %d\n", aOSRT); } - break; + return nullptr; } ScopedCERTCertificate ca; if (aOSRT == OSRTGoodOtherCA) { ca = PK11_FindCertFromNickname("otherCA", nullptr); if (!ca) { PrintPRError("PK11_FindCertFromNickname failed"); return nullptr; @@ -210,17 +220,17 @@ GetOCSPResponseForType(OCSPStapleRespons case OSRTUnauthorized: response = CERT_CreateEncodedOCSPErrorResponse( aArena, SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); if (!response) { PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed"); return nullptr; } break; - case OSRTNone: + case OSRTEmpty: break; default: // responses is contained in aArena and will be freed when aArena is responses = PORT_ArenaNewArray(aArena, CERTOCSPSingleResponse *, 2); if (!responses) { PrintPRError("PORT_ArenaNewArray failed"); return nullptr; } @@ -258,16 +268,21 @@ DoSNISocketConfig(PRFileDesc *aFd, const ScopedCERTCertificate cert; SSLKEAType certKEA; if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, DEFAULT_CERT_NICKNAME, &cert, &certKEA)) { return SSL_SNI_SEND_ALERT; } + // If the OCSP response type is "none", don't staple a response. + if (host->mOSRT == OSRTNone) { + return 0; + } + PLArenaPool *arena = PORT_NewArena(1024); if (!arena) { PrintPRError("PORT_NewArena failed"); return SSL_SNI_SEND_ALERT; } // response is contained by the arena - freeing the arena will free it SECItemArray *response = GetOCSPResponseForType(host->mOSRT, cert, arena);
--- a/testing/mochitest/Makefile.in +++ b/testing/mochitest/Makefile.in @@ -31,17 +31,16 @@ include $(topsrcdir)/build/automation-bu $(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanager.py \ $(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py \ $(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py \ $(topsrcdir)/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py \ $(topsrcdir)/testing/mozbase/mozdevice/mozdevice/droid.py \ $(topsrcdir)/testing/mozbase/mozdevice/mozdevice/Zeroconf.py \ $(topsrcdir)/build/automationutils.py \ $(topsrcdir)/build/mobile/remoteautomation.py \ - $(topsrcdir)/build/mobile/b2gautomation.py \ gen_template.pl \ server.js \ chunkifyTests.js \ manifestLibrary.js \ harness.xul \ browser-test-overlay.xul \ browser-test.js \ cc-analyzer.js \
--- a/testing/mochitest/browser-harness.xul +++ b/testing/mochitest/browser-harness.xul @@ -101,16 +101,21 @@ // If MochiTest was started with the --test-path flag specifying a subset // of tests to run, put that path in the label of the "Run Tests" button // so the tester knows which tests will run when they press that button. if (gConfig.testPath) document.getElementById("runTestsButton").label = "Run " + gConfig.testPath + " tests"; + // Similarly, update the title for --start-at and --end-at. + if (gConfig.startAt || gConfig.endAt) + document.getElementById("runTestsButton").label = + "Run subset of tests"; + if (gConfig.autorun) setTimeout(runTests, 0); } var gErrorCount = 0; function browserTest(aTestFile) { this.path = aTestFile; @@ -185,16 +190,20 @@ var srvScope = {}; scriptLoader.loadSubScript('chrome://mochikit/content/server.js', srvScope); var fileNames = []; var fileNameRegexp = /browser_.+\.js$/; srvScope.arrayOfTestFiles(links, fileNames, fileNameRegexp); + if (gConfig.startAt || gConfig.endAt) { + fileNames = skipTests(fileNames, gConfig.startAt, gConfig.endAt); + } + if (gConfig.totalChunks && gConfig.thisChunk) { fileNames = chunkifyTests(fileNames, gConfig.totalChunks, gConfig.thisChunk, gConfig.chunkByDir); } createTester(fileNames.map(function (f) { return new browserTest(f); })); }
--- a/testing/mochitest/chunkifyTests.js +++ b/testing/mochitest/chunkifyTests.js @@ -58,8 +58,24 @@ function chunkifyTests(tests, totalChunk var end = Math.round(this_chunk * tests_per_chunk); returnTests = tests.slice(start, end); if (logger) logger.log("Running tests " + (start+1) + "-" + end + "/" + tests.length); } return returnTests; } + +function skipTests(tests, startTestPattern, endTestPattern) { + var startIndex = 0, endIndex = tests.length - 1; + for (var i = 0; i < tests.length; ++i) { + var test_path = tests[i]; + if (startTestPattern && test_path.endsWith(startTestPattern)) { + startIndex = i; + } + + if (endTestPattern && test_path.endsWith(endTestPattern)) { + endIndex = i; + } + } + + return tests.slice(startIndex, endIndex + 1); +}
--- a/testing/mochitest/harness.xul +++ b/testing/mochitest/harness.xul @@ -17,16 +17,18 @@ src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/> <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/> <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/MozillaLogger.js"/> <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" /> <script type="application/javascript" + src="chrome://mochikit/content/chunkifyTests.js" /> + <script type="application/javascript" src="chrome://mochikit/content/manifestLibrary.js" /> <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/setup.js" /> <script type="application/javascript;version=1.7"><![CDATA[ if (Cc === undefined) { var Cc = Components.classes; var Ci = Components.interfaces;
--- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -180,17 +180,18 @@ class MochitestRunner(MozbuildObject): options.logcat_dir = self.mochitest_dir options.httpdPath = self.mochitest_dir options.xrePath = xre_path return mochitest.run_remote_mochitests(parser, options) def run_desktop_test(self, suite=None, test_file=None, debugger=None, debugger_args=None, shuffle=False, keep_open=False, rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False, slow=False, - chunk_by_dir=0, total_chunks=None, this_chunk=None, jsdebugger=False): + chunk_by_dir=0, total_chunks=None, this_chunk=None, jsdebugger=False, + start_at=None, end_at=None): """Runs a mochitest. test_file is a path to a test file. It can be a relative path from the top source directory, an absolute filename, or a directory containing test files. suite is the type of mochitest to run. It can be one of ('plain', 'chrome', 'browser', 'metro', 'a11y'). @@ -281,16 +282,18 @@ class MochitestRunner(MozbuildObject): options.runSlower = slow options.testingModulesDir = os.path.join(self.tests_dir, 'modules') options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins')) options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols') options.chunkByDir = chunk_by_dir options.totalChunks = total_chunks options.thisChunk = this_chunk options.jsdebugger = jsdebugger + options.startAt = start_at + options.endAt = end_at options.failureFile = failure_file_path if test_path: test_root = runner.getTestRoot(options) test_root_file = mozpack.path.join(self.mochitest_dir, test_root, test_path) if not os.path.exists(test_root_file): print('Specified test path does not exist: %s' % test_root_file) @@ -458,16 +461,24 @@ def B2GCommand(func): chunk_total = CommandArgument('--total-chunks', type=int, help='Total number of chunks to split tests into.') func = chunk_total(func) this_chunk = CommandArgument('--this-chunk', type=int, help='If running tests by chunks, the number of the chunk to run.') func = this_chunk(func) + start_at = CommandArgument('--start-at', type=str, + help='Start running the test sequence at this test.') + func = start_at(func) + + end_at = CommandArgument('--end-at', type=str, + help='Stop running the test sequence at this test.') + func = end_at(func) + path = CommandArgument('test_file', default=None, nargs='?', metavar='TEST', help='Test to run. Can be specified as a single file, a ' \ 'directory, or omitted. If omitted, the entire test suite is ' \ 'executed.') func = path(func) return func
--- a/testing/mochitest/manifest.webapp +++ b/testing/mochitest/manifest.webapp @@ -22,17 +22,19 @@ "camera":{}, "geolocation":{}, "wifi-manage":{}, "wifi":{}, "desktop-notification":{}, "idle":{}, "network-events":{}, "embed-apps":{}, - "systemXHR":{} + "systemXHR":{}, + "audio-channel-content":{}, + "audio-channel-alarm":{} }, "locales": { "en-US": { "name": "Mochitest", "description": "Mochitests" } }, "datastores-access" : {
--- a/testing/mochitest/mochitest_options.py +++ b/testing/mochitest/mochitest_options.py @@ -140,16 +140,30 @@ class MochitestOptions(optparse.OptionPa }], [["--test-path"], { "action": "store", "type": "string", "dest": "testPath", "help": "start in the given directory's tests", "default": "", }], + [["--start-at"], + { "action": "store", + "type": "string", + "dest": "startAt", + "help": "skip over tests until reaching the given test", + "default": "", + }], + [["--end-at"], + { "action": "store", + "type": "string", + "dest": "endAt", + "help": "don't run any tests after the given one", + "default": "", + }], [["--browser-chrome"], { "action": "store_true", "dest": "browserChrome", "help": "run browser chrome Mochitests", "default": False, }], [["--webapprt-content"], { "action": "store_true",
--- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -283,16 +283,18 @@ class MochitestUtilsMixin(object): URL parameters to test URL: autorun -- kick off tests automatically closeWhenDone -- closes the browser after the tests hideResultsTable -- hides the table of individual test results logFile -- logs test run to an absolute path totalChunks -- how many chunks to split tests into thisChunk -- which chunk to run + startAt -- name of test to start at + endAt -- name of test to end at timeout -- per-test timeout in seconds repeat -- How many times to repeat the test, ie: repeat=1 will run the test twice. """ # allow relative paths for logFile if options.logFile: options.logFile = self.getLogFilePath(options.logFile) if options.browserChrome or options.chrome or options.a11y or options.webapprtChrome: @@ -309,16 +311,20 @@ class MochitestUtilsMixin(object): self.urlOpts.append("fileLevel=" + encodeURIComponent(options.fileLevel)) if options.consoleLevel: self.urlOpts.append("consoleLevel=" + encodeURIComponent(options.consoleLevel)) if options.totalChunks: self.urlOpts.append("totalChunks=%d" % options.totalChunks) self.urlOpts.append("thisChunk=%d" % options.thisChunk) if options.chunkByDir: self.urlOpts.append("chunkByDir=%d" % options.chunkByDir) + if options.startAt: + self.urlOpts.append("startAt=%s" % options.startAt) + if options.endAt: + self.urlOpts.append("endAt=%s" % options.endAt) if options.shuffle: self.urlOpts.append("shuffle=1") if "MOZ_HIDE_RESULTS_TABLE" in env and env["MOZ_HIDE_RESULTS_TABLE"] == "1": self.urlOpts.append("hideResultsTable=1") if options.runUntilFailure: self.urlOpts.append("runUntilFailure=1") if options.repeat: self.urlOpts.append("repeat=%d" % options.repeat)
--- a/testing/mochitest/tests/SimpleTest/setup.js +++ b/testing/mochitest/tests/SimpleTest/setup.js @@ -137,16 +137,20 @@ RunSet.runall = function(e) { RunSet.runtests(); } } RunSet.runtests = function(e) { // Which tests we're going to run var my_tests = gTestList; + if (params.startAt || params.endAt) { + my_tests = skipTests(my_tests, params.startAt, params.endAt); + } + if (params.totalChunks && params.thisChunk) { my_tests = chunkifyTests(my_tests, params.totalChunks, params.thisChunk, params.chunkByDir, TestRunner.logger); } if (params.shuffle) { for (var i = my_tests.length-1; i > 0; --i) { var j = Math.floor(Math.random() * i); var tmp = my_tests[j];
--- a/toolkit/content/browser-child.js +++ b/toolkit/content/browser-child.js @@ -109,67 +109,68 @@ let WebNavigation = { init: function() { addMessageListener("WebNavigation:GoBack", this); addMessageListener("WebNavigation:GoForward", this); addMessageListener("WebNavigation:GotoIndex", this); addMessageListener("WebNavigation:LoadURI", this); addMessageListener("WebNavigation:Reload", this); addMessageListener("WebNavigation:Stop", this); + + // Send a CPOW for the sessionHistory object. + let history = this._webNavigation.sessionHistory; + sendAsyncMessage("WebNavigation:setHistory", {}, {history: history}); }, receiveMessage: function(message) { switch (message.name) { case "WebNavigation:GoBack": this.goBack(); break; case "WebNavigation:GoForward": this.goForward(); break; case "WebNavigation:GotoIndex": - this.gotoIndex(message); + this.gotoIndex(message.data.index); break; case "WebNavigation:LoadURI": - this.loadURI(message); + this.loadURI(message.data.uri, message.data.flags); break; case "WebNavigation:Reload": - this.reload(message); + this.reload(message.data.flags); break; case "WebNavigation:Stop": - this.stop(message); + this.stop(message.data.flags); break; } }, goBack: function() { if (this._webNavigation.canGoBack) this._webNavigation.goBack(); }, goForward: function() { if (this._webNavigation.canGoForward) this._webNavigation.goForward(); }, - gotoIndex: function(message) { - this._webNavigation.gotoIndex(message.index); + gotoIndex: function(index) { + this._webNavigation.gotoIndex(index); }, - loadURI: function(message) { - let flags = message.json.flags || this._webNavigation.LOAD_FLAGS_NONE; - this._webNavigation.loadURI(message.json.uri, flags, null, null, null); + loadURI: function(uri, flags) { + this._webNavigation.loadURI(uri, flags, null, null, null); }, - reload: function(message) { - let flags = message.json.flags || this._webNavigation.LOAD_FLAGS_NONE; + reload: function(flags) { this._webNavigation.reload(flags); }, - stop: function(message) { - let flags = message.json.flags || this._webNavigation.STOP_ALL; + stop: function(flags) { this._webNavigation.stop(flags); } }; WebNavigation.init(); let SecurityUI = { getSSLStatusAsString: function() { @@ -222,8 +223,12 @@ addEventListener("ImageContentLoaded", f if (!req.image) return; sendAsyncMessage("ImageDocumentLoaded", { width: req.image.width, height: req.image.height }); } }, false); RemoteAddonsChild.init(this); + +addMessageListener("History:UseGlobalHistory", function (aMessage) { + docShell.useGlobalHistory = aMessage.data.enabled; +});
--- a/toolkit/content/widgets/remote-browser.xml +++ b/toolkit/content/widgets/remote-browser.xml @@ -28,28 +28,19 @@ createInstance(Ci.nsISupportsInterfacePointer); ptr.data = this._securityUI; return ptr.data.QueryInterface(Ci.nsISecureBrowserUI); ]]></getter> </property> <field name="_remoteWebNavigation">null</field> - <property name="webNavigation" readonly="true"> - <getter> - <![CDATA[ - if (!this._remoteWebNavigation) { - let jsm = "resource://gre/modules/RemoteWebNavigation.jsm"; - let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation; - this._remoteWebNavigation = new RemoteWebNavigation(this); - } - return this._remoteWebNavigation; - ]]> - </getter> - </property> + <property name="webNavigation" + onget="return this._remoteWebNavigation;" + readonly="true"/> <field name="_remoteWebProgress">null</field> <property name="webProgress" readonly="true"> <getter> <![CDATA[ if (!this._remoteWebProgress) { let jsm = "resource://gre/modules/RemoteWebProgress.jsm"; @@ -106,34 +97,42 @@ <field name="_imageDocument">null</field> <property name="imageDocument" onget="return this._imageDocument" readonly="true"/> <constructor> <![CDATA[ + let jsm = "resource://gre/modules/RemoteWebNavigation.jsm"; + let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation; + this._remoteWebNavigation = new RemoteWebNavigation(this); + this.messageManager.addMessageListener("DOMTitleChanged", this); this.messageManager.addMessageListener("ImageDocumentLoaded", this); this.messageManager.loadFrameScript("chrome://global/content/browser-child.js", true); if (this.hasAttribute("selectpopup")) { this.messageManager.addMessageListener("Forms:ShowDropDown", this); this.messageManager.addMessageListener("Forms:HideDropDown", this); this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true); } - let jsm = "resource://gre/modules/RemoteController.jsm"; + jsm = "resource://gre/modules/RemoteController.jsm"; let RemoteController = Components.utils.import(jsm, {}).RemoteController; this._controller = new RemoteController(this); this.controllers.appendController(this._controller); jsm = "resource://gre/modules/RemoteAddonsParent.jsm"; let RemoteAddonsParent = Components.utils.import(jsm, {}).RemoteAddonsParent; RemoteAddonsParent.init(); + + if (!this.hasAttribute("disableglobalhistory")) { + this.messageManager.sendAsyncMessage("History:UseGlobalHistory", {enabled:true}); + } ]]> </constructor> <method name="receiveMessage"> <parameter name="aMessage"/> <body><![CDATA[ let data = aMessage.data; switch (aMessage.name) {
--- a/toolkit/devtools/apps/app-actor-front.js +++ b/toolkit/devtools/apps/app-actor-front.js @@ -248,8 +248,29 @@ function getTargetForApp(client, webapps deferred.reject(error); }); } }); return deferred.promise; } exports.getTargetForApp = getTargetForApp; +function reloadApp(client, webappsActor, manifestURL) { + let deferred = promise.defer(); + getTargetForApp(client, + webappsActor, + manifestURL). + then((target) => { + // Request the ContentAppActor to reload the app + let request = { + to: target.form.actor, + type: "reload", + manifestURL: manifestURL + }; + client.request(request, (res) => { + deferred.resolve(); + }); + }, () => { + deferred.reject("Not running"); + }); + return deferred.promise; +} +exports.reloadApp = reloadApp;
--- a/toolkit/devtools/server/actors/webapps.js +++ b/toolkit/devtools/server/actors/webapps.js @@ -413,22 +413,51 @@ WebappsActor.prototype = { let installDir = DOMApplicationRegistry._getAppDir(id); let manFile = installDir.clone(); manFile.append("manifest.webapp"); zipReader.extract("manifest.webapp", manFile); zipReader.close(); zipFile.moveTo(installDir, "application.zip"); let origin = "app://" + id; + let manifestURL = origin + "/manifest.webapp"; + + // Refresh application.zip content (e.g. reinstall app), as done here: + // http://hg.mozilla.org/mozilla-central/annotate/aaefec5d34f8/dom/apps/src/Webapps.jsm#l1125 + // Do it in parent process for the simulator + let jar = installDir.clone(); + jar.append("application.zip"); + Services.obs.notifyObservers(jar, "flush-cache-entry", null); + + // And then in app content process + // This function will be evaluated in the scope of the content process + // frame script. That will flush the jar cache for this app and allow + // loading fresh updated resources if we reload its document. + let FlushFrameScript = function (path) { + let jar = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + jar.initWithPath(path); + let obs = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + obs.notifyObservers(jar, "flush-cache-entry", null); + }; + for each (let frame in self._appFrames()) { + if (frame.getAttribute("mozapp") == manifestURL) { + let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager; + mm.loadFrameScript("data:," + + encodeURIComponent("(" + FlushFrameScript.toString() + ")" + + "('" + jar.path + "')"), false); + } + } // Create a fake app object with the minimum set of properties we need. let app = { origin: origin, installOrigin: origin, - manifestURL: origin + "/manifest.webapp", + manifestURL: manifestURL, appStatus: appType, receipts: aReceipts, } self._registerApp(deferred, app, id, aDir); } catch(e) { // If anything goes wrong, just send it back. self._sendError(deferred, e.toString(), aId); @@ -734,16 +763,20 @@ WebappsActor.prototype = { } reg.close(app); return {}; }, _appFrames: function () { + // For now, we only support app frames on b2g + if (Services.appinfo.ID != "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}") { + return; + } // Register the system app let chromeWindow = Services.wm.getMostRecentWindow('navigator:browser'); let systemAppFrame = chromeWindow.shell.contentBrowser; yield systemAppFrame; // Register apps hosted in the system app. i.e. the homescreen, all regular // apps and the keyboard. // Bookmark apps and other system app internal frames like captive portal
--- a/toolkit/modules/RemoteWebNavigation.jsm +++ b/toolkit/modules/RemoteWebNavigation.jsm @@ -6,19 +6,27 @@ this.EXPORTED_SYMBOLS = ["RemoteWebNavigation"]; const Ci = Components.interfaces; const Cc = Components.classes; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +function makeURI(url) +{ + return Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService). + newURI(url, null, null); +} + function RemoteWebNavigation(browser) { this._browser = browser; + this._browser.messageManager.addMessageListener("WebNavigation:setHistory", this); } RemoteWebNavigation.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebNavigation, Ci.nsISupports]), LOAD_FLAGS_MASK: 65535, LOAD_FLAGS_NONE: 0, LOAD_FLAGS_IS_REFRESH: 16, @@ -37,39 +45,67 @@ RemoteWebNavigation.prototype = { LOAD_FLAGS_FORCE_ALLOW_COOKIES: 131072, STOP_NETWORK: 1, STOP_CONTENT: 2, STOP_ALL: 3, canGoBack: false, canGoForward: false, - goBack: function() { this._sendMessage("WebNavigation:GoBack", {}); }, - goForward: function() { this._sendMessage("WebNavigation:GoForward", {}); }, - gotoIndex: function(aIndex) { this._sendMessage("WebNavigation:GotoIndex", {index: aIndex}); }, + goBack: function() { + this._sendMessage("WebNavigation:GoBack", {}); + }, + goForward: function() { + this._sendMessage("WebNavigation:GoForward", {}); + }, + gotoIndex: function(aIndex) { + this._sendMessage("WebNavigation:GotoIndex", {index: aIndex}); + }, loadURI: function(aURI, aLoadFlags, aReferrer, aPostData, aHeaders) { this._browser._contentTitle = ""; this._sendMessage("WebNavigation:LoadURI", {uri: aURI, flags: aLoadFlags}); }, - reload: function(aReloadFlags) { this._sendMessage("WebNavigation:Reload", {flags: aReloadFlags}); }, - stop: function(aStopFlags) { this._sendMessage("WebNavigation:Stop", {flags: aStopFlags}); }, - get document() { return this._browser.contentDocument; }, + reload: function(aReloadFlags) { + this._sendMessage("WebNavigation:Reload", {flags: aReloadFlags}); + }, + stop: function(aStopFlags) { + this._sendMessage("WebNavigation:Stop", {flags: aStopFlags}); + }, + + get document() { + return this._browser.contentDocument; + }, + + _currentURI: null, get currentURI() { - if (!this._currentURI) - this._currentURI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI("about:blank", null, null); + if (!this._currentURI) { + this._currentURI = makeURI("about:blank"); + } return this._currentURI; }, - set currentURI(aURI) { this.loadURI(aURI.spec, null, null, null); }, + set currentURI(aURI) { + this.loadURI(aURI.spec, null, null, null); + }, + referringURI: null, - get sessionHistory() { return null; }, + + _sessionHistory: null, + get sessionHistory() { return this._sessionHistory; }, set sessionHistory(aValue) { }, - _currentURI: null, _sendMessage: function(aMessage, aData) { try { this._browser.messageManager.sendAsyncMessage(aMessage, aData); } catch (e) { Cu.reportError(e); } + }, + + receiveMessage: function(aMessage) { + switch (aMessage.name) { + case "WebNavigation:setHistory": + this._sessionHistory = aMessage.objects.history; + break; + } } };
rename from toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js rename to toolkit/mozapps/update/tests/unit_aus_update/downloadAndHashCheckMar.js --- a/toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js +++ b/toolkit/mozapps/update/tests/unit_aus_update/downloadAndHashCheckMar.js @@ -1,31 +1,20 @@ /* 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/. */ -/* General MAR File Download Tests */ - -const INC_CONTRACT_ID = "@mozilla.org/network/incremental-download;1"; - var gNextRunFunc; -var gStatusResult; var gExpectedStatusResult; -var gIncrementalDownloadClassID, gIncOldFactory; - -// gIncrementalDownloadErrorType is used to loop through each of the connection -// error types in the Mock incremental downloader. -var gIncrementalDownloadErrorType = 0; function run_test() { setupTestCommon(true); - logTestInfo("testing mar downloads, mar hash verification, and " + - "mar download interrupted recovery"); + logTestInfo("testing mar download and mar hash verification"); Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false); // The HTTP server is only used for the mar file downloads since it is slow start_httpserver(); setUpdateURLOverride(gURLData + "update.xml"); // The mock XMLHttpRequest is MUCH faster overrideXHR(callHandleEvent); standardInit(); @@ -33,17 +22,16 @@ function run_test() { } // The HttpServer must be stopped before calling do_test_finished function finish_test() { stop_httpserver(do_test_finished); } function end_test() { - cleanupMockIncrementalDownload(); cleanupTestCommon(); } // Callback function used by the custom XMLHttpRequest implementation to // call the nsIDOMEventListener's handleEvent method for onload. function callHandleEvent() { gXHR.status = 400; gXHR.responseText = gResponseBody; @@ -186,17 +174,17 @@ function run_test_pt8() { // mar download with a valid SHA512 hash function run_test_pt9() { setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR); run_test_helper_pt1("mar download with a valid SHA512 hash", AUS_Cr.NS_OK, run_test_pt10); } -// mar download with an invalid SHA384 hash +// mar download with an invalid SHA512 hash function run_test_pt10() { setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR + "0"); run_test_helper_pt1("mar download with an invalid SHA512 hash", AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt11); } // mar download with the mar not found function run_test_pt11() { @@ -214,229 +202,14 @@ function run_test_pt12() { if (IS_TOOLKIT_GONK) { // There seems to be a race on the web server side when the patchFile is // stored on the SDCard. Sometimes, the webserver will serve up an error // 416 and the contents of the file, and sometimes it will serve up an error // 200 and no contents. This can cause either NS_ERROR_UNEXPECTED or // NS_ERROR_CONTENT_CORRUPTED. // Bug 828858 was filed to follow up on this issue. run_test_helper_bug828858_pt1("mar download with a valid MD5 hash but invalid file size", - AUS_Cr.NS_ERROR_UNEXPECTED, run_test_pt13); + AUS_Cr.NS_ERROR_UNEXPECTED, finish_test); } else { run_test_helper_pt1("mar download with a valid MD5 hash but invalid file size", - AUS_Cr.NS_ERROR_UNEXPECTED, run_test_pt13); + AUS_Cr.NS_ERROR_UNEXPECTED, finish_test); } } - -var newFactory = { - createInstance: function(aOuter, aIID) { - if (aOuter) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return new IncrementalDownload().QueryInterface(aIID); - }, - lockFactory: function(aLock) { - throw Components.results.NS_ERROR_NOT_IMPLEMENTED; - }, - QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIFactory]) -}; - -function initMockIncrementalDownload() { - var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar); - gIncrementalDownloadClassID = registrar.contractIDToCID(INC_CONTRACT_ID); - gIncOldFactory = AUS_Cm.getClassObject(AUS_Cc[INC_CONTRACT_ID], - AUS_Ci.nsIFactory); - registrar.unregisterFactory(gIncrementalDownloadClassID, gIncOldFactory); - var components = [IncrementalDownload]; - registrar.registerFactory(gIncrementalDownloadClassID, "", - INC_CONTRACT_ID, newFactory); -} - -function cleanupMockIncrementalDownload() { - if (gIncOldFactory) { - var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar); - registrar.unregisterFactory(gIncrementalDownloadClassID, newFactory); - registrar.registerFactory(gIncrementalDownloadClassID, "", - INC_CONTRACT_ID, gIncOldFactory); - } - gIncOldFactory = null; -} - -/* This Mock incremental downloader is used to verify that connection - * interrupts work correctly in updater code. The implementation of - * the mock incremental downloader is very simple, it simply copies - * the file to the destination location. -*/ - -function IncrementalDownload() { - this.wrappedJSObject = this; -} - -IncrementalDownload.prototype = { - QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIIncrementalDownload]), - - /* nsIIncrementalDownload */ - init: function(uri, file, chunkSize, intervalInSeconds) { - this._destination = file; - this._URI = uri; - this._finalURI = uri; - }, - - start: function(observer, ctxt) { - var tm = Components.classes["@mozilla.org/thread-manager;1"]. - getService(AUS_Ci.nsIThreadManager); - // Do the actual operation async to give a chance for observers - // to add themselves. - tm.mainThread.dispatch(function() { - this._observer = observer.QueryInterface(AUS_Ci.nsIRequestObserver); - this._ctxt = ctxt; - this._observer.onStartRequest(this, this.ctxt); - let mar = getTestDirFile(FILE_SIMPLE_MAR); - mar.copyTo(this._destination.parent, this._destination.leafName); - var status = AUS_Cr.NS_OK - switch (gIncrementalDownloadErrorType++) { - case 0: - status = AUS_Cr.NS_ERROR_NET_RESET; - break; - case 1: - status = AUS_Cr.NS_ERROR_CONNECTION_REFUSED; - break; - case 2: - status = AUS_Cr.NS_ERROR_NET_RESET; - break; - case 3: - status = AUS_Cr.NS_OK; - break; - case 4: - status = AUS_Cr.NS_ERROR_OFFLINE; - // After we report offline, we want to eventually show offline - // status being changed to online. - var tm = Components.classes["@mozilla.org/thread-manager;1"]. - getService(AUS_Ci.nsIThreadManager); - tm.mainThread.dispatch(function() { - Services.obs.notifyObservers(gAUS, - "network:offline-status-changed", - "online"); - }, AUS_Ci.nsIThread.DISPATCH_NORMAL); - break; - } - this._observer.onStopRequest(this, this._ctxt, status); - }.bind(this), AUS_Ci.nsIThread.DISPATCH_NORMAL); - }, - - get URI() { - return this._URI; - }, - - get currentSize() { - throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - - get destination() { - return this._destination; - }, - - get finalURI() { - return this._finalURI; - }, - - get totalSize() { - throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - - /* nsIRequest */ - cancel: function(aStatus) { - throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - suspend: function() { - throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - isPending: function() { - throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - _loadFlags: 0, - get loadFlags() { - return this._loadFlags; - }, - set loadFlags(val) { - this._loadFlags = val; - }, - - _loadGroup: null, - get loadGroup() { - return this._loadGroup; - }, - set loadGroup(val) { - this._loadGroup = val; - }, - - _name: "", - get name() { - return this._name; - }, - - _status: 0, - get status() { - return this._status;