merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-10-06 11:59:54 +02:00
Родитель 5f7f7c6912 2980c56cf9
Коммит 7c8e81673d
334 изменённых файлов: 21880 добавлений и 4466 удалений

Просмотреть файл

@ -35,4 +35,6 @@ else:
'/accessible/other',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -258,7 +258,7 @@ EventTree*
EventTree::FindOrInsert(Accessible* aContainer)
{
if (!mFirst) {
mFirst.reset(new EventTree(aContainer, true));
mFirst.reset(new EventTree(aContainer, mDependentEvents.IsEmpty()));
return mFirst.get();
}

Просмотреть файл

@ -425,8 +425,8 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
#if defined(XP_WIN)
IAccessibleHolder holder(CreateHolderFromAccessible(childDoc));
ipcDoc->SendCOMProxy(holder);
MOZ_ASSERT(parentIPCDoc);
ipcDoc->SendMsaaID(AccessibleWrap::GetChildIDFor(childDoc));
#endif
}
}

Просмотреть файл

@ -42,6 +42,8 @@ else:
'/accessible/other',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:

Просмотреть файл

@ -54,14 +54,13 @@ DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
nsTArray<AccessibleData>& aTree)
{
uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
#if defined(XP_WIN)
int32_t msaaId = AccessibleWrap::GetChildIDFor(aRoot);
#endif
uint32_t role = aRoot->Role();
uint32_t childCount = aRoot->ChildCount();
uint32_t interfaces = InterfacesFor(aRoot);
#if defined(XP_WIN)
IAccessibleHolder holder(CreateHolderFromAccessible(aRoot));
#endif
// OuterDocAccessibles are special because we don't want to serialize the
// child doc here, we'll call PDocAccessibleConstructor in
// NotificationController.
@ -71,8 +70,7 @@ DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
}
#if defined(XP_WIN)
aTree.AppendElement(AccessibleData(id, role, childCount, interfaces,
holder));
aTree.AppendElement(AccessibleData(id, msaaId, role, childCount, interfaces));
#else
aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
#endif
@ -82,29 +80,6 @@ DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
}
}
#if defined(XP_WIN)
/* static */ void
DocAccessibleChildBase::SetMsaaIds(Accessible* aRoot,
uint32_t& aMsaaIdIndex,
const nsTArray<MsaaMapping>& aNewMsaaIds)
{
const MsaaMapping& mapping = aNewMsaaIds[aMsaaIdIndex];
#if defined(DEBUG)
uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
MOZ_ASSERT(mapping.ID() == id);
#endif // defined(DEBUG)
static_cast<AccessibleWrap*>(aRoot)->SetID(mapping.MsaaID());
++aMsaaIdIndex;
if (aRoot->IsOuterDoc()) {
// This needs to match the tree traversal in SerializeTree
return;
}
for (uint32_t i = 0, n = aRoot->ChildCount(); i < n; ++i) {
SetMsaaIds(aRoot->GetChildAt(i), aMsaaIdIndex, aNewMsaaIds);
}
}
#endif // defined(XP_WIN)
void
DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
{
@ -114,22 +89,7 @@ DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
nsTArray<AccessibleData> shownTree;
ShowEventData data(parentID, idxInParent, shownTree);
SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
#if defined(XP_WIN)
nsTArray<MsaaMapping> newMsaaIds;
SendShowEventInfo(data, &newMsaaIds);
// newMsaaIds could be empty if something went wrong in SendShowEvent()
if (!newMsaaIds.IsEmpty()) {
uint32_t index = 0;
SetMsaaIds(aShowEvent->GetAccessible(), index, newMsaaIds);
}
// NB: On Windows, SendShowEvent attaches the subtree and generates new IDs,
// but does *NOT* fire the native event. We need to do that after
// we've called SetMsaaIds.
SendEvent(reinterpret_cast<uint64_t>(aShowEvent->GetAccessible()->UniqueID()),
nsIAccessibleEvent::EVENT_SHOW);
#else
SendShowEvent(data, aShowEvent->IsFromUserInput());
#endif // defined(XP_WIN)
}
} // namespace a11y

Просмотреть файл

@ -60,10 +60,6 @@ public:
protected:
static uint32_t InterfacesFor(Accessible* aAcc);
static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree);
#if defined(XP_WIN)
static void SetMsaaIds(Accessible* aRoot, uint32_t& aMsaaIdIndex,
const nsTArray<MsaaMapping>& aNewMsaaIds);
#endif
DocAccessible* mDoc;
};

Просмотреть файл

@ -16,13 +16,8 @@ namespace mozilla {
namespace a11y {
bool
#if defined(XP_WIN)
DocAccessibleParent::RecvShowEventInfo(const ShowEventData& aData,
nsTArray<MsaaMapping>* aNewMsaaIds)
#else
DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
const bool& aFromUser)
#endif // defined(XP_WIN)
{
if (mShutdown)
return true;
@ -49,13 +44,7 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
return true;
}
#if defined(XP_WIN)
aNewMsaaIds->SetCapacity(aData.NewTree().Length());
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx,
aNewMsaaIds);
#else
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
#endif
MOZ_ASSERT(consumed == aData.NewTree().Length());
// XXX This shouldn't happen, but if we failed to add children then the below
@ -73,9 +62,6 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
// NB: On Windows we dispatch the native event via a subsequent call to
// RecvEvent().
#if !defined(XP_WIN)
ProxyAccessible* target = parent->ChildAt(newChildIdx);
ProxyShowHideEvent(target, parent, true, aFromUser);
@ -90,7 +76,6 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node,
aFromUser);
nsCoreUtils::DispatchAccEvent(Move(event));
#endif
return true;
}
@ -98,11 +83,7 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
uint32_t
DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
const nsTArray<a11y::AccessibleData>& aNewTree,
uint32_t aIdx, uint32_t aIdxInParent
#if defined(XP_WIN)
, nsTArray<MsaaMapping>* aNewMsaaIds
#endif
)
uint32_t aIdx, uint32_t aIdxInParent)
{
if (aNewTree.Length() <= aIdx) {
NS_ERROR("bad index in serialized tree!");
@ -122,43 +103,22 @@ DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
auto role = static_cast<a11y::role>(newChild.Role());
#if defined(XP_WIN)
const IAccessibleHolder& proxyStream = newChild.COMProxy();
RefPtr<IAccessible> comPtr(proxyStream.Get());
if (!comPtr) {
NS_ERROR("Could not obtain remote IAccessible interface");
return 0;
}
ProxyAccessible* newProxy =
new ProxyAccessible(newChild.ID(), aParent, this, role,
newChild.Interfaces(), comPtr);
#else
ProxyAccessible* newProxy =
new ProxyAccessible(newChild.ID(), aParent, this, role,
newChild.Interfaces());
#endif
aParent->AddChildAt(aIdxInParent, newProxy);
mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
ProxyCreated(newProxy, newChild.Interfaces());
#if defined(XP_WIN)
Accessible* idForAcc = WrapperFor(newProxy);
MOZ_ASSERT(idForAcc);
uint32_t newMsaaId = AccessibleWrap::GetChildIDFor(idForAcc);
MOZ_ASSERT(newMsaaId);
aNewMsaaIds->AppendElement(MsaaMapping(newChild.ID(), newMsaaId));
#endif // defined(XP_WIN)
WrapperFor(newProxy)->SetID(newChild.MsaaID());
#endif
uint32_t accessibles = 1;
uint32_t kids = newChild.ChildrenCount();
for (uint32_t i = 0; i < kids; i++) {
uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i
#if defined(XP_WIN)
, aNewMsaaIds
#endif
);
uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
if (!consumed)
return 0;
@ -500,16 +460,20 @@ DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
#if defined(XP_WIN)
/**
* @param aMsaaID The MSAA ID that was generated by content that the chrome
* process should assign to this DocAccessibleParent.
* @param aCOMProxy COM Proxy to the document in the content process.
* @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
* the parent of the document. The content process will use this
* proxy when traversing up across the content/chrome boundary.
*/
bool
DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy,
uint32_t* aMsaaID)
DocAccessibleParent::RecvCOMProxy(const int32_t& aMsaaID,
const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy)
{
WrapperFor(this)->SetID(aMsaaID);
RefPtr<IAccessible> ptr(aCOMProxy.Get());
SetCOMInterface(ptr);
@ -520,8 +484,13 @@ DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
}
aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
Accessible* wrapper = WrapperFor(this);
*aMsaaID = AccessibleWrap::GetChildIDFor(wrapper);
return true;
}
bool
DocAccessibleParent::RecvMsaaID(const int32_t& aMsaaID)
{
WrapperFor(this)->SetID(aMsaaID);
return true;
}
#endif // defined(XP_WIN)

Просмотреть файл

@ -50,13 +50,8 @@ public:
virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType)
override;
#if defined(XP_WIN)
virtual bool RecvShowEventInfo(const ShowEventData& aData,
nsTArray<MsaaMapping>* aNewMsaaIds) override;
#else
virtual bool RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
override;
#endif // defined(XP_WIN)
virtual bool RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser)
override;
virtual bool RecvStateChangeEvent(const uint64_t& aID,
@ -78,6 +73,7 @@ public:
virtual bool RecvRoleChangedEvent(const uint32_t& aRole) override final;
virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
void Unbind()
{
mParent = nullptr;
@ -148,9 +144,11 @@ public:
{ return mChildDocs[aIdx]; }
#if defined(XP_WIN)
virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy,
uint32_t* aMsaaID) override;
virtual bool RecvCOMProxy(const int32_t& aMsaaID,
const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy) override;
virtual bool RecvMsaaID(const int32_t& aMsaaID) override;
#endif
private:
@ -180,11 +178,7 @@ private:
uint32_t AddSubtree(ProxyAccessible* aParent,
const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
uint32_t aIdxInParent
#if defined(XP_WIN)
, nsTArray<MsaaMapping>* aNewMsaaIds
#endif // defined(XP_WIN)
);
uint32_t aIdxInParent);
MOZ_MUST_USE bool CheckDocTree() const;
xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);

Просмотреть файл

@ -33,11 +33,10 @@ DocAccessibleChild::~DocAccessibleChild()
void
DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
{
int32_t msaaID = AccessibleWrap::GetChildIDFor(mDoc);
IAccessibleHolder parentProxy;
uint32_t msaaID = AccessibleWrap::kNoID;
PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy, &msaaID);
PDocAccessibleChild::SendCOMProxy(msaaID, aProxy, &parentProxy);
mParentProxy.reset(parentProxy.Release());
mDoc->SetID(msaaID);
}
} // namespace a11y

Просмотреть файл

@ -15,10 +15,10 @@ namespace a11y {
struct AccessibleData
{
uint64_t ID;
int32_t MsaaID;
uint32_t Role;
uint32_t ChildrenCount;
uint32_t Interfaces;
IAccessibleHolder COMProxy;
};
struct ShowEventData
@ -28,12 +28,6 @@ struct ShowEventData
AccessibleData[] NewTree;
};
struct MsaaMapping
{
uint64_t ID;
uint32_t MsaaID;
};
struct Attribute
{
nsCString Name;
@ -52,7 +46,7 @@ parent:
* event.
*/
async Event(uint64_t aID, uint32_t type);
sync ShowEventInfo(ShowEventData data) returns (MsaaMapping[] aNewMsaaIds);
async ShowEvent(ShowEventData data, bool aFromUser);
async HideEvent(uint64_t aRootID, bool aFromUser);
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
async CaretMoveEvent(uint64_t aID, int32_t aOffset);
@ -69,8 +63,10 @@ parent:
// For now we'll add the command to send the proxy here. This might move to
// PDocAccessible constructor in PBrowser.
sync COMProxy(IAccessibleHolder aDocCOMProxy)
returns(IAccessibleHolder aParentCOMProxy, uint32_t aMsaaID);
sync COMProxy(int32_t aMsaaID, IAccessibleHolder aDocCOMProxy)
returns(IAccessibleHolder aParentCOMProxy);
async MsaaID(int32_t aMsaaID);
child:
async __delete__();

Просмотреть файл

@ -19,6 +19,8 @@
#include <comutil.h>
static const VARIANT kChildIdSelf = {VT_I4};
namespace mozilla {
namespace a11y {
@ -28,6 +30,15 @@ ProxyAccessible::GetCOMInterface(void** aOutAccessible) const
if (!aOutAccessible) {
return false;
}
if (!mCOMProxy) {
// See if we can lazily obtain a COM proxy
AccessibleWrap* wrap = WrapperFor(this);
bool isDefunct = false;
ProxyAccessible* thisPtr = const_cast<ProxyAccessible*>(this);
thisPtr->mCOMProxy = wrap->GetIAccessibleFor(kChildIdSelf, &isDefunct);
}
RefPtr<IAccessible> addRefed = mCOMProxy;
addRefed.forget(aOutAccessible);
return !!mCOMProxy;
@ -42,11 +53,8 @@ ProxyAccessible::Name(nsString& aName) const
return;
}
VARIANT id;
id.vt = VT_I4;
id.lVal = CHILDID_SELF;
BSTR result;
HRESULT hr = acc->get_accName(id, &result);
HRESULT hr = acc->get_accName(kChildIdSelf, &result);
_bstr_t resultWrap(result, false);
if (FAILED(hr)) {
return;
@ -63,11 +71,8 @@ ProxyAccessible::Value(nsString& aValue) const
return;
}
VARIANT id;
id.vt = VT_I4;
id.lVal = CHILDID_SELF;
BSTR result;
HRESULT hr = acc->get_accValue(id, &result);
HRESULT hr = acc->get_accValue(kChildIdSelf, &result);
_bstr_t resultWrap(result, false);
if (FAILED(hr)) {
return;
@ -84,11 +89,8 @@ ProxyAccessible::Description(nsString& aDesc) const
return;
}
VARIANT id;
id.vt = VT_I4;
id.lVal = CHILDID_SELF;
BSTR result;
HRESULT hr = acc->get_accDescription(id, &result);
HRESULT hr = acc->get_accDescription(kChildIdSelf, &result);
_bstr_t resultWrap(result, false);
if (FAILED(hr)) {
return;
@ -105,11 +107,8 @@ ProxyAccessible::State() const
return state;
}
VARIANT id;
id.vt = VT_I4;
id.lVal = CHILDID_SELF;
VARIANT varState;
HRESULT hr = acc->get_accState(id, &varState);
HRESULT hr = acc->get_accState(kChildIdSelf, &varState);
if (FAILED(hr)) {
return state;
}
@ -130,10 +129,7 @@ ProxyAccessible::Bounds()
long top;
long width;
long height;
VARIANT id;
id.vt = VT_I4;
id.lVal = CHILDID_SELF;
HRESULT hr = acc->accLocation(&left, &top, &width, &height, id);
HRESULT hr = acc->accLocation(&left, &top, &width, &height, kChildIdSelf);
if (FAILED(hr)) {
return rect;
}

Просмотреть файл

@ -25,11 +25,8 @@ class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible>
{
public:
ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces,
const RefPtr<IAccessible>& aIAccessible)
DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces)
: ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
, mCOMProxy(aIAccessible)
{
MOZ_COUNT_CTOR(ProxyAccessible);
}

Просмотреть файл

@ -77,7 +77,8 @@
new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
new invokerChecker(EVENT_HIDE, getNode("t1_button")),
new invokerChecker(EVENT_SHOW, getNode("t1_button")),
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
new invokerChecker(EVENT_REORDER, getNode("t1_container")),
new unexpectedInvokerChecker(EVENT_REORDER, getNode("t1_checkbox"))
];
this.invoke = function removeARIAOwns_invoke()

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsEventMap.h"
#include "nsArrayUtils.h"
#include "mozilla/Preferences.h"
#include "nsIXULRuntime.h"
#include "oleacc.h"
@ -60,9 +61,9 @@ const uint32_t USE_ROLE_STRING = 0;
static gAccessibles = 0;
#endif
#ifdef _WIN64
IDSet AccessibleWrap::sIDGen;
#endif
MsaaIdGenerator AccessibleWrap::sIDGen;
static const VARIANT kVarChildIdSelf = {VT_I4};
static const int32_t kIEnumVariantDisconnected = -1;
@ -77,10 +78,9 @@ AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap::~AccessibleWrap()
{
#ifdef _WIN64
if (mID != kNoID && XRE_IsParentProcess())
sIDGen.ReleaseID(mID);
#endif
if (mID != kNoID) {
sIDGen.ReleaseID(this);
}
}
ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
@ -249,22 +249,82 @@ AccessibleWrap::get_accChild(
// IAccessible::accChild is used to return this accessible or child accessible
// at the given index or to get an accessible by child ID in the case of
// document accessible (it's handled by overriden GetXPAccessibleFor method
// on the document accessible). The getting an accessible by child ID is used
// by AccessibleObjectFromEvent() called by AT when AT handles our MSAA event.
Accessible* child = GetXPAccessibleFor(varChild);
if (!child)
// document accessible.
// The getting an accessible by child ID is used by AccessibleObjectFromEvent()
// called by AT when AT handles our MSAA event.
bool isDefunct = false;
RefPtr<IAccessible> child = GetIAccessibleFor(varChild, &isDefunct);
if (!child) {
return E_INVALIDARG;
}
if (child->IsDefunct())
if (isDefunct) {
return CO_E_OBJNOTCONNECTED;
}
*ppdispChild = NativeAccessible(child);
child.forget(ppdispChild);
return S_OK;
A11Y_TRYBLOCK_END
}
/**
* This function is a helper for implementing IAccessible methods that accept
* a Child ID as a parameter. If the child ID is CHILDID_SELF, the function
* returns S_OK but a null *aOutInterface. Otherwise, *aOutInterface points
* to the resolved IAccessible.
*
* The CHILDID_SELF case is special because in that case we actually execute
* the implementation of the IAccessible method, whereas in the non-self case,
* we delegate the method call to that object for execution.
*
* A sample invocation of this would look like:
*
* RefPtr<IAccessible> accessible;
* HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
* if (FAILED(hr)) {
* return hr;
* }
*
* if (accessible) {
* return accessible->get_accFoo(kVarChildIdSelf, pszName);
* }
*
* // Implementation for CHILDID_SELF case goes here
*/
HRESULT
AccessibleWrap::ResolveChild(const VARIANT& aVarChild,
IAccessible** aOutInterface)
{
MOZ_ASSERT(aOutInterface);
*aOutInterface = nullptr;
if (aVarChild.vt != VT_I4) {
return E_INVALIDARG;
}
if (IsDefunct()) {
return CO_E_OBJNOTCONNECTED;
}
if (aVarChild.lVal == CHILDID_SELF) {
return S_OK;
}
bool isDefunct = false;
RefPtr<IAccessible> accessible = GetIAccessibleFor(aVarChild, &isDefunct);
if (!accessible) {
return E_INVALIDARG;
}
if (isDefunct) {
return CO_E_OBJNOTCONNECTED;
}
accessible.forget(aOutInterface);
return S_OK;
}
STDMETHODIMP
AccessibleWrap::get_accName(
/* [optional][in] */ VARIANT varChild,
@ -272,23 +332,23 @@ AccessibleWrap::get_accName(
{
A11Y_TRYBLOCK_BEGIN
if (!pszName)
if (!pszName || varChild.vt != VT_I4)
return E_INVALIDARG;
*pszName = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accName(kVarChildIdSelf, pszName);
}
nsAutoString name;
xpAccessible->Name(name);
Name(name);
// The name was not provided, e.g. no alt attribute for an image. A screen
// reader may choose to invent its own accessible name, e.g. from an image src
@ -317,18 +377,18 @@ AccessibleWrap::get_accValue(
*pszValue = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accValue(kVarChildIdSelf, pszValue);
}
nsAutoString value;
xpAccessible->Value(value);
Value(value);
// See bug 438784: need to expose URL on doc's value attribute. For this,
// reverting part of fix for bug 425693 to make this MSAA method behave
@ -355,18 +415,18 @@ AccessibleWrap::get_accDescription(VARIANT varChild,
*pszDescription = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accDescription(kVarChildIdSelf, pszDescription);
}
nsAutoString description;
xpAccessible->Description(description);
Description(description);
*pszDescription = ::SysAllocStringLen(description.get(),
description.Length());
@ -387,23 +447,23 @@ AccessibleWrap::get_accRole(
VariantInit(pvarRole);
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accRole(kVarChildIdSelf, pvarRole);
}
a11y::role geckoRole;
#ifdef DEBUG
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(xpAccessible),
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(this),
"Does not support Text when it should");
#endif
geckoRole = xpAccessible->Role();
geckoRole = Role();
uint32_t msaaRole = 0;
@ -440,7 +500,7 @@ AccessibleWrap::get_accRole(
// -- Try BSTR role
// Could not map to known enumerated MSAA role like ROLE_BUTTON
// Use BSTR role to expose role attribute or tag name + namespace
nsIContent *content = xpAccessible->GetContent();
nsIContent *content = GetContent();
if (!content)
return E_FAIL;
@ -489,15 +549,15 @@ AccessibleWrap::get_accState(
pvarState->vt = VT_I4;
pvarState->lVal = 0;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accState(kVarChildIdSelf, pvarState);
}
// MSAA only has 31 states and the lowest 31 bits of our state bit mask
// are the same states as MSAA.
@ -563,19 +623,20 @@ AccessibleWrap::get_accKeyboardShortcut(
return E_INVALIDARG;
*pszKeyboardShortcut = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* acc = GetXPAccessibleFor(varChild);
if (!acc)
return E_INVALIDARG;
if (accessible) {
return accessible->get_accKeyboardShortcut(kVarChildIdSelf,
pszKeyboardShortcut);
}
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
KeyBinding keyBinding = acc->AccessKey();
KeyBinding keyBinding = AccessKey();
if (keyBinding.IsEmpty())
keyBinding = acc->KeyboardShortcut();
keyBinding = KeyboardShortcut();
nsAutoString shortcut;
keyBinding.ToString(shortcut);
@ -796,18 +857,18 @@ AccessibleWrap::get_accDefaultAction(
*pszDefaultAction = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->get_accDefaultAction(kVarChildIdSelf, pszDefaultAction);
}
nsAutoString defaultAction;
xpAccessible->ActionNameAt(0, defaultAction);
ActionNameAt(0, defaultAction);
*pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
defaultAction.Length());
@ -823,16 +884,15 @@ AccessibleWrap::accSelect(
{
A11Y_TRYBLOCK_BEGIN
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
// currently only handle focus and selection
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->accSelect(flagsSelect, kVarChildIdSelf);
}
if (flagsSelect & SELFLAG_TAKEFOCUS) {
if (XRE_IsContentProcess()) {
@ -841,26 +901,26 @@ AccessibleWrap::accSelect(
// is happening, so we dispatch TakeFocus from the main thread to
// guarantee that we are outside any IPC.
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewRunnableMethod(xpAccessible, &Accessible::TakeFocus);
mozilla::NewRunnableMethod(this, &Accessible::TakeFocus);
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
return S_OK;
}
xpAccessible->TakeFocus();
TakeFocus();
return S_OK;
}
if (flagsSelect & SELFLAG_TAKESELECTION) {
xpAccessible->TakeSelection();
TakeSelection();
return S_OK;
}
if (flagsSelect & SELFLAG_ADDSELECTION) {
xpAccessible->SetSelected(true);
SetSelected(true);
return S_OK;
}
if (flagsSelect & SELFLAG_REMOVESELECTION) {
xpAccessible->SetSelected(false);
SetSelected(false);
return S_OK;
}
@ -887,17 +947,18 @@ AccessibleWrap::accLocation(
*pcxWidth = 0;
*pcyHeight = 0;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (accessible) {
return accessible->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight,
kVarChildIdSelf);
}
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
nsIntRect rect = xpAccessible->Bounds();
nsIntRect rect = Bounds();
*pxLeft = rect.x;
*pyTop = rect.y;
@ -921,15 +982,15 @@ AccessibleWrap::accNavigate(
VariantInit(pvarEndUpAt);
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varStart, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* accessible = GetXPAccessibleFor(varStart);
if (!accessible)
return E_INVALIDARG;
if (accessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (accessible) {
return accessible->accNavigate(navDir, kVarChildIdSelf, pvarEndUpAt);
}
Accessible* navAccessible = nullptr;
Maybe<RelationType> xpRelation;
@ -941,34 +1002,34 @@ AccessibleWrap::accNavigate(
switch(navDir) {
case NAVDIR_FIRSTCHILD:
if (accessible->IsProxy()) {
if (!accessible->Proxy()->MustPruneChildren()) {
navAccessible = WrapperFor(accessible->Proxy()->FirstChild());
if (IsProxy()) {
if (!Proxy()->MustPruneChildren()) {
navAccessible = WrapperFor(Proxy()->FirstChild());
}
} else {
if (!nsAccUtils::MustPrune(accessible))
navAccessible = accessible->FirstChild();
if (!nsAccUtils::MustPrune(this))
navAccessible = FirstChild();
}
break;
case NAVDIR_LASTCHILD:
if (accessible->IsProxy()) {
if (!accessible->Proxy()->MustPruneChildren()) {
navAccessible = WrapperFor(accessible->Proxy()->LastChild());
if (IsProxy()) {
if (!Proxy()->MustPruneChildren()) {
navAccessible = WrapperFor(Proxy()->LastChild());
}
} else {
if (!nsAccUtils::MustPrune(accessible))
navAccessible = accessible->LastChild();
if (!nsAccUtils::MustPrune(this))
navAccessible = LastChild();
}
break;
case NAVDIR_NEXT:
navAccessible = accessible->IsProxy()
? WrapperFor(accessible->Proxy()->NextSibling())
: accessible->NextSibling();
navAccessible = IsProxy()
? WrapperFor(Proxy()->NextSibling())
: NextSibling();
break;
case NAVDIR_PREVIOUS:
navAccessible = accessible->IsProxy()
? WrapperFor(accessible->Proxy()->PrevSibling())
: accessible->PrevSibling();
navAccessible = IsProxy()
? WrapperFor(Proxy()->PrevSibling())
: PrevSibling();
break;
case NAVDIR_DOWN:
case NAVDIR_LEFT:
@ -1046,17 +1107,17 @@ AccessibleWrap::accDoDefaultAction(
{
A11Y_TRYBLOCK_BEGIN
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
Accessible* xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_INVALIDARG;
if (accessible) {
return accessible->accDoDefaultAction(kVarChildIdSelf);
}
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
return xpAccessible->DoAction(0) ? S_OK : E_INVALIDARG;
return DoAction(0) ? S_OK : E_INVALIDARG;
A11Y_TRYBLOCK_END
}
@ -1148,13 +1209,8 @@ AccessibleWrap::GetNativeInterface(void** aOutAccessible)
void
AccessibleWrap::SetID(uint32_t aID)
{
MOZ_ASSERT(XRE_IsContentProcess());
MOZ_ASSERT(XRE_IsParentProcess() && IsProxy());
mID = aID;
DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(Document());
DebugOnly<AccessibleWrap*> checkAcc = nullptr;
MOZ_ASSERT(!(checkAcc = doc->GetAccessibleByID(aID)) ||
checkAcc->GetExistingID() == aID);
doc->AddID(aID, this);
}
void
@ -1257,15 +1313,14 @@ AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
return 0;
}
// Content should use mID which has been generated by the chrome process.
if (XRE_IsContentProcess() && !aAccessible->IsApplication()) {
// Chrome should use mID which has been generated by the content process.
if (aAccessible->IsProxy()) {
const uint32_t id = static_cast<AccessibleWrap*>(aAccessible)->mID;
MOZ_ASSERT(id != kNoID);
return id;
}
#ifdef _WIN64
if (!aAccessible->Document() && !aAccessible->IsProxy())
if (!aAccessible->Document())
return 0;
uint32_t* id = & static_cast<AccessibleWrap*>(aAccessible)->mID;
@ -1274,27 +1329,12 @@ AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
*id = sIDGen.GetID();
if (aAccessible->IsProxy()) {
DocProxyAccessibleWrap* doc =
static_cast<AccessibleWrap*>(aAccessible)->DocProxyWrapper();
doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
} else {
DocAccessibleWrap* doc =
static_cast<DocAccessibleWrap*>(aAccessible->Document());
doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
}
MOZ_ASSERT(!aAccessible->IsProxy());
DocAccessibleWrap* doc =
static_cast<DocAccessibleWrap*>(aAccessible->Document());
doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
return *id;
#else
int32_t id = - reinterpret_cast<intptr_t>(aAccessible);
if (aAccessible->IsProxy()) {
DocProxyAccessibleWrap* doc =
static_cast<AccessibleWrap*>(aAccessible)->DocProxyWrapper();
doc->AddID(id, static_cast<AccessibleWrap*>(aAccessible));
}
return id;
#endif
}
HWND
@ -1396,83 +1436,116 @@ GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
return nullptr;
}
static AccessibleWrap*
GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc, uint32_t aID)
static already_AddRefed<IDispatch>
GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc,
const VARIANT& aVarChild)
{
auto wrapper = static_cast<DocProxyAccessibleWrap*>(WrapperFor(aDoc));
AccessibleWrap* child = wrapper->GetAccessibleByID(aID);
if (child) {
return child;
RefPtr<IAccessible> comProxy;
int32_t wrapperChildId = AccessibleWrap::GetChildIDFor(wrapper);
if (wrapperChildId == aVarChild.lVal) {
wrapper->GetNativeInterface(getter_AddRefs(comProxy));
return comProxy.forget();
}
size_t childDocs = aDoc->ChildDocCount();
for (size_t i = 0; i < childDocs; i++) {
const DocAccessibleParent* childDoc = aDoc->ChildDocAt(i);
child = GetProxiedAccessibleInSubtree(childDoc, aID);
if (child) {
return child;
}
MOZ_ASSERT(aDoc->IsTopLevel());
if (!aDoc->IsTopLevel()) {
return nullptr;
}
return nullptr;
wrapper->GetNativeInterface(getter_AddRefs(comProxy));
RefPtr<IDispatch> disp;
if (FAILED(comProxy->get_accChild(aVarChild, getter_AddRefs(disp)))) {
return nullptr;
}
return disp.forget();
}
Accessible*
AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
already_AddRefed<IAccessible>
AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
{
if (aVarChild.vt != VT_I4)
return nullptr;
// if its us real easy - this seems to always be the case
if (aVarChild.lVal == CHILDID_SELF)
return this;
VARIANT varChild = aVarChild;
MOZ_ASSERT(aIsDefunct);
*aIsDefunct = false;
RefPtr<IAccessible> result;
if (varChild.lVal == CHILDID_SELF) {
*aIsDefunct = IsDefunct();
if (*aIsDefunct) {
return nullptr;
}
GetNativeInterface(getter_AddRefs(result));
if (result) {
return result.forget();
}
// If we're not a proxy, there's nothing more we can do to attempt to
// resolve the IAccessible, so we just fail.
if (!IsProxy()) {
return nullptr;
}
// Otherwise, since we're a proxy and we have a null native interface, this
// indicates that we need to obtain a COM proxy. To do this, we'll replace
// CHILDID_SELF with our real MSAA ID and continue the search from there.
varChild.lVal = GetExistingID();
}
if (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this)) {
return nullptr;
}
if (aVarChild.lVal > 0) {
// Gecko child indices are 0-based in contrast to indices used in MSAA.
if (IsProxy()) {
if (static_cast<uint32_t>(aVarChild.lVal) > Proxy()->ChildrenCount()) {
return nullptr;
}
// If the MSAA ID is not a chrome id then we already know that we won't
// find it here and should look remotely instead.
if (XRE_IsParentProcess() && !sIDGen.IsChromeID(varChild.lVal)) {
return GetRemoteIAccessibleFor(varChild);
}
MOZ_ASSERT(XRE_IsParentProcess() ||
sIDGen.IsIDForThisContentProcess(varChild.lVal));
return WrapperFor(Proxy()->ChildAt(aVarChild.lVal - 1));
} else {
return GetChildAt(aVarChild.lVal - 1);
if (varChild.lVal > 0) {
// Gecko child indices are 0-based in contrast to indices used in MSAA.
MOZ_ASSERT(!IsProxy());
Accessible* xpAcc = GetChildAt(varChild.lVal - 1);
if (!xpAcc) {
return nullptr;
}
*aIsDefunct = xpAcc->IsDefunct();
static_cast<AccessibleWrap*>(xpAcc)->GetNativeInterface(getter_AddRefs(result));
return result.forget();
}
// If lVal negative then it is treated as child ID and we should look for
// accessible through whole accessible subtree including subdocuments.
// Otherwise we treat lVal as index in parent.
// Convert child ID to unique ID.
// First handle the case that both this accessible and the id'd one are in
// this process.
if (!IsProxy()) {
void* uniqueID = reinterpret_cast<void*>(intptr_t(-aVarChild.lVal));
DocAccessible* document = Document();
Accessible* child =
#ifdef _WIN64
GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
#else
XRE_IsContentProcess() ?
GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal)) :
document->GetAccessibleByUniqueIDInSubtree(uniqueID);
#endif
GetAccessibleInSubtree(document, static_cast<uint32_t>(varChild.lVal));
// If it is a document then just return an accessible.
if (child && IsDoc())
return child;
if (child && IsDoc()) {
*aIsDefunct = child->IsDefunct();
static_cast<AccessibleWrap*>(child)->GetNativeInterface(getter_AddRefs(result));
return result.forget();
}
// Otherwise check whether the accessible is a child (this path works for
// ARIA documents and popups).
Accessible* parent = child;
while (parent && parent != document) {
if (parent == this)
return child;
if (parent == this) {
*aIsDefunct = child->IsDefunct();
static_cast<AccessibleWrap*>(child)->GetNativeInterface(getter_AddRefs(result));
return result.forget();
}
parent = parent->Parent();
}
@ -1480,34 +1553,26 @@ AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
// Now see about the case that both this accessible and the target one are
// proxied.
uint32_t id = aVarChild.lVal;
if (IsProxy()) {
DocAccessibleParent* proxyDoc = Proxy()->Document();
AccessibleWrap* wrapper = GetProxiedAccessibleInSubtree(proxyDoc, id);
if (!wrapper)
RefPtr<IDispatch> disp = GetProxiedAccessibleInSubtree(proxyDoc, varChild);
if (!disp) {
return nullptr;
MOZ_ASSERT(wrapper->IsProxy());
if (proxyDoc == this->Proxy()) {
return wrapper;
}
ProxyAccessible* parent = wrapper->Proxy();
while (parent && parent != proxyDoc) {
if (parent == this->Proxy()) {
return wrapper;
}
parent = parent->Parent();
}
return nullptr;
MOZ_ASSERT(mscom::IsProxy(disp));
DebugOnly<HRESULT> hr = disp->QueryInterface(IID_IAccessible,
getter_AddRefs(result));
MOZ_ASSERT(SUCCEEDED(hr));
return result.forget();
}
// Finally we need to handle the case that this accessible is in the main
// process, but the target is proxied. This is the case when the target
// accessible is in a child document of this one.
return nullptr;
}
already_AddRefed<IAccessible>
AccessibleWrap::GetRemoteIAccessibleFor(const VARIANT& aVarChild)
{
DocAccessibleParent* proxyDoc = nullptr;
DocAccessible* doc = Document();
const nsTArray<DocAccessibleParent*>* remoteDocs =
@ -1516,9 +1581,18 @@ AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
return nullptr;
}
RefPtr<IAccessible> result;
size_t docCount = remoteDocs->Length();
for (size_t i = 0; i < docCount; i++) {
Accessible* outerDoc = remoteDocs->ElementAt(i)->OuterDocOfRemoteBrowser();
DocAccessibleParent* remoteDoc = remoteDocs->ElementAt(i);
uint32_t remoteDocMsaaId = WrapperFor(remoteDoc)->GetExistingID();
if (!sIDGen.IsSameContentProcessFor(aVarChild.lVal, remoteDocMsaaId)) {
continue;
}
Accessible* outerDoc = remoteDoc->OuterDocOfRemoteBrowser();
if (!outerDoc) {
continue;
}
@ -1527,28 +1601,16 @@ AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
continue;
}
if (doc == this) {
AccessibleWrap* proxyWrapper =
GetProxiedAccessibleInSubtree(remoteDocs->ElementAt(i), id);
if (proxyWrapper) {
return proxyWrapper;
}
RefPtr<IDispatch> disp =
GetProxiedAccessibleInSubtree(remoteDoc, aVarChild);
if (!disp) {
continue;
}
Accessible* parent = outerDoc;
while (parent && parent != doc) {
if (parent == this) {
AccessibleWrap* proxyWrapper =
GetProxiedAccessibleInSubtree(remoteDocs->ElementAt(i), id);
if (proxyWrapper) {
return proxyWrapper;
}
}
parent = parent->Parent();
}
DebugOnly<HRESULT> hr = disp->QueryInterface(IID_IAccessible,
getter_AddRefs(result));
MOZ_ASSERT(SUCCEEDED(hr));
return result.forget();
}
return nullptr;
@ -1603,3 +1665,17 @@ AccessibleWrap::GetTI(LCID lcid)
return gTypeInfo;
}
/* static */
uint32_t
AccessibleWrap::GetContentProcessIdFor(dom::ContentParentId aIPCContentId)
{
return sIDGen.GetContentProcessIDFor(aIPCContentId);
}
/* static */
void
AccessibleWrap::ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId)
{
sIDGen.ReleaseContentProcessIDFor(aIPCContentId);
}

Просмотреть файл

@ -14,8 +14,9 @@
#include "ia2AccessibleComponent.h"
#include "ia2AccessibleHyperlink.h"
#include "ia2AccessibleValue.h"
#include "mozilla/a11y/MsaaIdGenerator.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "mozilla/a11y/IDSet.h"
#include "mozilla/Attributes.h"
#ifdef __GNUC__
// Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
@ -173,7 +174,8 @@ public: // construction, destruction
/**
* Find an accessible by the given child ID in cached documents.
*/
Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
MOZ_MUST_USE already_AddRefed<IAccessible>
GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct);
virtual void GetNativeInterface(void **aOutAccessible) override;
@ -181,14 +183,25 @@ public: // construction, destruction
uint32_t GetExistingID() const { return mID; }
static const uint32_t kNoID = 0;
// This is only valid to call in content
void SetID(uint32_t aID);
static uint32_t GetContentProcessIdFor(dom::ContentParentId aIPCContentId);
static void ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId);
protected:
virtual ~AccessibleWrap();
uint32_t mID;
HRESULT
ResolveChild(const VARIANT& aVarChild, IAccessible** aOutInterface);
/**
* Find a remote accessible by the given child ID.
*/
MOZ_MUST_USE already_AddRefed<IAccessible>
GetRemoteIAccessibleFor(const VARIANT& aVarChild);
/**
* Return the wrapper for the document's proxy.
*/
@ -201,9 +214,7 @@ protected:
static ITypeInfo* gTypeInfo;
#ifdef _WIN64
static IDSet sIDGen;
#endif
static MsaaIdGenerator sIDGen;
enum navRelations {
NAVRELATION_CONTROLLED_BY = 0x1000,

Просмотреть файл

@ -19,19 +19,29 @@ namespace mozilla {
namespace a11y {
/**
* On windows an accessible's id must be a negative 32 bit integer. It is
* On windows an accessible's id must be a negative 32 bit integer. It is
* important to support recycling arbitrary IDs because accessibles can be
* created and destroyed at any time in the life of a page. IDSet provides 2
* operations: generate an ID in the range [ - 2^31, 0 ), and release an ID so
* operations: generate an ID in the range (0, mMaxId], and release an ID so
* it can be allocated again. Allocated ID are tracked by a sparse bitmap
* implemented with a splay tree. Nodes in the tree are keyed by the upper N
* bits of the bitwise negation of the ID, and the node contains a bitmap
* tracking the allocation of 2^(32 - N) IDs.
* bits of the ID, and the node contains a bitmap tracking the allocation of
* 2^(ceil(log2(mMaxId)) - N) IDs.
*
* Note that negation is handled by MsaaIdGenerator as it performs additional
* decoration on the ID generated by IDSet.
* @see mozilla::a11y::MsaaIdGenerator
*/
class IDSet
{
public:
constexpr IDSet() : mBitSet(), mIdx(0) {}
constexpr explicit IDSet(const uint32_t aMaxIdBits)
: mBitSet()
, mIdx(0)
, mMaxId((1UL << aMaxIdBits) - 1UL)
, mMaxIdx(mMaxId / bitsPerElt)
{
}
/**
* Return a new unique id.
@ -46,7 +56,7 @@ public:
elt->mBitvec[0] |= (1ull << i);
mIdx = idx;
return ~(elt->mIdx * bitsPerElt + i);
return (elt->mIdx * bitsPerElt + i);
}
if (elt->mBitvec[1] != UINT64_MAX) {
@ -54,11 +64,11 @@ public:
elt->mBitvec[1] |= (1ull << i);
mIdx = idx;
return ~(elt->mIdx * bitsPerElt + bitsPerWord + i);
return (elt->mIdx * bitsPerElt + bitsPerWord + i);
}
idx++;
if (idx > sMaxIdx) {
if (idx > mMaxIdx) {
idx = 0;
}
@ -73,8 +83,7 @@ public:
*/
void ReleaseID(uint32_t aID)
{
aID = ~aID;
MOZ_ASSERT(aID < static_cast<uint32_t>(INT32_MAX));
MOZ_ASSERT(aID < mMaxId);
uint32_t idx = aID / bitsPerElt;
mIdx = idx;
@ -92,7 +101,6 @@ private:
static const unsigned int wordsPerElt = 2;
static const unsigned int bitsPerWord = 64;
static const unsigned int bitsPerElt = wordsPerElt * bitsPerWord;
static const uint32_t sMaxIdx = INT32_MAX / bitsPerElt;
struct BitSetElt : mozilla::SplayTreeNode<BitSetElt>
{
@ -118,6 +126,8 @@ private:
SplayTree<BitSetElt, BitSetElt> mBitSet;
uint32_t mIdx;
const uint32_t mMaxId;
const uint32_t mMaxIdx;
};
}

Просмотреть файл

@ -0,0 +1,246 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MsaaIdGenerator.h"
#include "mozilla/a11y/AccessibleWrap.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Unused.h"
#include "nsDataHashtable.h"
#include "nsIXULRuntime.h"
// These constants may be adjusted to modify the proportion of the Child ID
// allocated to the content ID vs proportion allocated to the unique ID. They
// must always sum to 31, ie. the width of a 32-bit integer less the sign bit.
// NB: kNumContentProcessIDBits must be large enough to successfully hold the
// maximum permitted number of e10s content processes. If the e10s maximum
// number of content processes changes, then kNumContentProcessIDBits must also
// be updated if necessary to accommodate that new value!
static const uint32_t kNumContentProcessIDBits = 7UL;
static const uint32_t kNumUniqueIDBits = (31UL - kNumContentProcessIDBits);
static_assert(kNumContentProcessIDBits + kNumUniqueIDBits == 31,
"Allocation of Content ID bits and Unique ID bits must sum to 31");
namespace mozilla {
namespace a11y {
namespace detail {
typedef nsDataHashtable<nsUint64HashKey, uint32_t> ContentParentIdMap;
#pragma pack(push, 1)
union MsaaID
{
int32_t mInt32;
uint32_t mUInt32;
struct
{
uint32_t mUniqueID:kNumUniqueIDBits;
uint32_t mContentProcessID:kNumContentProcessIDBits;
uint32_t mSignBit:1;
}
mCracked;
};
#pragma pack(pop)
static uint32_t
BuildMsaaID(const uint32_t aID, const uint32_t aContentProcessID)
{
MsaaID id;
id.mCracked.mSignBit = 0;
id.mCracked.mUniqueID = aID;
id.mCracked.mContentProcessID = aContentProcessID;
return ~id.mUInt32;
}
class MsaaIDCracker
{
public:
explicit MsaaIDCracker(const uint32_t aMsaaID)
{
mID.mUInt32 = ~aMsaaID;
}
uint32_t GetContentProcessId()
{
return mID.mCracked.mContentProcessID;
}
uint32_t GetUniqueId()
{
return mID.mCracked.mUniqueID;
}
private:
MsaaID mID;
};
} // namespace detail
constexpr MsaaIdGenerator::MsaaIdGenerator()
: mIDSet(kNumUniqueIDBits)
, mContentProcessID(0)
{}
uint32_t
MsaaIdGenerator::GetID()
{
static const uint32_t kContentProcessId = ResolveContentProcessID();
uint32_t id = mIDSet.GetID();
MOZ_ASSERT(id <= ((1UL << kNumUniqueIDBits) - 1UL));
return detail::BuildMsaaID(id, kContentProcessId);
}
void
MsaaIdGenerator::ReleaseID(AccessibleWrap* aAccWrap)
{
MOZ_ASSERT(aAccWrap);
uint32_t id = aAccWrap->GetExistingID();
MOZ_ASSERT(id != AccessibleWrap::kNoID);
detail::MsaaIDCracker cracked(id);
if (cracked.GetContentProcessId() != mContentProcessID) {
// This may happen if chrome holds a proxy whose ID was originally generated
// by a content process. Since ReleaseID only has meaning in the process
// that originally generated that ID, we ignore ReleaseID calls for any ID
// that did not come from the current process.
MOZ_ASSERT(aAccWrap->IsProxy());
return;
}
mIDSet.ReleaseID(cracked.GetUniqueId());
}
bool
MsaaIdGenerator::IsChromeID(uint32_t aID)
{
detail::MsaaIDCracker cracked(aID);
return cracked.GetContentProcessId() == 0;
}
bool
MsaaIdGenerator::IsIDForThisContentProcess(uint32_t aID)
{
MOZ_ASSERT(XRE_IsContentProcess());
static const uint32_t kContentProcessId = ResolveContentProcessID();
detail::MsaaIDCracker cracked(aID);
return cracked.GetContentProcessId() == kContentProcessId;
}
bool
MsaaIdGenerator::IsIDForContentProcess(uint32_t aID,
dom::ContentParentId aIPCContentProcessId)
{
MOZ_ASSERT(XRE_IsParentProcess());
detail::MsaaIDCracker cracked(aID);
return cracked.GetContentProcessId() ==
GetContentProcessIDFor(aIPCContentProcessId);
}
bool
MsaaIdGenerator::IsSameContentProcessFor(uint32_t aFirstID, uint32_t aSecondID)
{
detail::MsaaIDCracker firstCracked(aFirstID);
detail::MsaaIDCracker secondCracked(aSecondID);
return firstCracked.GetContentProcessId() ==
secondCracked.GetContentProcessId();
}
uint32_t
MsaaIdGenerator::ResolveContentProcessID()
{
if (XRE_IsParentProcess()) {
return 0;
}
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
Unused << contentChild->SendGetA11yContentId(&mContentProcessID);
MOZ_ASSERT(mContentProcessID);
return mContentProcessID;
}
/**
* Each dom::ContentParent has a 64-bit ID. This ID is monotonically increasing
* with each new content process, so those IDs are effectively single-use. OTOH,
* MSAA requires 32-bit IDs. Since we only allocate kNumContentProcessIDBits for
* the content process ID component, the MSAA content process ID value must be
* reusable. sContentParentIdMap holds the current associations between
* dom::ContentParent IDs and the MSAA content parent IDs that have been
* allocated to them.
*/
static StaticAutoPtr<detail::ContentParentIdMap> sContentParentIdMap;
static const uint32_t kBitsPerByte = 8UL;
// Set sContentProcessIdBitmap[0] to 1 to reserve the Chrome process's id
static uint64_t sContentProcessIdBitmap[(1UL << kNumContentProcessIDBits) /
(sizeof(uint64_t) * kBitsPerByte)] = {1ULL};
static const uint32_t kBitsPerElement = sizeof(sContentProcessIdBitmap[0]) *
kBitsPerByte;
uint32_t
MsaaIdGenerator::GetContentProcessIDFor(dom::ContentParentId aIPCContentProcessID)
{
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
if (!sContentParentIdMap) {
sContentParentIdMap = new detail::ContentParentIdMap();
ClearOnShutdown(&sContentParentIdMap);
}
uint32_t value = 0;
if (sContentParentIdMap->Get(aIPCContentProcessID, &value)) {
return value;
}
uint32_t index = 0;
for (; index < ArrayLength(sContentProcessIdBitmap); ++index) {
if (sContentProcessIdBitmap[index] == UINT64_MAX) {
continue;
}
uint32_t bitIndex = CountTrailingZeroes64(~sContentProcessIdBitmap[index]);
MOZ_ASSERT(!(sContentProcessIdBitmap[index] & (1ULL << bitIndex)));
MOZ_ASSERT(bitIndex != 0 || index != 0);
sContentProcessIdBitmap[index] |= (1ULL << bitIndex);
value = index * kBitsPerElement + bitIndex;
break;
}
// If we run out of content process IDs, we're in trouble
MOZ_RELEASE_ASSERT(index < ArrayLength(sContentProcessIdBitmap));
sContentParentIdMap->Put(aIPCContentProcessID, value);
return value;
}
void
MsaaIdGenerator::ReleaseContentProcessIDFor(dom::ContentParentId aIPCContentProcessID)
{
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
if (!sContentParentIdMap) {
// Since Content IDs are generated lazily, ContentParent might attempt
// to release an ID that was never allocated to begin with.
return;
}
Maybe<uint32_t> mapping = sContentParentIdMap->GetAndRemove(aIPCContentProcessID);
if (!mapping) {
// Since Content IDs are generated lazily, ContentParent might attempt
// to release an ID that was never allocated to begin with.
return;
}
uint32_t index = mapping.ref() / kBitsPerElement;
MOZ_ASSERT(index < ArrayLength(sContentProcessIdBitmap));
uint64_t mask = 1ULL << (mapping.ref() % kBitsPerElement);
MOZ_ASSERT(sContentProcessIdBitmap[index] & mask);
sContentProcessIdBitmap[index] &= ~mask;
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_MsaaIdGenerator_h
#define mozilla_a11y_MsaaIdGenerator_h
#include "mozilla/a11y/IDSet.h"
#include "mozilla/dom/ipc/IdType.h"
namespace mozilla {
namespace a11y {
class AccessibleWrap;
/**
* This class is responsible for generating child IDs used by our MSAA
* implementation. Since e10s requires us to differentiate IDs based on the
* originating process of the accessible, a portion of the ID's bits are
* allocated to storing that information. The remaining bits represent the
* unique ID of the accessible, within that content process.
*
* The constants kNumContentProcessIDBits and kNumUniqueIDBits in the
* implementation are responsible for determining the proportion of bits that
* are allocated for each purpose.
*/
class MsaaIdGenerator
{
public:
constexpr MsaaIdGenerator();
uint32_t GetID();
void ReleaseID(AccessibleWrap* aAccWrap);
bool IsChromeID(uint32_t aID);
bool IsIDForThisContentProcess(uint32_t aID);
bool IsIDForContentProcess(uint32_t aID,
dom::ContentParentId aIPCContentProcessId);
bool IsSameContentProcessFor(uint32_t aFirstID, uint32_t aSecondID);
uint32_t GetContentProcessIDFor(dom::ContentParentId aIPCContentProcessID);
void ReleaseContentProcessIDFor(dom::ContentParentId aIPCContentProcessID);
private:
uint32_t ResolveContentProcessID();
private:
IDSet mIDSet;
uint32_t mContentProcessID;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_MsaaIdGenerator_h

Просмотреть файл

@ -85,20 +85,6 @@ a11y::ProxyDestroyed(ProxyAccessible* aProxy)
if (!wrapper)
return;
auto doc =
static_cast<DocProxyAccessibleWrap*>(WrapperFor(aProxy->Document()));
MOZ_ASSERT(doc);
if (doc) {
#ifdef _WIN64
uint32_t id = wrapper->GetExistingID();
if (id != AccessibleWrap::kNoID) {
doc->RemoveID(id);
}
#else
doc->RemoveID(-reinterpret_cast<int32_t>(wrapper));
#endif
}
wrapper->Shutdown();
aProxy->SetWrapper(0);
wrapper->Release();

Просмотреть файл

@ -13,6 +13,7 @@ EXPORTS.mozilla.a11y += [
'Compatibility.h',
'HyperTextAccessibleWrap.h',
'IDSet.h',
'MsaaIdGenerator.h',
]
UNIFIED_SOURCES += [
@ -28,6 +29,7 @@ UNIFIED_SOURCES += [
'HyperTextAccessibleWrap.cpp',
'ImageAccessibleWrap.cpp',
'IUnknownImpl.cpp',
'MsaaIdGenerator.cpp',
'nsWinUtils.cpp',
'Platform.cpp',
'RootAccessibleWrap.cpp',

Просмотреть файл

@ -19,4 +19,6 @@ LOCAL_INCLUDES += [
'/accessible/xul',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -17,4 +17,6 @@ LOCAL_INCLUDES += [
'/accessible/xul',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -47,6 +47,8 @@ else:
'/accessible/other',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:

Просмотреть файл

@ -385,7 +385,10 @@ var FullScreen = {
break;
}
case "DOMFullscreen:NewOrigin": {
PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
// Don't show the warning if we've already exit fullscreen.
if (document.fullscreen) {
PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
}
break;
}
case "DOMFullscreen:Exit": {
@ -410,6 +413,18 @@ var FullScreen = {
// before transition.
PointerlockFsWarning.close();
// If it is a remote browser, send a message to ask the content
// to enter fullscreen state. We don't need to do so if it is an
// in-process browser, since all related document should have
// entered fullscreen state at this point.
// This should be done before the active tab check below to ensure
// that the content document handles the pending request. Doing so
// before the check is fine since we also check the activeness of
// the requesting document in content-side handling code.
if (this._isRemoteBrowser(aBrowser)) {
aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
}
// If we've received a fullscreen notification, we have to ensure that the
// element that's requesting fullscreen belongs to the browser that's currently
// active. If not, we exit fullscreen since the "full-screen document" isn't
@ -424,14 +439,6 @@ var FullScreen = {
return;
}
// If it is a remote browser, send a message to ask the content
// to enter fullscreen state. We don't need to do so if it is an
// in-process browser, since all related document should have
// entered fullscreen state at this point.
if (this._isRemoteBrowser(aBrowser)) {
aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
}
document.documentElement.setAttribute("inDOMFullscreen", true);
if (gFindBarInitialized) {

Просмотреть файл

@ -54,6 +54,8 @@ PluginContent.prototype = {
global.addMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
global.addMessageListener("BrowserPlugins:CrashReportSubmitted", this);
global.addMessageListener("BrowserPlugins:Test:ClearCrashData", this);
Services.obs.addObserver(this, "decoder-doctor-notification", false);
},
uninit: function() {
@ -75,6 +77,9 @@ PluginContent.prototype = {
global.removeMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
global.removeMessageListener("BrowserPlugins:CrashReportSubmitted", this);
global.removeMessageListener("BrowserPlugins:Test:ClearCrashData", this);
Services.obs.removeObserver(this, "decoder-doctor-notification");
delete this.global;
delete this.content;
},
@ -118,6 +123,26 @@ PluginContent.prototype = {
}
},
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "decoder-doctor-notification":
let data = JSON.parse(aData);
if (this.haveShownNotification &&
aSubject.top.document == this.content.document &&
data.formats.toLowerCase().includes("application/x-mpegurl", 0)) {
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let principal = this.content.document.nodePrincipal;
let location = this.content.document.location.href;
this.global.content.pluginRequiresReload = true;
this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification",
{ plugins: [... this.pluginData.values()],
showNow: true,
location: location,
}, null, principal);
}
}
},
onPageShow: function (event) {
// Ignore events that aren't from the main document.
if (!this.content || event.target != this.content.document) {
@ -140,6 +165,7 @@ PluginContent.prototype = {
this._finishRecordingFlashPluginTelemetry();
this.clearPluginCaches();
this.haveShownNotification = false;
},
getPluginUI: function (plugin, anonid) {
@ -725,9 +751,11 @@ PluginContent.prototype = {
}
}
// If there are no instances of the plugin on the page any more, what the
// If there are no instances of the plugin on the page any more or if we've
// noted that the content needs to be reloaded due to replacing HLS, what the
// user probably needs is for us to allow and then refresh.
if (newState != "block" && !pluginFound) {
if (newState != "block" &&
(!pluginFound || contentWindow.pluginRequiresReload)) {
this.reloadPage();
}
this.updateNotificationUI();
@ -789,6 +817,8 @@ PluginContent.prototype = {
this.pluginData.set(pluginInfo.permissionString, pluginInfo);
}
this.haveShownNotification = true;
this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", {
plugins: [... this.pluginData.values()],
showNow: showNow,

Просмотреть файл

@ -25,7 +25,9 @@ if test -n "$MOZ_ASAN"; then
fi
CFLAGS="-fsanitize=address $CFLAGS"
CXXFLAGS="-fsanitize=address $CXXFLAGS"
LDFLAGS="-fsanitize=address $LDFLAGS"
if test -z "$CLANG_CL"; then
LDFLAGS="-fsanitize=address $LDFLAGS"
fi
AC_DEFINE(MOZ_ASAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi
@ -42,7 +44,9 @@ if test -n "$MOZ_MSAN"; then
MOZ_LLVM_HACKS=1
CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CFLAGS"
CXXFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CXXFLAGS"
LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $LDFLAGS"
if test -z "$CLANG_CL"; then
LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $LDFLAGS"
fi
AC_DEFINE(MOZ_MSAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi
@ -59,7 +63,9 @@ if test -n "$MOZ_TSAN"; then
MOZ_LLVM_HACKS=1
CFLAGS="-fsanitize=thread $CFLAGS"
CXXFLAGS="-fsanitize=thread $CXXFLAGS"
LDFLAGS="-fsanitize=thread $LDFLAGS"
if test -z "$CLANG_CL"; then
LDFLAGS="-fsanitize=thread $LDFLAGS"
fi
AC_DEFINE(MOZ_TSAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi

Просмотреть файл

@ -334,6 +334,13 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
bool aIgnoreSandboxing)
{
NS_PRECONDITION(aChannel, "Must have channel!");
// Check whether we have an nsILoadInfo that says what we should do.
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (loadInfo && loadInfo->GetForceInheritPrincipalOverruleOwner()) {
NS_ADDREF(*aPrincipal = loadInfo->PrincipalToInherit());
return NS_OK;
}
nsCOMPtr<nsISupports> owner;
aChannel->GetOwner(getter_AddRefs(owner));
if (owner) {
@ -343,9 +350,6 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
}
}
// Check whether we have an nsILoadInfo that says what we should do.
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
if (loadInfo) {
if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
RefPtr<nsNullPrincipal> prin;

Просмотреть файл

@ -108,3 +108,4 @@ support-files = file_framedhistoryframes.html
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug1121701.html]
skip-if = (buildapp == 'b2g' || buildapp == 'mulet')
[test_forceinheritprincipal_overrule_owner.html]

Просмотреть файл

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="text/javascript">
var channel = SpecialPowers.wrap(document).docShell.currentDocumentChannel;
var loadInfo = channel.loadInfo;
// 1) perform some sanity checks
var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
var principalToInherit = channel.loadInfo.principalToInherit.URI.asciiSpec;
ok(triggeringPrincipal.startsWith("http://mochi.test:8888/"),
"initial triggeringPrincipal correct");
ok(loadingPrincipal.startsWith("http://mochi.test:8888/"),
"initial loadingPrincipal correct");
ok(principalToInherit.startsWith("http://mochi.test:8888/"),
"initial principalToInherit correct");
// reset principals on the loadinfo
loadInfo.resetPrincipalsToNullPrincipal();
// 2) verify loadInfo contains the correct principals
var triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
var loadingPrincipal = channel.loadInfo.loadingPrincipal;
var principalToInherit = channel.loadInfo.principalToInherit;
ok(triggeringPrincipal.isNullPrincipal,
"triggeringPrincipal after resetting correct");
ok(loadingPrincipal.isNullPrincipal,
"triggeringPrincipal after resetting correct");
ok(triggeringPrincipal.isNullPrincipal,
"principalToInherit after resetting correct");
// 3) verify that getChannelResultPrincipal returns right principal
var resultPrincipal = SpecialPowers.Services.scriptSecurityManager
.getChannelResultPrincipal(channel);
ok(resultPrincipal.isNullPrincipal,
"resultPrincipal after resetting correct");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1195,20 +1195,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
return NS_ERROR_NOT_IMPLEMENTED;
}
bool ourPassPointerEvents =
ourContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::mozpasspointerevents,
nsGkAtoms::_true,
eCaseMatters);
bool otherPassPointerEvents =
otherContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::mozpasspointerevents,
nsGkAtoms::_true,
eCaseMatters);
if (ourPassPointerEvents != otherPassPointerEvents) {
return NS_ERROR_NOT_IMPLEMENTED;
}
bool ourFullscreenAllowed =
ourContent->IsXULElement() ||
(OwnerIsMozBrowserOrAppFrame() &&
@ -2662,13 +2648,6 @@ nsFrameLoader::TryRemoteBrowser()
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
}
if (mOwnerContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::mozpasspointerevents,
nsGkAtoms::_true,
eCaseMatters)) {
Unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
}
ReallyLoadFrameScripts();
InitializeBrowserAPI();
@ -2708,20 +2687,6 @@ nsFrameLoader::DeactivateRemoteFrame() {
return NS_ERROR_UNEXPECTED;
}
void
nsFrameLoader::ActivateUpdateHitRegion() {
if (mRemoteBrowser) {
Unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
}
}
void
nsFrameLoader::DeactivateUpdateHitRegion() {
if (mRemoteBrowser) {
Unused << mRemoteBrowser->SendSetUpdateHitRegion(false);
}
}
NS_IMETHODIMP
nsFrameLoader::SendCrossProcessMouseEvent(const nsAString& aType,
float aX,

Просмотреть файл

@ -218,9 +218,6 @@ public:
void GetURL(nsString& aURL);
void ActivateUpdateHitRegion();
void DeactivateUpdateHitRegion();
// Properly retrieves documentSize of any subdocument type.
nsresult GetWindowDimensions(nsIntRect& aRect);

Просмотреть файл

@ -628,7 +628,6 @@ GK_ATOM(mouseup, "mouseup")
GK_ATOM(mozaudiochannel, "mozaudiochannel")
GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
GK_ATOM(mozpasspointerevents, "mozpasspointerevents")
GK_ATOM(mozpointerlockchange, "mozpointerlockchange")
GK_ATOM(mozpointerlockerror, "mozpointerlockerror")
GK_ATOM(mozprivatebrowsing, "mozprivatebrowsing")

Просмотреть файл

@ -6112,12 +6112,16 @@ nsGlobalWindow::SetFullScreen(bool aFullScreen)
return SetFullscreenInternal(FullscreenReason::ForFullscreenMode, aFullScreen);
}
void
static void
FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen)
{
if (aInDOMFullscreen) {
// Ask the document to handle any pending DOM fullscreen change.
nsIDocument::HandlePendingFullscreenRequests(aDoc);
if (!nsIDocument::HandlePendingFullscreenRequests(aDoc)) {
// If we don't end up having anything in fullscreen,
// async request exiting fullscreen.
nsIDocument::AsyncExitFullscreen(aDoc);
}
} else {
// If the window is leaving fullscreen state, also ask the document
// to exit from DOM Fullscreen.

Просмотреть файл

@ -660,7 +660,7 @@ nsImageLoadingContent::ForceReload(const mozilla::dom::Optional<bool>& aNotify,
ImageLoadType loadType = \
(mCurrentRequestFlags & REQUEST_IS_IMAGESET) ? eImageLoadType_Imageset
: eImageLoadType_Normal;
nsresult rv = LoadImage(currentURI, true, notify, loadType, nullptr,
nsresult rv = LoadImage(currentURI, true, notify, loadType, true, nullptr,
nsIRequest::VALIDATE_ALWAYS);
if (NS_FAILED(rv)) {
aError.Throw(rv);
@ -751,7 +751,10 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
return NS_OK;
}
// Second, parse the URI string to get image URI
// Fire loadstart event
FireEvent(NS_LITERAL_STRING("loadstart"));
// Parse the URI string to get image URI
nsCOMPtr<nsIURI> imageURI;
nsresult rv = StringToURI(aNewURI, doc, getter_AddRefs(imageURI));
if (NS_FAILED(rv)) {
@ -764,7 +767,7 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
NS_TryToSetImmutable(imageURI);
return LoadImage(imageURI, aForce, aNotify, aImageLoadType, doc);
return LoadImage(imageURI, aForce, aNotify, aImageLoadType, false, doc);
}
nsresult
@ -772,9 +775,15 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
bool aForce,
bool aNotify,
ImageLoadType aImageLoadType,
bool aLoadStart,
nsIDocument* aDocument,
nsLoadFlags aLoadFlags)
{
// Fire loadstart event if required
if (aLoadStart) {
FireEvent(NS_LITERAL_STRING("loadstart"));
}
if (!mLoadingEnabled) {
// XXX Why fire an error here? seems like the callers to SetLoadingEnabled
// don't want/need it.

Просмотреть файл

@ -126,13 +126,15 @@ protected:
* @param aNotify If true, nsIDocumentObserver state change notifications
* will be sent as needed.
* @param aImageLoadType The ImageLoadType for this request
* @param aLoadStart If true, dispatch "loadstart" event.
* @param aDocument Optional parameter giving the document this node is in.
* This is purely a performance optimization.
* @param aLoadFlags Optional parameter specifying load flags to use for
* the image load
*/
nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify,
ImageLoadType aImageLoadType, nsIDocument* aDocument = nullptr,
ImageLoadType aImageLoadType, bool aLoadStart = true,
nsIDocument* aDocument = nullptr,
nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
/**

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsContentUtils.h"
#include "nsIPermissionManager.h"
#include "nsIDocument.h"
#include "nsIBlocklistService.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -360,7 +361,10 @@ nsPluginArray::EnsurePlugins()
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
} else if (pluginTag->IsActive()) {
uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
if (pluginTag->IsClicktoplay()) {
uint32_t blocklistState;
if (pluginTag->IsClicktoplay() &&
NS_SUCCEEDED(pluginTag->GetBlocklistState(&blocklistState)) &&
blocklistState == nsIBlocklistService::STATE_NOT_BLOCKED) {
nsCString name;
pluginTag->GetName(name);
if (PluginShouldBeHidden(name)) {

Просмотреть файл

@ -4440,39 +4440,6 @@ CanvasRenderingContext2D::GetLineJoin(nsAString& aLinejoinStyle, ErrorResult& aE
}
}
void
CanvasRenderingContext2D::SetMozDash(JSContext* aCx,
const JS::Value& aMozDash,
ErrorResult& aError)
{
nsTArray<Float> dash;
aError = JSValToDashArray(aCx, aMozDash, dash);
if (!aError.Failed()) {
ContextState& state = CurrentState();
state.dash = Move(dash);
if (state.dash.IsEmpty()) {
state.dashOffset = 0;
}
}
}
void
CanvasRenderingContext2D::GetMozDash(JSContext* aCx,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aError)
{
DashArrayToJSVal(CurrentState().dash, aCx, aRetval, aError);
}
void
CanvasRenderingContext2D::SetMozDashOffset(double aMozDashOffset)
{
ContextState& state = CurrentState();
if (!state.dash.IsEmpty()) {
state.dashOffset = aMozDashOffset;
}
}
void
CanvasRenderingContext2D::SetLineDash(const Sequence<double>& aSegments,
ErrorResult& aRv)

Просмотреть файл

@ -365,10 +365,6 @@ public:
mozilla::ErrorResult& aError);
void GetFillRule(nsAString& aFillRule);
void SetFillRule(const nsAString& aFillRule);
void GetMozDash(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aError);
void SetMozDash(JSContext* aCx, const JS::Value& aMozDash,
mozilla::ErrorResult& aError);
void SetLineDash(const Sequence<double>& aSegments,
mozilla::ErrorResult& aRv);
@ -377,12 +373,6 @@ public:
void SetLineDashOffset(double aOffset);
double LineDashOffset() const;
double MozDashOffset()
{
return CurrentState().dashOffset;
}
void SetMozDashOffset(double aMozDashOffset);
void GetMozTextStyle(nsAString& aMozTextStyle)
{
GetFont(aMozTextStyle);

Просмотреть файл

@ -250,7 +250,6 @@ tags = imagebitmap
tags = imagebitmap
[test_ImageData_ctor.html]
[test_isPointInStroke.html]
[test_mozDashOffset.html]
[test_mozGetAsFile.html]
[test_strokeText_throw.html]
[test_toBlob.html]

Просмотреть файл

@ -6,7 +6,7 @@
window.onload=function(){
var c=document.getElementById("myCanvas").getContext("2d");
c.beginPath();
c.mozDash = [1,1];
c.setLineDash([1,1]);
c.strokeRect(10, 10, 200, 200);
}
</script>

Просмотреть файл

@ -1,39 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for mozDashOffset</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script>
try {
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.mozDash = [1, 1];
ctx.mozDashOffset = 1;
ctx.mozDashOffset = Infinity;
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
ctx.mozDashOffset = 1;
ctx.mozDashOffset = -Infinity;
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
ctx.mozDashOffset = 1;
ctx.mozDashOffset = NaN;
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
} catch(e) {
ok(false, "unexpected exception thrown in: test_mozDashOffset.html");
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -34,6 +34,9 @@
#include "IHistory.h"
#include "imgIContainer.h"
#include "mozIApplication.h"
#if defined(XP_WIN) && defined(ACCESSIBILITY)
#include "mozilla/a11y/AccessibleWrap.h"
#endif
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/DataStorage.h"
@ -1954,6 +1957,10 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
}
mBlobURLs.Clear();
#if defined(XP_WIN32) && defined(ACCESSIBILITY)
a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
#endif
}
void
@ -5348,6 +5355,18 @@ ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aUR
return true;
}
bool
ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
{
#if defined(XP_WIN32) && defined(ACCESSIBILITY)
*aContentId = a11y::AccessibleWrap::GetContentProcessIdFor(ChildID());
MOZ_ASSERT(*aContentId);
return true;
#else
return false;
#endif
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -565,6 +565,9 @@ public:
virtual bool
RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI) override;
virtual bool
RecvGetA11yContentId(uint32_t* aContentId) override;
virtual int32_t Pid() const override;
// Use the PHangMonitor channel to ask the child to repaint a tab.

Просмотреть файл

@ -746,13 +746,6 @@ child:
*/
async Destroy();
/**
* Tell the child side if it has to update it's touchable region
* to the parent.
*/
async SetUpdateHitRegion(bool aEnabled);
/**
* Update the child side docShell active (resource use) state.
*

Просмотреть файл

@ -1236,6 +1236,8 @@ parent:
async AccumulateChildHistogram(Accumulation[] accumulations);
async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
sync GetA11yContentId() returns (uint32_t aContentId);
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);

Просмотреть файл

@ -535,7 +535,6 @@ TabChild::TabChild(nsIContentChild* aManager,
, mNotified(false)
, mTriedBrowserInit(false)
, mOrientation(eScreenOrientation_PortraitPrimary)
, mUpdateHitRegion(false)
, mIgnoreKeyPressEvent(false)
, mHasValidInnerSize(false)
, mDestroyed(false)
@ -548,7 +547,6 @@ TabChild::TabChild(nsIContentChild* aManager,
, mParentIsActive(false)
, mDidSetRealShowInfo(false)
, mDidLoadURLInit(false)
, mAPZChild(nullptr)
, mLayerObserverEpoch(0)
#if defined(XP_WIN) && defined(ACCESSIBILITY)
, mNativeWindowHandle(0)
@ -2641,28 +2639,6 @@ TabChild::RecvDestroy()
return true;
}
bool
TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
{
mUpdateHitRegion = aEnabled;
// We need to trigger a repaint of the child frame to ensure that it
// recomputes and sends its region.
if (!mUpdateHitRegion) {
return true;
}
nsCOMPtr<nsIDocument> document(GetDocument());
NS_ENSURE_TRUE(document, true);
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
NS_ENSURE_TRUE(presShell, true);
RefPtr<nsPresContext> presContext = presShell->GetPresContext();
NS_ENSURE_TRUE(presContext, true);
presContext->InvalidatePaintedLayers();
return true;
}
bool
TabChild::RecvSetDocShellIsActive(const bool& aIsActive,
const bool& aPreserveLayers,
@ -3008,15 +2984,6 @@ TabChild::MakeHidden()
}
}
void
TabChild::UpdateHitRegion(const nsRegion& aRegion)
{
mRemoteFrame->SendUpdateHitRegion(aRegion);
if (mAPZChild) {
mAPZChild->SendUpdateHitRegion(aRegion);
}
}
NS_IMETHODIMP
TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
{

Просмотреть файл

@ -518,10 +518,6 @@ public:
nsIContentChild* Manager() const { return mManager; }
bool GetUpdateHitRegion() const { return mUpdateHitRegion; }
void UpdateHitRegion(const nsRegion& aRegion);
static inline TabChild*
GetFrom(nsIDocShell* aDocShell)
{
@ -651,11 +647,6 @@ public:
const CSSRect& aRect,
const uint32_t& aFlags);
void SetAPZChild(layers::APZChild* aAPZChild)
{
mAPZChild = aAPZChild;
}
// Request that the docshell be marked as active.
void ForcePaint(uint64_t aLayerObserverEpoch);
@ -672,8 +663,6 @@ protected:
virtual bool RecvDestroy() override;
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) override;
virtual bool RecvSetDocShellIsActive(const bool& aIsActive,
const bool& aIsHidden,
const uint64_t& aLayerObserverEpoch) override;
@ -765,7 +754,6 @@ private:
bool mNotified;
bool mTriedBrowserInit;
ScreenOrientationInternal mOrientation;
bool mUpdateHitRegion;
bool mIgnoreKeyPressEvent;
RefPtr<APZEventState> mAPZEventState;

Просмотреть файл

@ -153,12 +153,6 @@ interface CanvasRenderingContext2D {
[Throws]
attribute object mozCurrentTransformInverse;
[Throws]
attribute any mozDash; /* default |null| */
[LenientFloat]
attribute double mozDashOffset; /* default 0.0 */
[SetterThrows]
attribute DOMString mozTextStyle;

Просмотреть файл

@ -19,6 +19,7 @@ struct D3D11DeviceStatus
{
bool isWARP;
bool textureSharingWorks;
bool alphaTextureSharingWorks;
uint32_t featureLevel;
DxgiAdapterDesc adapter;
};

Просмотреть файл

@ -237,6 +237,10 @@ IMFYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder)
return nullptr;
}
if (!gfx::DeviceManagerDx::Get()->AlphaTextureSharingWorks()) {
return nullptr;
}
if (mData.mYStride < 0 || mData.mCbCrStride < 0) {
// D3D11 only supports unsigned stride values.
return nullptr;

Просмотреть файл

@ -107,23 +107,6 @@ public:
*/
virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) = 0;
/**
* APZ uses |FrameMetrics::mCompositionBounds| for hit testing. Sometimes,
* widget code has knowledge of a touch-sensitive region that should
* additionally constrain hit testing for all frames associated with the
* controller. This method allows APZ to query the controller for such a
* region. A return value of true indicates that the controller has such a
* region, and it is returned in |aOutRegion|.
* This method needs to be called on the main thread.
* TODO: once bug 928833 is implemented, this should be removed, as
* APZ can then get the correct touch-sensitive region for each frame
* directly from the layer.
*/
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion)
{
return false;
}
enum class APZStateChange {
/**
* APZ started modifying the view (including panning, zooming, and fling).

Просмотреть файл

@ -276,30 +276,6 @@ ComputeClipRegion(GeckoContentController* aController,
clipRegion = RoundedToInt(aLayer.Metrics().GetCompositionBounds());
}
// Optionally, the GeckoContentController can provide a touch-sensitive
// region that constrains all frames associated with the controller.
// In this case we intersect the composition bounds with that region.
CSSRect touchSensitiveRegion;
if (aController->GetTouchSensitiveRegion(&touchSensitiveRegion)) {
// Here we assume 'touchSensitiveRegion' is in the CSS pixels of the
// parent frame. To convert it to ParentLayer pixels, we therefore need
// the cumulative resolution of the parent frame. We approximate this as
// the quotient of our cumulative resolution and our pres shell resolution;
// this approximation may not be accurate in the presence of a css-driven
// resolution.
LayoutDeviceToParentLayerScale2D parentCumulativeResolution =
aLayer.Metrics().GetCumulativeResolution()
/ ParentLayerToLayerScale(aLayer.Metrics().GetPresShellResolution());
// Not sure what rounding option is the most correct here, but if we ever
// figure it out we can change this. For now I'm rounding in to minimize
// the chances of getting a complex region.
ParentLayerIntRegion extraClip = RoundedIn(
touchSensitiveRegion
* aLayer.Metrics().GetDevPixelsPerCSSPixel()
* parentCumulativeResolution);
clipRegion.AndWith(extraClip);
}
return clipRegion;
}

Просмотреть файл

@ -99,8 +99,6 @@ ContentProcessController::~ContentProcessController()
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
} else if (mBrowser) {
mBrowser->SetAPZChild(nullptr);
}
}

Просмотреть файл

@ -46,8 +46,6 @@ sync protocol PAPZ
parent:
async UpdateHitRegion(nsRegion aRegion);
async __delete__();
child:

Просмотреть файл

@ -30,7 +30,6 @@ using namespace mozilla::gfx;
RemoteContentController::RemoteContentController()
: mCompositorThread(MessageLoop::current())
, mCanSend(true)
, mMutex("RemoteContentController")
{
}
@ -50,9 +49,9 @@ RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics
void
RemoteContentController::HandleTapOnMainThread(TapType aTapType,
const LayoutDevicePoint& aPoint,
LayoutDevicePoint aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
ScrollableLayerGuid aGuid,
uint64_t aInputBlockId)
{
MOZ_ASSERT(NS_IsMainThread());
@ -93,7 +92,7 @@ RemoteContentController::HandleTap(TapType aTapType,
} else {
// We don't want to get the TabParent or call TabParent::SendHandleTap() from a non-main thread (this might happen
// on Android, where this is called from the Java UI thread)
NS_DispatchToMainThread(NewRunnableMethod<TapType, const LayoutDevicePoint&, Modifiers, const ScrollableLayerGuid&, uint64_t>
NS_DispatchToMainThread(NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, ScrollableLayerGuid, uint64_t>
(this, &RemoteContentController::HandleTapOnMainThread, aTapType, aPoint, aModifiers, aGuid, aInputBlockId));
}
}
@ -160,18 +159,6 @@ RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTas
mCompositorThread->PostTask(Move(aTask));
}
bool
RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion)
{
MutexAutoLock lock(mMutex);
if (mTouchSensitiveRegion.IsEmpty()) {
return false;
}
*aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
return true;
}
void
RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
@ -264,14 +251,6 @@ RemoteContentController::NotifyFlushComplete()
}
}
bool
RemoteContentController::RecvUpdateHitRegion(const nsRegion& aRegion)
{
MutexAutoLock lock(mMutex);
mTouchSensitiveRegion = aRegion;
return true;
}
void
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
{

Просмотреть файл

@ -59,8 +59,6 @@ public:
virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) override;
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override;
virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override;
@ -76,8 +74,6 @@ public:
virtual void NotifyFlushComplete() override;
virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void Destroy() override;
@ -87,14 +83,10 @@ private:
bool mCanSend;
void HandleTapOnMainThread(TapType aType,
const LayoutDevicePoint& aPoint,
LayoutDevicePoint aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
ScrollableLayerGuid aGuid,
uint64_t aInputBlockId);
// Mutex protecting members below accessed from multiple threads.
mozilla::Mutex mMutex;
nsRegion mTouchSensitiveRegion;
};
} // namespace layers

Просмотреть файл

@ -328,6 +328,7 @@ DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11)
// Only test this when not using WARP since it can fail and cause
// GetDeviceRemovedReason to return weird values.
bool textureSharingWorks = D3D11Checks::DoesTextureSharingWork(device);
bool alphaTextureSharingWorks = D3D11Checks::DoesAlphaTextureSharingWork(device);
DXGI_ADAPTER_DESC desc;
PodZero(&desc);
@ -355,6 +356,7 @@ DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11)
mDeviceStatus = Some(D3D11DeviceStatus(
false,
textureSharingWorks,
alphaTextureSharingWorks,
featureLevel,
DxgiAdapterDesc::From(desc)));
}
@ -409,8 +411,10 @@ DeviceManagerDx::CreateWARPCompositorDevice()
// Only test for texture sharing on Windows 8 since it puts the device into
// an unusable state if used on Windows 7
bool textureSharingWorks = false;
bool alphaTextureSharingWorks = false;
if (IsWin8OrLater()) {
textureSharingWorks = D3D11Checks::DoesTextureSharingWork(device);
alphaTextureSharingWorks = D3D11Checks::DoesAlphaTextureSharingWork(device);
}
DxgiAdapterDesc nullAdapter;
@ -423,6 +427,7 @@ DeviceManagerDx::CreateWARPCompositorDevice()
mDeviceStatus = Some(D3D11DeviceStatus(
true,
textureSharingWorks,
alphaTextureSharingWorks,
featureLevel,
nullAdapter));
}
@ -670,6 +675,16 @@ DeviceManagerDx::TextureSharingWorks()
return mDeviceStatus->textureSharingWorks();
}
bool
DeviceManagerDx::AlphaTextureSharingWorks()
{
MutexAutoLock lock(mDeviceLock);
if (!mDeviceStatus) {
return false;
}
return mDeviceStatus->alphaTextureSharingWorks();
}
bool
DeviceManagerDx::IsWARP()
{

Просмотреть файл

@ -58,6 +58,7 @@ public:
unsigned GetCompositorFeatureLevel() const;
bool TextureSharingWorks();
bool AlphaTextureSharingWorks();
bool IsWARP();
bool CreateCompositorDevices();

Просмотреть файл

@ -24,6 +24,7 @@
#include "builtin/TypedObject.h"
#include "jit/InlinableNatives.h"
#include "js/GCAPI.h"
#include "js/Value.h"
#include "jsobjinlines.h"
@ -173,7 +174,8 @@ js::ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out)
if (!IsVectorObject<V>(v))
return ErrorWrongTypeArg(cx, 1, typeDescr);
Elem* mem = reinterpret_cast<Elem*>(v.toObject().as<TypedObject>().typedMem());
JS::AutoCheckCannotGC nogc(cx);
Elem* mem = reinterpret_cast<Elem*>(v.toObject().as<TypedObject>().typedMem(nogc));
*out = jit::SimdConstant::CreateSimd128(mem);
return true;
}
@ -188,10 +190,10 @@ template bool js::ToSimdConstant<Bool32x4>(JSContext* cx, HandleValue v, jit::Si
template<typename Elem>
static Elem
TypedObjectMemory(HandleValue v)
TypedObjectMemory(HandleValue v, const JS::AutoAssertOnGC& nogc)
{
TypedObject& obj = v.toObject().as<TypedObject>();
return reinterpret_cast<Elem>(obj.typedMem());
return reinterpret_cast<Elem>(obj.typedMem(nogc));
}
static const ClassOps SimdTypeDescrClassOps = {
@ -422,7 +424,11 @@ FillLanes(JSContext* cx, Handle<TypedObject*> result, const CallArgs& args)
for (unsigned i = 0; i < T::lanes; i++) {
if (!T::Cast(cx, args.get(i), &tmp))
return false;
reinterpret_cast<Elem*>(result->typedMem())[i] = tmp;
// Reassure typedMem() that we won't GC while holding onto the returned
// pointer, even though we could GC on every iteration of this loop
// (but it is safe because we re-fetch each time.)
JS::AutoCheckCannotGC nogc(cx);
reinterpret_cast<Elem*>(result->typedMem(nogc))[i] = tmp;
}
args.rval().setObject(*result);
return true;
@ -639,7 +645,8 @@ js::CreateSimd(JSContext* cx, const typename V::Elem* data)
if (!result)
return nullptr;
Elem* resultMem = reinterpret_cast<Elem*>(result->typedMem());
JS::AutoCheckCannotGC nogc(cx);
Elem* resultMem = reinterpret_cast<Elem*>(result->typedMem(nogc));
memcpy(resultMem, data, sizeof(Elem) * V::lanes);
return result;
}
@ -835,6 +842,35 @@ StoreResult(JSContext* cx, CallArgs& args, typename Out::Elem* result)
return true;
}
// StoreResult can GC, and it is commonly used after pulling something out of a
// TypedObject:
//
// Elem result = op(TypedObjectMemory<Elem>(args[0]));
// StoreResult<Out>(..., result);
//
// The pointer extracted from the typed object in args[0] in the above example
// could be an interior pointer, and therefore be invalidated by GC.
// TypedObjectMemory() requires an assertion token to be passed in to prove
// that we won't GC, but the scope of eg an AutoCheckCannotGC RAII object
// extends to the end of its containing scope -- which would include the call
// to StoreResult, resulting in a rooting hazard.
//
// TypedObjectElemArray fixes this by wrapping the problematic pointer in a
// type, and the analysis is able to see that it is dead before calling
// StoreResult. (But if another GC called is made before the pointer is dead,
// it will correctly report a hazard.)
//
template <typename Elem>
class TypedObjectElemArray {
Elem* elements;
public:
explicit TypedObjectElemArray(HandleValue objVal) {
JS::AutoCheckCannotGC nogc;
elements = TypedObjectMemory<Elem*>(objVal, nogc);
}
Elem& operator[](int i) { return elements[i]; }
} JS_HAZ_GC_POINTER;
// Coerces the inputs of type In to the type Coercion, apply the operator Op
// and converts the result to the type Out.
template<typename In, typename Coercion, template<typename C> class Op, typename Out>
@ -849,7 +885,7 @@ CoercedUnaryFunc(JSContext* cx, unsigned argc, Value* vp)
return ErrorBadArgs(cx);
CoercionElem result[Coercion::lanes];
CoercionElem* val = TypedObjectMemory<CoercionElem*>(args[0]);
TypedObjectElemArray<CoercionElem> val(args[0]);
for (unsigned i = 0; i < Coercion::lanes; i++)
result[i] = Op<CoercionElem>::apply(val[i]);
return StoreResult<Out>(cx, args, (RetElem*) result);
@ -869,8 +905,8 @@ CoercedBinaryFunc(JSContext* cx, unsigned argc, Value* vp)
return ErrorBadArgs(cx);
CoercionElem result[Coercion::lanes];
CoercionElem* left = TypedObjectMemory<CoercionElem*>(args[0]);
CoercionElem* right = TypedObjectMemory<CoercionElem*>(args[1]);
TypedObjectElemArray<CoercionElem> left(args[0]);
TypedObjectElemArray<CoercionElem> right(args[1]);
for (unsigned i = 0; i < Coercion::lanes; i++)
result[i] = Op<CoercionElem>::apply(left[i], right[i]);
return StoreResult<Out>(cx, args, (RetElem*) result);
@ -905,7 +941,8 @@ ExtractLane(JSContext* cx, unsigned argc, Value* vp)
if (!ArgumentToLaneIndex(cx, args[1], V::lanes, &lane))
return false;
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
JS::AutoCheckCannotGC nogc(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0], nogc);
Elem val = vec[lane];
args.rval().set(V::ToValue(val));
return true;
@ -921,7 +958,8 @@ AllTrue(JSContext* cx, unsigned argc, Value* vp)
if (args.length() < 1 || !IsVectorObject<V>(args[0]))
return ErrorBadArgs(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
JS::AutoCheckCannotGC nogc(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0], nogc);
bool allTrue = true;
for (unsigned i = 0; allTrue && i < V::lanes; i++)
allTrue = vec[i];
@ -940,7 +978,8 @@ AnyTrue(JSContext* cx, unsigned argc, Value* vp)
if (args.length() < 1 || !IsVectorObject<V>(args[0]))
return ErrorBadArgs(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
JS::AutoCheckCannotGC nogc(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0], nogc);
bool anyTrue = false;
for (unsigned i = 0; !anyTrue && i < V::lanes; i++)
anyTrue = vec[i];
@ -968,7 +1007,7 @@ ReplaceLane(JSContext* cx, unsigned argc, Value* vp)
if (!V::Cast(cx, args.get(2), &value))
return false;
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
TypedObjectElemArray<Elem> vec(args[0]);
Elem result[V::lanes];
for (unsigned i = 0; i < V::lanes; i++)
result[i] = i == lane ? value : vec[i];
@ -992,8 +1031,7 @@ Swizzle(JSContext* cx, unsigned argc, Value* vp)
return false;
}
Elem* val = TypedObjectMemory<Elem*>(args[0]);
TypedObjectElemArray<Elem> val(args[0]);
Elem result[V::lanes];
for (unsigned i = 0; i < V::lanes; i++)
result[i] = val[lanes[i]];
@ -1017,13 +1055,16 @@ Shuffle(JSContext* cx, unsigned argc, Value* vp)
return false;
}
Elem* lhs = TypedObjectMemory<Elem*>(args[0]);
Elem* rhs = TypedObjectMemory<Elem*>(args[1]);
Elem result[V::lanes];
for (unsigned i = 0; i < V::lanes; i++) {
Elem* selectedInput = lanes[i] < V::lanes ? lhs : rhs;
result[i] = selectedInput[lanes[i] % V::lanes];
{
JS::AutoCheckCannotGC nogc(cx);
Elem* lhs = TypedObjectMemory<Elem*>(args[0], nogc);
Elem* rhs = TypedObjectMemory<Elem*>(args[1], nogc);
for (unsigned i = 0; i < V::lanes; i++) {
Elem* selectedInput = lanes[i] < V::lanes ? lhs : rhs;
result[i] = selectedInput[lanes[i] % V::lanes];
}
}
return StoreResult<V>(cx, args, result);
@ -1046,8 +1087,8 @@ BinaryScalar(JSContext* cx, unsigned argc, Value* vp)
if (!ToInt32(cx, args[1], &bits))
return false;
TypedObjectElemArray<Elem> val(args[0]);
Elem result[V::lanes];
Elem* val = TypedObjectMemory<Elem*>(args[0]);
for (unsigned i = 0; i < V::lanes; i++)
result[i] = Op<Elem>::apply(val[i], bits);
@ -1066,8 +1107,8 @@ CompareFunc(JSContext* cx, unsigned argc, Value* vp)
return ErrorBadArgs(cx);
OutElem result[Out::lanes];
InElem* left = TypedObjectMemory<InElem*>(args[0]);
InElem* right = TypedObjectMemory<InElem*>(args[1]);
TypedObjectElemArray<InElem> left(args[0]);
TypedObjectElemArray<InElem> right(args[1]);
for (unsigned i = 0; i < Out::lanes; i++) {
unsigned j = (i * In::lanes) / Out::lanes;
result[i] = Op<InElem>::apply(left[j], right[j]) ? -1 : 0;
@ -1161,8 +1202,7 @@ FuncConvert(JSContext* cx, unsigned argc, Value* vp)
if (args.length() != 1 || !IsVectorObject<V>(args[0]))
return ErrorBadArgs(cx);
Elem* val = TypedObjectMemory<Elem*>(args[0]);
TypedObjectElemArray<Elem> val(args[0]);
RetElem result[Vret::lanes];
for (unsigned i = 0; i < V::lanes; i++) {
if (ThrowOnConvert<Elem, RetElem>::value(val[i])) {
@ -1195,7 +1235,10 @@ FuncConvertBits(JSContext* cx, unsigned argc, Value* vp)
// For consistency with other SIMD functions, simply copy the input in a
// temporary array.
RetElem copy[Vret::lanes];
memcpy(copy, TypedObjectMemory<RetElem*>(args[0]), Vret::lanes * sizeof(RetElem));
{
JS::AutoCheckCannotGC nogc(cx);
memcpy(copy, TypedObjectMemory<RetElem*>(args[0], nogc), Vret::lanes * sizeof(RetElem));
}
return StoreResult<Vret>(cx, args, copy);
}
@ -1244,9 +1287,9 @@ SelectBits(JSContext* cx, unsigned argc, Value* vp)
return ErrorBadArgs(cx);
}
MaskTypeElem* val = TypedObjectMemory<MaskTypeElem*>(args[0]);
MaskTypeElem* tv = TypedObjectMemory<MaskTypeElem*>(args[1]);
MaskTypeElem* fv = TypedObjectMemory<MaskTypeElem*>(args[2]);
TypedObjectElemArray<MaskTypeElem> val(args[0]);
TypedObjectElemArray<MaskTypeElem> tv(args[1]);
TypedObjectElemArray<MaskTypeElem> fv(args[2]);
MaskTypeElem tr[MaskType::lanes];
for (unsigned i = 0; i < MaskType::lanes; i++)
@ -1278,9 +1321,9 @@ Select(JSContext* cx, unsigned argc, Value* vp)
return ErrorBadArgs(cx);
}
MaskTypeElem* mask = TypedObjectMemory<MaskTypeElem*>(args[0]);
Elem* tv = TypedObjectMemory<Elem*>(args[1]);
Elem* fv = TypedObjectMemory<Elem*>(args[2]);
TypedObjectElemArray<MaskTypeElem> mask(args[0]);
TypedObjectElemArray<Elem> tv(args[1]);
TypedObjectElemArray<Elem> fv(args[2]);
Elem result[V::lanes];
for (unsigned i = 0; i < V::lanes; i++)
@ -1361,9 +1404,10 @@ Load(JSContext* cx, unsigned argc, Value* vp)
if (!result)
return false;
JS::AutoCheckCannotGC nogc(cx);
SharedMem<Elem*> src =
typedArray->as<TypedArrayObject>().viewDataEither().addBytes(byteStart).cast<Elem*>();
Elem* dst = reinterpret_cast<Elem*>(result->typedMem());
Elem* dst = reinterpret_cast<Elem*>(result->typedMem(nogc));
jit::AtomicOperations::podCopySafeWhenRacy(SharedMem<Elem*>::unshared(dst), src, NumElem);
args.rval().setObject(*result);
@ -1388,7 +1432,8 @@ Store(JSContext* cx, unsigned argc, Value* vp)
if (!IsVectorObject<V>(args[2]))
return ErrorBadArgs(cx);
Elem* src = TypedObjectMemory<Elem*>(args[2]);
JS::AutoCheckCannotGC nogc(cx);
Elem* src = TypedObjectMemory<Elem*>(args[2], nogc);
SharedMem<Elem*> dst =
typedArray->as<TypedArrayObject>().viewDataEither().addBytes(byteStart).cast<Elem*>();
js::jit::AtomicOperations::podCopySafeWhenRacy(dst, SharedMem<Elem*>::unshared(src), NumElem);

Просмотреть файл

@ -1511,7 +1511,8 @@ OutlineTypedObject::attach(JSContext* cx, TypedObject& typedObj, int32_t offset)
attach(cx, owner->as<ArrayBufferObject>(), offset);
} else {
MOZ_ASSERT(owner->is<InlineTypedObject>());
setOwnerAndData(owner, owner->as<InlineTypedObject>().inlineTypedMem() + offset);
JS::AutoCheckCannotGC nogc(cx);
setOwnerAndData(owner, owner->as<InlineTypedObject>().inlineTypedMem(nogc) + offset);
}
}
@ -1564,7 +1565,8 @@ TypedObject::createZeroed(JSContext* cx, HandleTypeDescr descr, int32_t length,
InlineTypedObject* obj = InlineTypedObject::create(cx, descr, heap);
if (!obj)
return nullptr;
descr->initInstances(cx->runtime(), obj->inlineTypedMem(), 1);
JS::AutoCheckCannotGC nogc(cx);
descr->initInstances(cx->runtime(), obj->inlineTypedMem(nogc), 1);
return obj;
}
@ -2455,7 +2457,7 @@ js::SetTypedObjectOffset(JSContext*, unsigned argc, Value* vp)
int32_t offset = args[1].toInt32();
MOZ_ASSERT(typedObj.isAttached());
typedObj.setData(typedObj.typedMemBase() + offset);
typedObj.resetOffset(offset);
args.rval().setUndefined();
return true;
}
@ -2579,7 +2581,7 @@ js::GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp)
#define JS_STORE_SCALAR_CLASS_IMPL(_constant, T, _name) \
bool \
js::StoreScalar##T::Func(JSContext*, unsigned argc, Value* vp) \
js::StoreScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) \
{ \
CallArgs args = CallArgsFromVp(argc, vp); \
MOZ_ASSERT(args.length() == 3); \
@ -2593,7 +2595,8 @@ js::StoreScalar##T::Func(JSContext*, unsigned argc, Value* vp) \
/* Should be guaranteed by the typed objects API: */ \
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
\
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset)); \
JS::AutoCheckCannotGC nogc(cx); \
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
double d = args[2].toNumber(); \
*target = ConvertScalar<T>(d); \
args.rval().setUndefined(); \
@ -2620,7 +2623,8 @@ js::StoreReference##_name::Func(JSContext* cx, unsigned argc, Value* vp)
/* Should be guaranteed by the typed objects API: */ \
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
\
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset)); \
JS::AutoCheckCannotGC nogc(cx); \
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
if (!store(cx, target, args[3], &typedObj, id)) \
return false; \
args.rval().setUndefined(); \
@ -2629,7 +2633,7 @@ js::StoreReference##_name::Func(JSContext* cx, unsigned argc, Value* vp)
#define JS_LOAD_SCALAR_CLASS_IMPL(_constant, T, _name) \
bool \
js::LoadScalar##T::Func(JSContext*, unsigned argc, Value* vp) \
js::LoadScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) \
{ \
CallArgs args = CallArgsFromVp(argc, vp); \
MOZ_ASSERT(args.length() == 2); \
@ -2642,14 +2646,15 @@ js::LoadScalar##T::Func(JSContext*, unsigned argc, Value* vp)
/* Should be guaranteed by the typed objects API: */ \
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
\
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset)); \
JS::AutoCheckCannotGC nogc(cx); \
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
args.rval().setNumber((double) *target); \
return true; \
}
#define JS_LOAD_REFERENCE_CLASS_IMPL(_constant, T, _name) \
bool \
js::LoadReference##_name::Func(JSContext*, unsigned argc, Value* vp) \
js::LoadReference##_name::Func(JSContext* cx, unsigned argc, Value* vp) \
{ \
CallArgs args = CallArgsFromVp(argc, vp); \
MOZ_ASSERT(args.length() == 2); \
@ -2662,7 +2667,8 @@ js::LoadReference##_name::Func(JSContext*, unsigned argc, Value* vp)
/* Should be guaranteed by the typed objects API: */ \
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
\
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset)); \
JS::AutoCheckCannotGC nogc(cx); \
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
load(target, args.rval()); \
return true; \
}

Просмотреть файл

@ -533,6 +533,10 @@ class TypedObject : public ShapedObject
static MOZ_MUST_USE bool obj_enumerate(JSContext* cx, HandleObject obj,
AutoIdVector& properties, bool enumerableOnly);
uint8_t* typedMem() const;
uint8_t* typedMemBase() const;
public:
TypedProto& typedProto() const {
// Typed objects' prototypes can't be modified.
@ -545,22 +549,21 @@ class TypedObject : public ShapedObject
int32_t offset() const;
int32_t length() const;
uint8_t* typedMem() const;
uint8_t* typedMemBase() const;
uint8_t* typedMem(const JS::AutoAssertOnGC&) const { return typedMem(); }
bool isAttached() const;
int32_t size() const {
return typeDescr().size();
}
uint8_t* typedMem(size_t offset) const {
uint8_t* typedMem(size_t offset, const JS::AutoAssertOnGC& nogc) const {
// It seems a bit surprising that one might request an offset
// == size(), but it can happen when taking the "address of" a
// 0-sized value. (In other words, we maintain the invariant
// that `offset + size <= size()` -- this is always checked in
// the caller's side.)
MOZ_ASSERT(offset <= (size_t) size());
return typedMem() + offset;
return typedMem(nogc) + offset;
}
inline MOZ_MUST_USE bool opaque() const;
@ -618,6 +621,11 @@ class OutlineTypedObject : public TypedObject
data_ = data;
}
void resetOffset(size_t offset) {
MOZ_ASSERT(offset <= (size_t) size());
setData(typedMemBase() + offset);
}
// Helper for createUnattached()
static OutlineTypedObject* createUnattachedWithClass(JSContext* cx,
const Class* clasp,
@ -676,9 +684,16 @@ class OutlineOpaqueTypedObject : public OutlineTypedObject
// Class for a typed object whose data is allocated inline.
class InlineTypedObject : public TypedObject
{
friend class TypedObject;
// Start of the inline data, which immediately follows the shape and type.
uint8_t data_[1];
protected:
uint8_t* inlineTypedMem() const {
return (uint8_t*) &data_;
}
public:
static const size_t MaximumSize = JSObject::MAX_BYTE_SIZE - sizeof(TypedObject);
@ -689,8 +704,12 @@ class InlineTypedObject : public TypedObject
return gc::GetGCObjectKindForBytes(nbytes + sizeof(TypedObject));
}
uint8_t* inlineTypedMem() const {
return (uint8_t*) &data_;
uint8_t* inlineTypedMem(const JS::AutoAssertOnGC&) const {
return inlineTypedMem();
}
uint8_t* inlineTypedMemForGC() const {
return inlineTypedMem();
}
static void obj_trace(JSTracer* trace, JSObject* object);
@ -714,6 +733,10 @@ class InlineTransparentTypedObject : public InlineTypedObject
static const Class class_;
ArrayBufferObject* getOrCreateBuffer(JSContext* cx);
uint8_t* inlineTypedMem() const {
return InlineTypedObject::inlineTypedMem();
}
};
// Class for an opaque typed object with inline data and no array buffer.

Просмотреть файл

@ -1480,7 +1480,7 @@ CallTraceHook(Functor f, JSTracer* trc, JSObject* obj, CheckGeneration check, Ar
InlineTypedObject& tobj = obj->as<InlineTypedObject>();
if (tobj.typeDescr().hasTraceList()) {
VisitTraceList(f, tobj.typeDescr().traceList(), tobj.inlineTypedMem(),
VisitTraceList(f, tobj.typeDescr().traceList(), tobj.inlineTypedMemForGC(),
mozilla::Forward<Args>(args)...);
}

Просмотреть файл

@ -113,3 +113,26 @@ function createI64(val) {
}
return ret;
}
// Fully test a module:
// - ensure it validates.
// - ensure it compiles and produces the expected result.
// - ensure textToBinary(binaryToText(binary)) = binary
// Preconditions:
// - the binary module must export a function called "run".
function wasmFullPass(text, expected, maybeImports) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let module = new WebAssembly.Module(binary);
let instance = new WebAssembly.Instance(module, maybeImports);
assertEq(instance.exports.run(), expected, "Initial module must return the expected result.");
let retext = wasmBinaryToText(binary);
let rebinary = wasmTextToBinary(retext);
assertEq(WebAssembly.validate(rebinary), true, "Recreated binary must validate.");
let remodule = new WebAssembly.Module(rebinary);
let reinstance = new WebAssembly.Instance(remodule, maybeImports);
assertEq(reinstance.exports.run(), expected, "Reformed module must return the expected result");
}

Просмотреть файл

@ -0,0 +1,10 @@
setJitCompilerOption('ion.warmup.trigger', 0);
gczeal(7, 1);
var dbgGlobal = newGlobal();
var dbg = new dbgGlobal.Debugger();
dbg.addDebuggee(this);
function f(x, await = () => Array.isArray(revocable.proxy), ...get) {
dbg.getNewestFrame().older.eval("print(a)");
}
function a() {}
for (var i = 0; i < 10; i++) f();

Просмотреть файл

@ -0,0 +1,8 @@
// |jit-test| test-also-wasm-baseline
load(libdir + "wasm.js");
wasmFullPass(`(module
(func $test (result i32) (param i32) (param i32) (i32.add (get_local 0) (get_local 1)))
(func $run (result i32) (call $test (i32.const 1) (i32.const ${Math.pow(2, 31) - 1})))
(export "run" $run)
)`, -Math.pow(2, 31));

Просмотреть файл

@ -2559,6 +2559,11 @@ jit::CanEnter(JSContext* cx, RunState& state)
return status;
}
// Skip if the script is being compiled off thread (again).
// MaybeCreateThisForConstructor could have started an ion compilation.
if (rscript->isIonCompilingOffThread())
return Method_Skipped;
// Attempt compilation. Returns Method_Compiled if already compiled.
bool constructing = state.isInvoke() && state.asInvoke()->constructing();
MethodStatus status = Compile(cx, rscript, nullptr, nullptr, constructing);

Просмотреть файл

@ -1261,8 +1261,9 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject* templateObj,
}
}
} else if (templateObj->is<InlineTypedObject>()) {
JS::AutoAssertOnGC nogc; // off-thread, so cannot GC
size_t nbytes = templateObj->as<InlineTypedObject>().size();
const uint8_t* memory = templateObj->as<InlineTypedObject>().inlineTypedMem();
const uint8_t* memory = templateObj->as<InlineTypedObject>().inlineTypedMem(nogc);
// Memcpy the contents of the template object to the new object.
size_t offset = 0;

Просмотреть файл

@ -147,7 +147,7 @@ RematerializedFrame::trace(JSTracer* trc)
TraceRoot(trc, &argsObj_, "remat ion frame argsobj");
TraceRoot(trc, &returnValue_, "remat ion frame return value");
TraceRoot(trc, &thisArgument_, "remat ion frame this");
TraceRootRange(trc, numActualArgs_ + isConstructing_ + script_->nfixed(),
TraceRootRange(trc, numArgSlots() + isConstructing_ + script_->nfixed(),
slots_, "remat ion frame stack");
}

Просмотреть файл

@ -3401,6 +3401,8 @@ Assembler::GetNopFill()
uint32_t fill;
if (fillStr && sscanf(fillStr, "%u", &fill) == 1)
NopFill = fill;
if (NopFill > 8)
MOZ_CRASH("Nop fill > 8 is not supported");
isSet = true;
}
return NopFill;

Просмотреть файл

@ -498,11 +498,11 @@ struct Imm8mData
// Default constructor makes an invalid immediate.
Imm8mData()
: data(0xff), rot(0xf), invalid(1)
: data(0xff), rot(0xf), buff(0), invalid(1)
{ }
Imm8mData(uint32_t data_, uint32_t rot_)
: data(data_), rot(rot_), invalid(0)
: data(data_), rot(rot_), buff(0), invalid(0)
{
MOZ_ASSERT(data == data_);
MOZ_ASSERT(rot == rot_);

Просмотреть файл

@ -51,29 +51,31 @@ TraceDataRelocations(JSTracer* trc, uint8_t* buffer, CompactBufferReader& reader
{
while (reader.more()) {
size_t offset = reader.readUnsigned();
void** ptr = X86Encoding::GetPointerRef(buffer + offset);
void* ptr = X86Encoding::GetPointer(buffer + offset);
#ifdef JS_PUNBOX64
// All pointers on x64 will have the top bits cleared. If those bits
// are not cleared, this must be a Value.
uintptr_t* word = reinterpret_cast<uintptr_t*>(ptr);
if (*word >> JSVAL_TAG_SHIFT) {
uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
if (word >> JSVAL_TAG_SHIFT) {
jsval_layout layout;
layout.asBits = *word;
layout.asBits = word;
Value v = IMPL_TO_JSVAL(layout);
TraceManuallyBarrieredEdge(trc, &v, "ion-masm-value");
if (*word != JSVAL_TO_IMPL(v).asBits) {
TraceManuallyBarrieredEdge(trc, &v, "jit-masm-value");
if (word != JSVAL_TO_IMPL(v).asBits) {
// Only update the code if the Value changed, because the code
// is not writable if we're not moving objects.
*word = JSVAL_TO_IMPL(v).asBits;
X86Encoding::SetPointer(buffer + offset, (void*)JSVAL_TO_IMPL(v).asBits);
}
continue;
}
#endif
// No barrier needed since these are constants.
TraceManuallyBarrieredGenericPointerEdge(trc, reinterpret_cast<gc::Cell**>(ptr),
"ion-masm-ptr");
gc::Cell* cellPtr = reinterpret_cast<gc::Cell*>(ptr);
TraceManuallyBarrieredGenericPointerEdge(trc, &cellPtr, "jit-masm-ptr");
if (cellPtr != ptr)
X86Encoding::SetPointer(buffer + offset, cellPtr);
}
}

Просмотреть файл

@ -15,31 +15,29 @@ namespace X86Encoding {
inline void*
GetPointer(const void* where)
{
return reinterpret_cast<void* const*>(where)[-1];
}
inline void**
GetPointerRef(void* where)
{
return &reinterpret_cast<void**>(where)[-1];
void* res;
memcpy(&res, (const char*)where - sizeof(void*), sizeof(void*));
return res;
}
inline void
SetPointer(void* where, const void* value)
{
reinterpret_cast<const void**>(where)[-1] = value;
memcpy((char*)where - sizeof(void*), &value, sizeof(void*));
}
inline int32_t
GetInt32(const void* where)
{
return reinterpret_cast<const int32_t*>(where)[-1];
int32_t res;
memcpy(&res, (const char*)where - sizeof(int32_t), sizeof(int32_t));
return res;
}
inline void
SetInt32(void* where, int32_t value)
{
reinterpret_cast<int32_t*>(where)[-1] = value;
memcpy((char*)where - sizeof(int32_t), &value, sizeof(int32_t));
}
inline void

Просмотреть файл

@ -346,7 +346,8 @@ ArrayBufferObject::changeViewContents(JSContext* cx, ArrayBufferViewObject* view
// Watch out for NULL data pointers in views. This means that the view
// is not fully initialized (in which case it'll be initialized later
// with the correct pointer).
uint8_t* viewDataPointer = view->dataPointerUnshared();
JS::AutoCheckCannotGC nogc(cx);
uint8_t* viewDataPointer = view->dataPointerUnshared(nogc);
if (viewDataPointer) {
MOZ_ASSERT(newContents);
ptrdiff_t offset = viewDataPointer - oldDataPointer;
@ -1448,7 +1449,7 @@ ArrayBufferViewObject::trace(JSTracer* trc, JSObject* objArg)
MOZ_ASSERT(view != obj);
void* srcData = obj->getPrivate();
void* dstData = view->as<InlineTypedObject>().inlineTypedMem() + offset;
void* dstData = view->as<InlineTypedObject>().inlineTypedMemForGC() + offset;
obj->setPrivateUnbarriered(dstData);
// We can't use a direct forwarding pointer here, as there might
@ -1497,7 +1498,7 @@ ArrayBufferViewObject::notifyBufferDetached(JSContext* cx, void* newData)
}
uint8_t*
ArrayBufferViewObject::dataPointerUnshared()
ArrayBufferViewObject::dataPointerUnshared(const JS::AutoAssertOnGC& nogc)
{
if (is<DataViewObject>())
return static_cast<uint8_t*>(as<DataViewObject>().dataPointer());
@ -1505,7 +1506,7 @@ ArrayBufferViewObject::dataPointerUnshared()
MOZ_ASSERT(!as<TypedArrayObject>().isSharedMemory());
return static_cast<uint8_t*>(as<TypedArrayObject>().viewDataUnshared());
}
return as<TypedObject>().typedMem();
return as<TypedObject>().typedMem(nogc);
}
#ifdef DEBUG

Просмотреть файл

@ -440,7 +440,7 @@ class ArrayBufferViewObject : public JSObject
// By construction we only need unshared variants here. See
// comments in ArrayBufferObject.cpp.
uint8_t* dataPointerUnshared();
uint8_t* dataPointerUnshared(const JS::AutoAssertOnGC&);
void setDataPointerUnshared(uint8_t* data);
static void trace(JSTracer* trc, JSObject* obj);

Просмотреть файл

@ -7211,7 +7211,7 @@ DebuggerFrame::create(JSContext* cx, HandleObject proto, AbstractFramePtr refere
{
JSObject* obj = NewObjectWithGivenProto(cx, &DebuggerFrame::class_, proto);
if (!obj)
return nullptr;
return nullptr;
DebuggerFrame& frame = obj->as<DebuggerFrame>();

Просмотреть файл

@ -152,7 +152,8 @@ TypeSet::ObjectGroupString(ObjectGroup* group)
#ifdef DEBUG
static bool InferSpewActive(SpewChannel channel)
bool
js::InferSpewActive(SpewChannel channel)
{
static bool active[SPEW_COUNT];
static bool checked = false;
@ -222,12 +223,10 @@ js::InferSpewColor(TypeSet* types)
return colors[DefaultHasher<TypeSet*>::hash(types) % 7];
}
#ifdef DEBUG
void
js::InferSpew(SpewChannel channel, const char* fmt, ...)
js::InferSpewImpl(const char* fmt, ...)
{
if (!InferSpewActive(channel))
return;
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "[infer] ");
@ -235,6 +234,7 @@ js::InferSpew(SpewChannel channel, const char* fmt, ...)
fprintf(stderr, "\n");
va_end(ap);
}
#endif
MOZ_NORETURN MOZ_COLD static void
TypeFailure(JSContext* cx, const char* fmt, ...)

Просмотреть файл

@ -1290,11 +1290,13 @@ enum SpewChannel {
#ifdef DEBUG
bool InferSpewActive(SpewChannel channel);
const char * InferSpewColorReset();
const char * InferSpewColor(TypeConstraint* constraint);
const char * InferSpewColor(TypeSet* types);
void InferSpew(SpewChannel which, const char* fmt, ...);
#define InferSpew(channel, ...) if (InferSpewActive(channel)) { InferSpewImpl(__VA_ARGS__); } else {}
void InferSpewImpl(const char* fmt, ...);
/* Check that the type property for id in group contains value. */
bool ObjectGroupHasProperty(JSContext* cx, ObjectGroup* group, jsid id, const Value& value);
@ -1304,7 +1306,8 @@ bool ObjectGroupHasProperty(JSContext* cx, ObjectGroup* group, jsid id, const Va
inline const char * InferSpewColorReset() { return nullptr; }
inline const char * InferSpewColor(TypeConstraint* constraint) { return nullptr; }
inline const char * InferSpewColor(TypeSet* types) { return nullptr; }
inline void InferSpew(SpewChannel which, const char* fmt, ...) {}
#define InferSpew(channel, ...) do {} while (0)
#endif

Просмотреть файл

@ -1639,15 +1639,6 @@ nsresult nsBidi::GetParaLevel(nsBidiLevel* aParaLevel)
return NS_OK;
}
nsresult nsBidi::GetCharTypeAt(int32_t aCharIndex, nsCharType* pType)
{
if(aCharIndex<0 || mLength<=aCharIndex) {
return NS_ERROR_INVALID_ARG;
}
*pType = (nsCharType)mDirProps[aCharIndex];
return NS_OK;
}
nsresult nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t *aLogicalLimit, nsBidiLevel *aLevel)
{
int32_t length = mLength;

Просмотреть файл

@ -528,15 +528,6 @@ public:
*/
nsresult GetParaLevel(nsBidiLevel* aParaLevel);
/**
* Get the bidirectional type for one character.
*
* @param aCharIndex the index of a character.
*
* @param aType receives the bidirectional type of the character at aCharIndex.
*/
nsresult GetCharTypeAt(int32_t aCharIndex, nsCharType* aType);
/**
* Get a logical run.
* This function returns information about a run and is used

Просмотреть файл

@ -1909,18 +1909,24 @@ nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine,
aCharType = eCharType_OtherNeutral;
for (offset = aOffset; offset < aCharTypeLimit; offset++) {
int32_t charLen;
for (offset = aOffset; offset < aCharTypeLimit; offset += charLen) {
// Make sure we give RTL chartype to all characters that would be classified
// as Right-To-Left by a bidi platform.
// (May differ from the UnicodeData, eg we set RTL chartype to some NSMs.)
if (IS_HEBREW_CHAR(aText[offset]) ) {
charLen = 1;
uint32_t ch = aText[offset];
if (IS_HEBREW_CHAR(ch) ) {
charType = eCharType_RightToLeft;
}
else if (IS_ARABIC_ALPHABETIC(aText[offset]) ) {
} else if (IS_ARABIC_ALPHABETIC(ch) ) {
charType = eCharType_RightToLeftArabic;
}
else {
aBidiEngine->GetCharTypeAt(offset, &charType);
} else {
if (NS_IS_HIGH_SURROGATE(ch) && offset + 1 < aCharTypeLimit &&
NS_IS_LOW_SURROGATE(aText[offset + 1])) {
ch = SURROGATE_TO_UCS4(ch, aText[offset + 1]);
charLen = 2;
}
charType = GetBidiCat(ch);
}
if (!CHARTYPE_IS_WEAK(charType) ) {

Просмотреть файл

@ -2026,10 +2026,6 @@ GetMouseThrough(const nsIFrame* aFrame)
static bool
IsFrameReceivingPointerEvents(nsIFrame* aFrame)
{
nsSubDocumentFrame* frame = do_QueryFrame(aFrame);
if (frame && frame->PassPointerEventsToChildren()) {
return true;
}
return NS_STYLE_POINTER_EVENTS_NONE !=
aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame);
}
@ -3679,7 +3675,7 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
"Reference frame mismatch");
if (aBuilder->IsInsidePointerEventsNoneDoc()) {
// Somewhere up the parent document chain is a subdocument with pointer-
// events:none set on it (and without a mozpasspointerevents).
// events:none set on it.
return;
}
if (!aFrame->GetParent()) {

Просмотреть файл

@ -519,7 +519,7 @@ public:
* Notify the display list builder that we're entering a presshell.
* aReferenceFrame should be a frame in the new presshell.
* aPointerEventsNoneDoc should be set to true if the frame generating this
* document is pointer-events:none without mozpasspointerevents.
* document is pointer-events:none.
*/
void EnterPresShell(nsIFrame* aReferenceFrame,
bool aPointerEventsNoneDoc = false);
@ -1176,7 +1176,7 @@ private:
bool mIsBackgroundOnly;
// This is a per-document flag turning off event handling for all content
// in the document, and is set when we enter a subdocument for a pointer-
// events:none frame that doesn't have mozpasspointerevents set.
// events:none frame.
bool mInsidePointerEventsNoneDoc;
};

Просмотреть файл

@ -8492,11 +8492,6 @@ nsLayoutUtils::CalculateScrollableRectForFrame(nsIScrollableFrame* aScrollableFr
if (aScrollableFrame) {
contentBounds = aScrollableFrame->GetScrollRange();
// We ifndef the below code for Fennec because it requires special behaviour
// on the APZC side. Because Fennec has it's own PZC implementation which doesn't
// provide the special behaviour, this code will cause it to break. We can remove
// the ifndef once Fennec switches over to APZ or if we add the special handling
// to Fennec
nsPoint scrollPosition = aScrollableFrame->GetScrollPosition();
if (aScrollableFrame->GetScrollbarStyles().mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
contentBounds.y = scrollPosition.y;

Просмотреть файл

@ -6229,47 +6229,6 @@ private:
uint32_t mFlags;
};
class AutoUpdateHitRegion
{
public:
AutoUpdateHitRegion(PresShell* aShell, nsIFrame* aFrame)
: mShell(aShell), mFrame(aFrame)
{
}
~AutoUpdateHitRegion()
{
if (!XRE_IsContentProcess() ||
!mFrame || !mShell) {
return;
}
TabChild* tabChild = TabChild::GetFrom(mShell);
if (!tabChild || !tabChild->GetUpdateHitRegion()) {
return;
}
nsRegion region;
nsDisplayListBuilder builder(mFrame,
nsDisplayListBuilderMode::EVENT_DELIVERY,
/* aBuildCert= */ false);
nsDisplayList list;
AutoTArray<nsIFrame*, 100> outFrames;
nsDisplayItem::HitTestState hitTestState;
builder.EnterPresShell(mFrame);
nsRect bounds = mShell->GetPresContext()->GetVisibleArea();
mFrame->BuildDisplayListForStackingContext(&builder, bounds, &list);
builder.LeavePresShell(mFrame);
list.HitTest(&builder, bounds, &hitTestState, &outFrames);
list.DeleteAll();
for (int32_t i = outFrames.Length() - 1; i >= 0; --i) {
region.Or(region, nsLayoutUtils::TransformFrameRectToAncestor(
outFrames[i], nsRect(nsPoint(0, 0), outFrames[i]->GetSize()), mFrame));
}
tabChild->UpdateHitRegion(region);
}
private:
PresShell* mShell;
nsIFrame* mFrame;
};
void
PresShell::RecordShadowStyleChange(ShadowRoot* aShadowRoot)
{
@ -6304,7 +6263,6 @@ PresShell::Paint(nsView* aViewToPaint,
bool shouldInvalidate = layerManager->NeedsWidgetInvalidation();
nsAutoNotifyDidPaint notifyDidPaint(this, aFlags);
AutoUpdateHitRegion updateHitRegion(this, frame);
// Whether or not we should set first paint when painting is
// suppressed is debatable. For now we'll do it because

Просмотреть файл

@ -11,8 +11,6 @@ support-files =
dialog_with_positioning_window.xul
no_clip_iframe_subdoc.html
no_clip_iframe_window.xul
passpointerevents_window.html
passpointerevents_dynamically_window.html
printpreview_bug396024_helper.xul
printpreview_bug482976_helper.xul
printpreview_helper.xul
@ -57,10 +55,6 @@ skip-if = buildapp == 'b2g'
skip-if = (!debug) || (toolkit == "cocoa") || (os == "linux") || (buildapp == 'b2g') # Disabled on Mac and Linux because of Bug 992311
[test_no_clip_iframe.xul]
skip-if = buildapp == 'b2g'
[test_passpointerevents.html]
skip-if = buildapp == 'b2g'
[test_passpointerevents_dynamic.html]
skip-if = buildapp == 'b2g'
[test_prerendered_transforms.html]
skip-if = buildapp == 'b2g'
[test_printpreview.xul]

Просмотреть файл

@ -1,28 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that mozpasspointerevents works after setting it dynamically</title>
</head>
<body onload="startTest()">
<iframe id="f" style="border:none; width:200px; height:200px; pointer-events:none"
src="data:text/html,<html style='pointer-events:none'><div style='margin:100px; width:100px; height:100px; background:yellow; pointer-events:auto'>">
</iframe>
<script type="application/javascript">
var SimpleTest = window.opener.SimpleTest;
var is = window.opener.is;
function startTest() {
var f = document.getElementById("f");
f.setAttribute("mozpasspointerevents", true);
var fRect = f.getBoundingClientRect();
var e1 = document.elementFromPoint(fRect.left + 10, fRect.top + 10);
is(e1, document.body, "check point in transparent region of the iframe");
var e2 = document.elementFromPoint(fRect.left + 110, fRect.top + 110);
is(e2, f, "check point in opaque region of the iframe");
window.close();
SimpleTest.finish();
}
</script>
</body>
</html>

Просмотреть файл

@ -1,27 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that mozpasspointerevents works</title>
</head>
<body onload="startTest()">
<iframe id="f" style="border:none; width:200px; height:200px; pointer-events:none" mozpasspointerevents
src="data:text/html,<html style='pointer-events:none'><div style='margin:100px; width:100px; height:100px; background:yellow; pointer-events:auto'>">
</iframe>
<script type="application/javascript">
var SimpleTest = window.opener.SimpleTest;
var is = window.opener.is;
function startTest() {
var f = document.getElementById("f");
var fRect = f.getBoundingClientRect();
var e1 = document.elementFromPoint(fRect.left + 10, fRect.top + 10);
is(e1, document.body, "check point in transparent region of the iframe");
var e2 = document.elementFromPoint(fRect.left + 110, fRect.top + 110);
is(e2, f, "check point in opaque region of the iframe");
window.close();
SimpleTest.finish();
}
</script>
</body>
</html>

Просмотреть файл

@ -1,21 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that mozpasspointerevents works</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var root = getRootDirectory(window.location.href);
window.openDialog(root + "passpointerevents_window.html", "passpointerevents",
"chrome,width=400,height=400");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1,21 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that mozpasspointerevents works after setting it dynamically</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var root = getRootDirectory(window.location.href);
window.openDialog(root + "passpointerevents_dynamically_window.html",
"passpointerevents", "chrome,width=400,height=400");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -244,7 +244,6 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g
[test_bug770106.html]
[test_remote_frame.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_remote_passpointerevents.html]
[test_bug842853.html]
[test_bug842853-2.html]
[test_bug849219.html]

Просмотреть файл

@ -1,52 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
"use strict";
SimpleTest.waitForExplicitFinish();
function checkPointerEvents() {
let iframe = this;
let fRect = iframe.getBoundingClientRect();
let e1 = document.elementFromPoint(fRect.left + 10, fRect.top + 10);
let e2 = document.elementFromPoint(fRect.left + 110, fRect.top + 110);
if (e1 === document.body && e2 === iframe) {
is(e1, document.body, "check point in transparent region of the iframe");
is(e2, iframe, "check point in opaque region of the iframe");
SimpleTest.finish();
}
else {
SimpleTest.executeSoon(checkPointerEvents.bind(iframe));
}
}
function runTest() {
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).setAttribute('mozbrowser', 'true');
SpecialPowers.wrap(iframe).setAttribute('mozpasspointerevents', 'true');
SpecialPowers.wrap(iframe).setAttribute('remote', 'true');
iframe.style = "border:none; width:400px; height:400px; pointer-events:none";
iframe.src = "data:text/html,<html style='pointer-events:none'><div style='margin:100px; width:100px; height:100px; background:yellow; pointer-events:auto'>";
document.body.appendChild(iframe);
SimpleTest.executeSoon(checkPointerEvents.bind(iframe));
}
addEventListener("load", function() {
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.addPermission("embed-apps", true, document);
SpecialPowers.pushPrefEnv({
"set": [
["dom.ipc.browser_frames.oop_by_default", true],
["dom.mozBrowserFramesEnabled", true]
]
}, runTest);
});
</script>
</body>
</html>

Просмотреть файл

@ -307,31 +307,6 @@ nsSubDocumentFrame::GetSubdocumentSize()
}
}
bool
nsSubDocumentFrame::PassPointerEventsToChildren()
{
// Limit use of mozpasspointerevents to documents with embedded:apps/chrome
// permission, because this could be used by the parent document to discover
// which parts of the subdocument are transparent to events (if subdocument
// uses pointer-events:none on its root element, which is admittedly
// unlikely)
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozpasspointerevents)) {
if (PresContext()->IsChrome()) {
return true;
}
nsCOMPtr<nsIPermissionManager> permMgr =
services::GetPermissionManager();
if (permMgr) {
uint32_t permission = nsIPermissionManager::DENY_ACTION;
permMgr->TestPermissionFromPrincipal(GetContent()->NodePrincipal(),
"embed-apps", &permission);
return permission == nsIPermissionManager::ALLOW_ACTION;
}
}
return false;
}
static void
WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
@ -380,22 +355,14 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
decorations.MoveTo(aLists);
}
// We only care about mozpasspointerevents if we're doing hit-testing
// related things.
bool passPointerEventsToChildren =
(aBuilder->IsForEventDelivery() || aBuilder->IsBuildingLayerEventRegions())
? PassPointerEventsToChildren() : false;
// If mozpasspointerevents is set, then we should allow subdocument content
// to handle events even if we're pointer-events:none.
if (aBuilder->IsForEventDelivery() && pointerEventsNone && !passPointerEventsToChildren) {
if (aBuilder->IsForEventDelivery() && pointerEventsNone) {
return;
}
// If we're passing pointer events to children then we have to descend into
// subdocuments no matter what, to determine which parts are transparent for
// hit-testing or event regions.
bool needToDescend = aBuilder->GetDescendIntoSubdocuments() || passPointerEventsToChildren;
bool needToDescend = aBuilder->GetDescendIntoSubdocuments();
if (!mInnerView || !needToDescend) {
return;
}
@ -448,8 +415,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
aBuilder->EnterPresShell(subdocRootFrame,
pointerEventsNone && !passPointerEventsToChildren);
aBuilder->EnterPresShell(subdocRootFrame, pointerEventsNone);
} else {
dirty = aDirtyRect;
}
@ -913,16 +879,6 @@ nsSubDocumentFrame::AttributeChanged(int32_t aNameSpaceID,
if (frameloader)
frameloader->MarginsChanged(margins.width, margins.height);
}
else if (aAttribute == nsGkAtoms::mozpasspointerevents) {
RefPtr<nsFrameLoader> frameloader = FrameLoader();
if (frameloader) {
if (aModType == nsIDOMMutationEvent::ADDITION) {
frameloader->ActivateUpdateHitRegion();
} else if (aModType == nsIDOMMutationEvent::REMOVAL) {
frameloader->DeactivateUpdateHitRegion();
}
}
}
return NS_OK;
}

Просмотреть файл

@ -30,8 +30,6 @@ sync protocol PRenderFrame
parent:
async NotifyCompositorTransaction();
async UpdateHitRegion(nsRegion aRegion);
async __delete__();
};

Просмотреть файл

@ -241,13 +241,6 @@ RenderFrameParent::RecvNotifyCompositorTransaction()
return true;
}
bool
RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion)
{
mTouchRegion = aRegion;
return true;
}
void
RenderFrameParent::TriggerRepaint()
{
@ -288,12 +281,6 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
}
bool
RenderFrameParent::HitTest(const nsRect& aRect)
{
return mTouchRegion.Contains(aRect);
}
void
RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
@ -354,7 +341,6 @@ nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
{
if (aBuilder->IsBuildingLayerEventRegions()) {
bool frameIsPointerEventsNone =
!aFrame->PassPointerEventsToChildren() &&
aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame) ==
NS_STYLE_POINTER_EVENTS_NONE;
if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) {
@ -380,13 +366,3 @@ nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
}
return layer.forget();
}
void
nsDisplayRemote::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
if (mRemoteFrame->HitTest(aRect)) {
aOutFrames->AppendElement(mFrame);
}
}

Просмотреть файл

@ -91,8 +91,6 @@ protected:
virtual bool RecvNotifyCompositorTransaction() override;
virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
private:
void TriggerRepaint();
void DispatchEventForPanZoomController(const InputEvent& aEvent);
@ -123,8 +121,6 @@ private:
// mFrameLoaderDestroyed==false.
bool mFrameLoaderDestroyed;
nsRegion mTouchRegion;
bool mAsyncPanZoomEnabled;
bool mInitted;
};
@ -154,9 +150,6 @@ public:
BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE)
private:

Просмотреть файл

@ -6,20 +6,20 @@ window.onload = function() {
ctx.lineWidth = 5;
ctx.mozDash = [ 5, 10 ]; // 5 on, 10 off
ctx.setLineDash([ 5, 10 ]); // 5 on, 10 off
ctx.moveTo(50, 50);
ctx.lineTo(250, 50);
ctx.stroke();
ctx.beginPath();
ctx.mozDashOffset = 5;
ctx.lineDashOffset = 5;
ctx.moveTo(50, 100);
ctx.lineTo(250, 100);
ctx.stroke();
ctx.beginPath();
ctx.mozDashOffset = 5;
ctx.mozDash = [ 5 ]; // 5 on, 5 off
ctx.lineDashOffset = 5;
ctx.setLineDash([ 5 ]); // 5 on, 5 off
ctx.moveTo(50, 150);
ctx.lineTo(250, 150);
ctx.stroke();

Просмотреть файл

@ -6,70 +6,83 @@ window.onload = function() {
try {
var ctx = document.getElementById("c1").getContext("2d");
assert(null === ctx.mozDash,
"Default dash is null (no dash)");
assert(0 == ctx.mozDashOffset,
"Default dashOffset is 0 (no dash)");
assert(0 === ctx.getLineDash().length,
"Default dash is [ ] (none)");
assert(0 === ctx.lineDashOffset,
"Default dashOffset is 0 (none)");
ctx.mozDash = [ 2 ];
assert(1 == ctx.mozDash.length && 2 == ctx.mozDash[0],
ctx.setLineDash([ 2 ]);
assert(2 === ctx.getLineDash().length &&
2 === ctx.getLineDash()[0] &&
2 === ctx.getLineDash()[1],
"dash = [ 2 ] works");
ctx.mozDash = null;
assert(null === ctx.mozDash,
"dash = null resets to null");
ctx.mozDash = [ 2 ];
ctx.mozDash = undefined;
assert(null === ctx.mozDash,
"dash = undefined resets to null");
ctx.mozDash = [ 2 ];
ctx.mozDash = [ ];
assert(null === ctx.mozDash,
"dash = [] resets to null");
ctx.setLineDash([ 2 ]);
ctx.setLineDash([ ]);
assert(0 === ctx.getLineDash().length,
"dash = [ ] works");
ctx.setLineDash([ 2 ]);
ctx.setLineDash([ 0, 0, 0 ]);
assert(6 === ctx.getLineDash().length,
0 === ctx.getLineDash()[0] &&
0 === ctx.getLineDash()[1] &&
0 === ctx.getLineDash()[2] &&
0 === ctx.getLineDash()[3] &&
0 === ctx.getLineDash()[4] &&
0 === ctx.getLineDash()[5],
"dash = [ 0, 0, 0 ] works");
ctx.mozDash = [ 2 ];
assert(0 == ctx.mozDashOffset, "dashOffset is 0");
ctx.mozDashOffset = 1;
assert(1 == ctx.mozDashOffset, "Setting dashOffset succeeded");
ctx.mozDash = null;
assert(0 == ctx.mozDashOffset, "Disabling dash resets dashOffset");
ctx.mozDash = [ 2 ];
assert(0 == ctx.mozDashOffset, "Previous dashOffset isn't remembered");
ctx.mozDash = null;
ctx.setLineDash([ 2 ]);
assert(0 === ctx.lineDashOffset, "dashOffset is 0");
ctx.lineDashOffset = 1;
assert(1 === ctx.lineDashOffset, "Setting dashOffset succeeded");
ctx.setLineDash([ ]);
assert(1 === ctx.lineDashOffset, "Changing dash does not reset dashOffset");
// NB: might want to add a |.dash = number| special case,
// don't test that it fails here. Might also want to add a
// |.dash = [0]| special case for resetting, so don't test
// that either.
var badVals = [ -1,
null,
undefined,
"",
"string",
/* According to the WebIDL sequence-ifying
* (really they mean array-ifying here)
* algorithm, objects without .length
* properties convert to a 0-length arrays.
* This seems ... odd, since by the book we're
* forced to accept |ctx.dash = Function|,
* e.g., but there it is.
*/
// { obj: true },
[ "array of string" ],
[ -1 ],
[ 0, 0, 0 ],
[ 2, "string" ],
];
ctx.mozDash = [ 2 ];
{ obj: true },
function() {}
]
ctx.setLineDash([ 2 ]);
for (var i = 0; i < badVals.length; ++i) {
var error = false;
try { ctx.mozDash = badVals[i]; }
try { ctx.setLineDash(badVals[i]); }
catch(e) { error = true; }
assert(error && 1 == ctx.mozDash.length && 2 == ctx.mozDash[0],
"Expected |dash = "+ badVals[i] +"| to throw exception and not change .dash");
assert(error &&
2 === ctx.getLineDash().length &&
2 === ctx.getLineDash()[0] &&
2 === ctx.getLineDash()[1],
"Expected setLineDash("+ badVals[i] +") to throw exception and not change dash");
}
ctx.mozDash = null;
var ignoredVals = [
[ "array of string" ],
[ -1 ],
[ 2, "string" ],
];
ctx.setLineDash([ 2 ]);
for (var i = 0; i < ignoredVals.length; ++i) {
ctx.setLineDash(ignoredVals[i]);
assert(2 === ctx.getLineDash().length &&
2 === ctx.getLineDash()[0] &&
2 === ctx.getLineDash()[1],
"Expected |setLineDash(" + ignoredVals[i] + ") to not change dash");
}
ctx.setLineDash([ 2 ]);
ctx.save();
ctx.mozDash = [ 2 ];
ctx.setLineDash([ 1, 1, 1, 1 ]);
ctx.restore();
assert(null === ctx.mozDash,
assert(2 === ctx.getLineDash().length &&
2 === ctx.getLineDash()[0] &&
2 === ctx.getLineDash()[1],
"dash was saved then restored");
} catch (e) {
document.body.innerHTML = "FAIL: "+ e.toString();

Просмотреть файл

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="600" height="400">
<circle cx="300" cy="200" r="100" style="fill:blue;"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 182 B

Просмотреть файл

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="600" height="400" preserveAspectRatio="none"
viewBox="50 100 500 200"
class="reftest-wait"
onload="setTimeAndSnapshot(1, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="50" y="100" width="500" height="200" style="fill:blue;"
clip-path="circle(100px at center) view-box"/>
<animate attributeName="viewBox" values="50 100 500 200; 0 0 600 400"
dur="0.5s" fill="freeze"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 543 B

Просмотреть файл

@ -279,3 +279,5 @@ fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,2) == anim-gradient-attr-presence-0
# Test animation that changes 'display' attribute
== anim-display.svg lime.svg
== anim-display-in-g-element.svg lime.svg
pref(layout.css.clip-path-shapes.enabled,true) fuzzy(63,146) == anim-clipPath-viewBox.svg anim-clipPath-viewBox-ref.svg

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше