mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 21:55:31 +00:00
Merge mozilla-central to autoland
This commit is contained in:
commit
06332a09b7
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
246
accessible/windows/msaa/MsaaIdGenerator.cpp
Normal file
246
accessible/windows/msaa/MsaaIdGenerator.cpp
Normal file
@ -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
|
57
accessible/windows/msaa/MsaaIdGenerator.h
Normal file
57
accessible/windows/msaa/MsaaIdGenerator.h
Normal file
@ -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) {
|
||||
|
@ -47,12 +47,6 @@ let allowedImageReferences = [
|
||||
{file: "chrome/devtools/modules/devtools/client/themes/images/filter.svg",
|
||||
from: "chrome/devtools/modules/devtools/client/themes/common.css",
|
||||
isFromDevTools: true},
|
||||
|
||||
// Bug 1302890
|
||||
{file: "chrome://global/skin/icons/warning-32.png",
|
||||
from: "chrome://devtools/skin/tooltips.css",
|
||||
platforms: ["linux", "win"],
|
||||
isFromDevTools: true},
|
||||
];
|
||||
|
||||
var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
|
||||
|
@ -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;
|
||||
|
@ -140,7 +140,7 @@ ToolbarView.prototype = {
|
||||
showResumeWarning: function (aPausedUrl) {
|
||||
let label = L10N.getFormatStr("resumptionOrderPanelTitle", aPausedUrl);
|
||||
let defaultStyle = "default-tooltip-simple-text-colors";
|
||||
this._resumeOrderTooltip.setTextContent({ messages: [label], isAlertTooltip: true });
|
||||
this._resumeOrderTooltip.setTextContent({ messages: [label] });
|
||||
this._resumeOrderTooltip.show(this._resumeButton);
|
||||
},
|
||||
|
||||
|
@ -356,15 +356,12 @@ Tooltip.prototype = {
|
||||
* A style class for the text messages.
|
||||
* @param {string} containerClass [optional]
|
||||
* A style class for the text messages container.
|
||||
* @param {boolean} isAlertTooltip [optional]
|
||||
* Pass true to add an alert image for your tooltip.
|
||||
*/
|
||||
setTextContent: function (
|
||||
{
|
||||
messages,
|
||||
messagesClass,
|
||||
containerClass,
|
||||
isAlertTooltip
|
||||
containerClass
|
||||
},
|
||||
extraButtons = []) {
|
||||
messagesClass = messagesClass || "default-tooltip-simple-text-colors";
|
||||
@ -390,18 +387,7 @@ Tooltip.prototype = {
|
||||
vbox.appendChild(button);
|
||||
}
|
||||
|
||||
if (isAlertTooltip) {
|
||||
let hbox = this.doc.createElement("hbox");
|
||||
hbox.setAttribute("align", "start");
|
||||
|
||||
let alertImg = this.doc.createElement("image");
|
||||
alertImg.className = "devtools-tooltip-alert-icon";
|
||||
hbox.appendChild(alertImg);
|
||||
hbox.appendChild(vbox);
|
||||
this.content = hbox;
|
||||
} else {
|
||||
this.content = vbox;
|
||||
}
|
||||
this.content = vbox;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -72,19 +72,6 @@
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
/* Tooltip: Alert Icon */
|
||||
|
||||
.devtools-tooltip-alert-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 6px;
|
||||
margin-inline-end: 20px;
|
||||
}
|
||||
|
||||
.devtools-tooltip-alert-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/warning-32.png");
|
||||
}
|
||||
|
||||
/* Tooltip: Variables View */
|
||||
|
||||
.devtools-tooltip-variables-view-box {
|
||||
|
@ -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]
|
||||
|
51
docshell/test/test_forceinheritprincipal_overrule_owner.html
Normal file
51
docshell/test/test_forceinheritprincipal_overrule_owner.html
Normal file
@ -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");
|
||||
}
|
||||
|
10
js/src/jit-test/tests/debug/bug1302432.js
Normal file
10
js/src/jit-test/tests/debug/bug1302432.js
Normal file
@ -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();
|
8
js/src/jit-test/tests/wasm/full-cycle.js
Normal file
8
js/src/jit-test/tests/wasm/full-cycle.js
Normal file
@ -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();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user