Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2017-04-06 13:11:40 +02:00
Родитель ca5876370d 207b516e89
Коммит 1aa7e647b7
196 изменённых файлов: 5070 добавлений и 1141 удалений

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

@ -18,9 +18,7 @@ StyleInfo::StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell) :
mElement(aElement)
{
mStyleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nullptr,
aPresShell);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, aPresShell);
}
void

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

@ -25,6 +25,8 @@
#define __XMLDocument_FWD_DEFINED__
#endif // !defined(__XMLDocument_FWD_DEFINED__)
#include <combaseapi.h>
#include "mozilla/a11y/COMPtrTypes.h"
// This define in rpcndr.h messes up our code, so we must undefine it after
@ -39,6 +41,7 @@ namespace mozilla {
namespace a11y {
typedef uint32_t IAccessibleHolder;
typedef uint32_t IHandlerControlHolder;
} // namespace a11y
} // namespace mozilla

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

@ -6,13 +6,19 @@
#include "mozilla/a11y/COMPtrTypes.h"
#include "Accessible2_3.h"
#include "MainThreadUtils.h"
#include "mozilla/a11y/Accessible.h"
#include "mozilla/a11y/HandlerProvider.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/MainThreadHandoff.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/Preferences.h"
#include "mozilla/RefPtr.h"
#include "nsXULAppAPI.h"
using mozilla::mscom::MainThreadHandoff;
using mozilla::mscom::ProxyUniquePtr;
using mozilla::mscom::STAUniquePtr;
namespace mozilla {
@ -26,24 +32,44 @@ CreateHolderFromAccessible(Accessible* aAccToWrap)
return nullptr;
}
IAccessible* rawNative = nullptr;
aAccToWrap->GetNativeInterface((void**)&rawNative);
MOZ_ASSERT(rawNative);
if (!rawNative) {
STAUniquePtr<IAccessible> iaToProxy;
aAccToWrap->GetNativeInterface(mscom::getter_AddRefs(iaToProxy));
MOZ_ASSERT(iaToProxy);
if (!iaToProxy) {
return nullptr;
}
STAUniquePtr<IAccessible> iaToProxy(rawNative);
static const bool useHandler =
Preferences::GetBool("accessibility.handler.enabled", false);
IAccessible* rawIntercepted = nullptr;
HRESULT hr = MainThreadHandoff::WrapInterface(Move(iaToProxy), &rawIntercepted);
RefPtr<HandlerProvider> payload;
if (useHandler) {
payload = new HandlerProvider(IID_IAccessible,
mscom::ToInterceptorTargetPtr(iaToProxy));
}
ProxyUniquePtr<IAccessible> intercepted;
HRESULT hr = MainThreadHandoff::WrapInterface(Move(iaToProxy), payload,
(IAccessible**) mscom::getter_AddRefs(intercepted));
MOZ_ASSERT(SUCCEEDED(hr));
if (FAILED(hr)) {
return nullptr;
}
IAccessibleHolder::COMPtrType iaIntercepted(rawIntercepted);
return IAccessibleHolder(Move(iaIntercepted));
return IAccessibleHolder(Move(intercepted));
}
IHandlerControlHolder
CreateHolderFromHandlerControl(mscom::ProxyUniquePtr<IHandlerControl> aHandlerControl)
{
MOZ_ASSERT(aHandlerControl);
MOZ_ASSERT(XRE_IsContentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!aHandlerControl) {
return nullptr;
}
return IHandlerControlHolder(Move(aHandlerControl));
}
} // namespace a11y

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

@ -7,6 +7,7 @@
#ifndef mozilla_a11y_COMPtrTypes_h
#define mozilla_a11y_COMPtrTypes_h
#include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/mscom/COMPtrHolder.h"
#include <oleacc.h>
@ -21,6 +22,11 @@ class Accessible;
IAccessibleHolder
CreateHolderFromAccessible(Accessible* aAccToWrap);
typedef mozilla::mscom::COMPtrHolder<IHandlerControl, IID_IHandlerControl> IHandlerControlHolder;
IHandlerControlHolder
CreateHolderFromHandlerControl(mscom::ProxyUniquePtr<IHandlerControl> aHandlerControl);
} // namespace a11y
} // namespace mozilla

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

@ -0,0 +1,263 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#define INITGUID
#include "mozilla/a11y/HandlerProvider.h"
#include "Accessible2_3.h"
#include "HandlerData.h"
#include "HandlerData_i.c"
#include "mozilla/Assertions.h"
#include "mozilla/a11y/AccessibleWrap.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/AgileReference.h"
#include "mozilla/mscom/MainThreadInvoker.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/mscom/Utils.h"
#include "nsThreadUtils.h"
#include <memory.h>
namespace mozilla {
namespace a11y {
HandlerProvider::HandlerProvider(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget)
: mRefCnt(0)
, mMutex("mozilla::a11y::HandlerProvider::mMutex")
, mTargetUnkIid(aIid)
, mTargetUnk(Move(aTarget))
{
}
HRESULT
HandlerProvider::QueryInterface(REFIID riid, void** ppv)
{
if (!ppv) {
return E_INVALIDARG;
}
RefPtr<IUnknown> punk;
if (riid == IID_IUnknown || riid == IID_IGeckoBackChannel) {
punk = static_cast<IGeckoBackChannel*>(this);
}
if (!punk) {
return E_NOINTERFACE;
}
punk.forget(ppv);
return S_OK;
}
ULONG
HandlerProvider::AddRef()
{
return ++mRefCnt;
}
ULONG
HandlerProvider::Release()
{
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
HRESULT
HandlerProvider::GetHandler(NotNull<CLSID*> aHandlerClsid)
{
if (!IsTargetInterfaceCacheable()) {
return E_NOINTERFACE;
}
*aHandlerClsid = CLSID_AccessibleHandler;
return S_OK;
}
void
HandlerProvider::GetAndSerializePayload(const MutexAutoLock&)
{
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (mSerializer) {
return;
}
IA2Payload payload{};
if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
&payload.mData) ||
!payload.mData.mUniqueId) {
return;
}
// But we set mGeckoBackChannel on the current thread which resides in the
// MTA. This is important to ensure that COM always invokes
// IGeckoBackChannel methods in an MTA background thread.
RefPtr<IGeckoBackChannel> payloadRef(this);
// AddRef/Release pair for this reference is handled by payloadRef
payload.mGeckoBackChannel = this;
mSerializer = MakeUnique<mscom::StructToStream>(payload, &IA2Payload_Encode);
// Now that we have serialized payload, we should free any BSTRs that were
// allocated in BuildIA2Data.
ClearIA2Data(payload.mData);
}
HRESULT
HandlerProvider::GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize)
{
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!IsTargetInterfaceCacheable()) {
*aOutPayloadSize = mscom::StructToStream::GetEmptySize();
return S_OK;
}
MutexAutoLock lock(mMutex);
GetAndSerializePayload(lock);
if (!mSerializer) {
return E_FAIL;
}
*aOutPayloadSize = mSerializer->GetSize();
return S_OK;
}
void
HandlerProvider::BuildIA2Data(IA2Data* aOutIA2Data)
{
MOZ_ASSERT(aOutIA2Data);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mTargetUnk);
MOZ_ASSERT(IsTargetInterfaceCacheable());
RefPtr<NEWEST_IA2_INTERFACE>
target(static_cast<NEWEST_IA2_INTERFACE*>(mTargetUnk.get()));
// NB: get_uniqueID should be the final property retrieved in this method,
// as its presence is used to determine whether the rest of this data
// retrieval was successful.
HRESULT hr = target->get_uniqueID(&aOutIA2Data->mUniqueId);
if (FAILED(hr)) {
ClearIA2Data(*aOutIA2Data);
}
}
void
HandlerProvider::ClearIA2Data(IA2Data& aData)
{
ZeroMemory(&aData, sizeof(IA2Data));
}
bool
HandlerProvider::IsTargetInterfaceCacheable()
{
return MarshalAs(mTargetUnkIid) == NEWEST_IA2_IID;
}
HRESULT
HandlerProvider::WriteHandlerPayload(NotNull<IStream*> aStream)
{
MutexAutoLock lock(mMutex);
if (!mSerializer) {
mscom::StructToStream emptyStruct;
return emptyStruct.Write(aStream);
}
HRESULT hr = mSerializer->Write(aStream);
mSerializer.reset();
return hr;
}
REFIID
HandlerProvider::MarshalAs(REFIID aIid)
{
static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
"You have modified NEWEST_IA2_IID. This code needs updating.");
if (aIid == IID_IDispatch || aIid == IID_IAccessible ||
aIid == IID_IAccessible2 || aIid == IID_IAccessible2_2 ||
aIid == IID_IAccessible2_3) {
// This should always be the newest IA2 interface ID
return NEWEST_IA2_IID;
}
// Otherwise we juse return the identity.
return aIid;
}
HRESULT
HandlerProvider::NewInstance(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget,
NotNull<mscom::IHandlerProvider**> aOutNewPayload)
{
RefPtr<IHandlerProvider> newPayload(new HandlerProvider(aIid, Move(aTarget)));
newPayload.forget(aOutNewPayload.get());
return S_OK;
}
void
HandlerProvider::SetHandlerControlOnMainThread(DWORD aPid,
mscom::ProxyUniquePtr<IHandlerControl> aCtrl)
{
MOZ_ASSERT(NS_IsMainThread());
auto content = dom::ContentChild::GetSingleton();
MOZ_ASSERT(content);
IHandlerControlHolder holder(CreateHolderFromHandlerControl(Move(aCtrl)));
Unused << content->SendA11yHandlerControl(aPid, holder);
}
HRESULT
HandlerProvider::put_HandlerControl(long aPid, IHandlerControl* aCtrl)
{
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!aCtrl) {
return E_INVALIDARG;
}
auto ptrProxy = mscom::ToProxyUniquePtr(aCtrl);
if (!mscom::InvokeOnMainThread(this,
&HandlerProvider::SetHandlerControlOnMainThread,
static_cast<DWORD>(aPid), Move(ptrProxy))) {
return E_FAIL;
}
return S_OK;
}
HRESULT
HandlerProvider::Refresh(IA2Data* aOutData)
{
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
aOutData)) {
return E_FAIL;
}
return S_OK;
}
} // namespace a11y
} // namespace mozilla

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

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_HandlerProvider_h
#define mozilla_a11y_HandlerProvider_h
#include "handler/AccessibleHandler.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Atomics.h"
#include "mozilla/mscom/IHandlerProvider.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
struct NEWEST_IA2_INTERFACE;
namespace mozilla {
namespace mscom {
class StructToStream;
} // namespace mscom
namespace a11y {
class HandlerProvider final : public IGeckoBackChannel
, public mscom::IHandlerProvider
{
public:
HandlerProvider(REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IHandlerProvider
STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override;
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
STDMETHODIMP NewInstance(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget,
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;
// IGeckoBackChannel
STDMETHODIMP put_HandlerControl(long aPid, IHandlerControl* aCtrl) override;
STDMETHODIMP Refresh(IA2Data* aOutData) override;
private:
~HandlerProvider() = default;
void SetHandlerControlOnMainThread(DWORD aPid,
mscom::ProxyUniquePtr<IHandlerControl> aCtrl);
void GetAndSerializePayload(const MutexAutoLock&);
void BuildIA2Data(IA2Data* aOutIA2Data);
static void ClearIA2Data(IA2Data& aData);
bool IsTargetInterfaceCacheable();
Atomic<uint32_t> mRefCnt;
Mutex mMutex; // Protects mSerializer
REFIID mTargetUnkIid;
mscom::InterceptorTargetPtr<IUnknown> mTargetUnk; // Constant, main thread only
UniquePtr<mscom::StructToStream> mSerializer;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerProvider_h

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,10 @@
;+# 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/.
LIBRARY AccessibleHandler.dll
EXPORTS DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

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

@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_AccessibleHandler_h
#define mozilla_a11y_AccessibleHandler_h
#define NEWEST_IA2_BASENAME Accessible2_3
#define __QUOTE(idl) #idl
#define __GENIDL(base) __QUOTE(base##.idl)
#define IDLFOR(base) __GENIDL(base)
#define NEWEST_IA2_IDL IDLFOR(NEWEST_IA2_BASENAME)
#define __GENIFACE(base) I##base
#define INTERFACEFOR(base) __GENIFACE(base)
#define NEWEST_IA2_INTERFACE INTERFACEFOR(NEWEST_IA2_BASENAME)
#define __GENIID(iface) IID_##iface
#define IIDFOR(iface) __GENIID(iface)
#define NEWEST_IA2_IID IIDFOR(NEWEST_IA2_INTERFACE)
#if defined(__midl)
import NEWEST_IA2_IDL;
#else
#include "HandlerData.h"
#include <windows.h>
#if !defined(MOZILLA_INTERNAL_API)
#include "Accessible2_3.h"
#include "Handler.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/UniquePtr.h"
#include <ocidl.h>
#include <servprov.h>
namespace mozilla {
namespace a11y {
class AccessibleHandler final : public mscom::Handler
, public NEWEST_IA2_INTERFACE
, public IServiceProvider
, public IProvideClassInfo
{
public:
static HRESULT Create(IUnknown* aOuter, REFIID aIid, void** aOutInterface);
// mscom::Handler
HRESULT QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
void** aOutInterface) override;
HRESULT ReadHandlerPayload(IStream* aStream, REFIID aIid) override;
REFIID MarshalAs(REFIID aRequestedIid) override;
HRESULT GetHandlerPayloadSize(REFIID aIid, DWORD* aOutPayloadSize) override;
HRESULT WriteHandlerPayload(IStream* aStream, REFIID aIId) override;
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) override;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override;
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId) override;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr) override;
// IAccessible
STDMETHODIMP get_accParent(IDispatch **ppdispParent) override;
STDMETHODIMP get_accChildCount(long *pcountChildren) override;
STDMETHODIMP get_accChild(VARIANT varChild, IDispatch **ppdispChild) override;
STDMETHODIMP get_accName(VARIANT varChild, BSTR *pszName) override;
STDMETHODIMP get_accValue(VARIANT varChild, BSTR *pszValue) override;
STDMETHODIMP get_accDescription(VARIANT varChild, BSTR *pszDescription) override;
STDMETHODIMP get_accRole(VARIANT varChild, VARIANT *pvarRole) override;
STDMETHODIMP get_accState(VARIANT varChild, VARIANT *pvarState) override;
STDMETHODIMP get_accHelp(VARIANT varChild, BSTR *pszHelp) override;
STDMETHODIMP get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild,
long *pidTopic) override;
STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild,
BSTR *pszKeyboardShortcut) override;
STDMETHODIMP get_accFocus(VARIANT *pvarChild) override;
STDMETHODIMP get_accSelection(VARIANT *pvarChildren) override;
STDMETHODIMP get_accDefaultAction(VARIANT varChild,
BSTR *pszDefaultAction) override;
STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
STDMETHODIMP accLocation(long *pxLeft, long *pyTop, long *pcxWidth,
long *pcyHeight, VARIANT varChild) override;
STDMETHODIMP accNavigate(long navDir, VARIANT varStart,
VARIANT *pvarEndUpAt) override;
STDMETHODIMP accHitTest( long xLeft, long yTop, VARIANT *pvarChild) override;
STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
// IAccessible2
STDMETHODIMP get_nRelations(long* nRelations) override;
STDMETHODIMP get_relation(long relationIndex,
IAccessibleRelation** relation) override;
STDMETHODIMP get_relations(long maxRelations, IAccessibleRelation** relations,
long* nRelations) override;
STDMETHODIMP role(long* role) override;
STDMETHODIMP scrollTo(IA2ScrollType scrollType) override;
STDMETHODIMP scrollToPoint(IA2CoordinateType coordinateType, long x,
long y) override;
STDMETHODIMP get_groupPosition(long* groupLevel, long* similarItemsInGroup,
long* positionInGroup) override;
STDMETHODIMP get_states(AccessibleStates* states) override;
STDMETHODIMP get_extendedRole(BSTR* extendedRole) override;
STDMETHODIMP get_localizedExtendedRole(BSTR* localizedExtendedRole) override;
STDMETHODIMP get_nExtendedStates(long* nExtendedStates) override;
STDMETHODIMP get_extendedStates(long maxExtendedStates, BSTR** extendedStates,
long* nExtendedStates) override;
STDMETHODIMP get_localizedExtendedStates(long maxLocalizedExtendedStates,
BSTR** localizedExtendedStates,
long* nLocalizedExtendedStates) override;
STDMETHODIMP get_uniqueID(long* uniqueID) override;
STDMETHODIMP get_windowHandle(HWND* windowHandle) override;
STDMETHODIMP get_indexInParent(long* indexInParent) override;
STDMETHODIMP get_locale(IA2Locale* locale) override;
STDMETHODIMP get_attributes(BSTR* attributes) override;
// IAccessible2_2
STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) override;
STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
long* caretOffset) override;
STDMETHODIMP get_relationTargetsOfType(BSTR type, long maxTargets,
IUnknown*** targets,
long* nTargets) override;
// IAccessible2_3
STDMETHODIMP get_selectionRanges(IA2Range** ranges, long* nRanges) override;
// IServiceProvider
STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aIid,
void** aOutInterface) override;
// IProvideClassInfo
STDMETHODIMP GetClassInfo(ITypeInfo** aOutTypeInfo) override;
private:
AccessibleHandler(IUnknown* aOuter, HRESULT* aResult);
virtual ~AccessibleHandler();
HRESULT ResolveIA2();
HRESULT ResolveIDispatch();
HRESULT MaybeUpdateCachedData();
RefPtr<IUnknown> mDispatchUnk;
/**
* Handlers aggregate their proxies. This means that their proxies delegate
* their IUnknown implementation to us.
*
* mDispatchUnk and the result of Handler::GetProxy() are both strong
* references to the aggregated objects. OTOH, any interfaces that are QI'd
* from those aggregated objects have delegated unknowns.
*
* AddRef'ing an interface with a delegated unknown ends up incrementing the
* refcount of the *aggregator*. Since we are the aggregator of mDispatchUnk
* and of the wrapped proxy, holding a strong reference to any interfaces
* QI'd off of those objects would create a reference cycle.
*
* We may hold onto pointers to those references, but when we query them we
* must immediately Release() them to prevent these cycles.
*
* It is safe for us to use these raw pointers because the aggregated
* objects's lifetimes are proper subsets of our own lifetime.
*/
IDispatch* mDispatch; // weak
NEWEST_IA2_INTERFACE* mIA2PassThru; // weak
IServiceProvider* mServProvPassThru; // weak
IA2Payload mCachedData;
UniquePtr<mscom::StructToStream> mSerializer;
uint32_t mCacheGen;
};
} // namespace a11y
} // namespace mozilla
#endif // !defined(MOZILLA_INTERNAL_API)
#endif // defined(__midl)
#endif // mozilla_a11y_AccessibleHandler_h

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

@ -0,0 +1,5 @@
/* 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/. */
1 typelib HandlerData.tlb

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

@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#if defined(MOZILLA_INTERNAL_API)
#error This code is NOT for internal Gecko use!
#endif // defined(MOZILLA_INTERNAL_API)
#include "AccessibleHandlerControl.h"
#include "AccessibleHandler.h"
#include "AccessibleEventId.h"
#include "mozilla/Move.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
HRESULT
AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
{
if (!aOutObject) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(new AccessibleHandlerControl());
ctl.forget(aOutObject);
return S_OK;
}
AccessibleHandlerControl::AccessibleHandlerControl()
: mRefCnt(0)
, mCacheGen(0)
, mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll"))
, mHandlerProxy(mscom::RegisterProxy())
{
MOZ_ASSERT(mIA2Proxy);
}
HRESULT
AccessibleHandlerControl::QueryInterface(REFIID aIid, void** aOutInterface)
{
if (!aOutInterface) {
return E_INVALIDARG;
}
if (aIid == IID_IUnknown || aIid == IID_IHandlerControl) {
RefPtr<IHandlerControl> ctl(this);
ctl.forget(aOutInterface);
return S_OK;
}
*aOutInterface = nullptr;
return E_NOINTERFACE;
}
ULONG
AccessibleHandlerControl::AddRef()
{
return ++mRefCnt;
}
ULONG
AccessibleHandlerControl::Release()
{
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
HRESULT
AccessibleHandlerControl::Invalidate()
{
++mCacheGen;
return S_OK;
}
HRESULT
AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo)
{
if (!mHandlerProxy) {
return E_UNEXPECTED;
}
return mHandlerProxy->GetTypeInfoForGuid(CLSID_AccessibleHandler,
aOutTypeInfo);
}
} // namespace a11y
} // namespace mozilla

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

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#if defined(MOZILLA_INTERNAL_API)
#error This code is NOT for internal Gecko use!
#endif // defined(MOZILLA_INTERNAL_API)
#ifndef mozilla_a11y_AccessibleHandlerControl_h
#define mozilla_a11y_AccessibleHandlerControl_h
#include "Factory.h"
#include "HandlerData.h"
#include "mozilla/mscom/Registration.h"
namespace mozilla {
namespace a11y {
class AccessibleHandlerControl final : public IHandlerControl
{
public:
static HRESULT Create(AccessibleHandlerControl** aOutObject);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IHandlerControl
STDMETHODIMP Invalidate() override;
uint32_t GetCacheGen() const
{
return mCacheGen;
}
HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
private:
AccessibleHandlerControl();
~AccessibleHandlerControl() = default;
ULONG mRefCnt;
uint32_t mCacheGen;
UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
};
extern mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_AccessibleHandlerControl_h

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

@ -0,0 +1,11 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
[explicit_handle]
interface HandlerData
{
typedef [encode,decode] IA2Payload;
}

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

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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 "AccessibleHandler.h"
import "ocidl.idl";
import "ServProv.idl";
typedef struct _IA2Data
{
long mUniqueId;
} IA2Data;
interface IGeckoBackChannel;
// We define different CLSIDs and IIDs depending on channel and officiality.
// This prevents handlers from installing overtop one another when multiple
// channels are present. Note that we do not do this for all UUIDs in this IDL,
// just the ones that are written to the registry (coclass and interfaces that
// have the [object] annotation)
#if !defined(MOZ_OFFICIAL_BRANDING)
# if defined(DEBUG)
// Local debug builds
# define HANDLER_CLSID 398ffd8d-5382-48f7-9e3b-19012762d39a
# define IHANDLERCONTROL_IID a218497e-8b10-460b-b668-a92b7ee39ff2
# define ASYNCIHANDLERCONTROL_IID ca18b9ab-04b6-41be-87f7-d99913d6a2e8
# define IGECKOBACKCHANNEL_IID 231c4946-4479-4c8e-aadc-8a0e48fc4c51
# else
// Local non-debug builds
# define HANDLER_CLSID ce573faf-7815-4fc2-a031-b092268ace9e
# define IHANDLERCONTROL_IID 2b715cce-1790-4fe1-aef5-48bb5acdf3a1
# define ASYNCIHANDLERCONTROL_IID 8e089670-4f57-41a7-89c0-37f17482fa6f
# define IGECKOBACKCHANNEL_IID 18e2488d-310f-400f-8339-0e50b513e801
# endif
#elif defined(NIGHTLY_BUILD)
// Official Nightly
# define IHANDLERCONTROL_IID c57343fc-e011-40c2-b748-da82eabf0f1f
# define ASYNCIHANDLERCONTROL_IID 648c92a1-ea35-46da-a806-6b55c6247373
# define HANDLER_CLSID 4629216b-8753-41bf-9527-5bff51401671
# define IGECKOBACKCHANNEL_IID e61e038d-40dd-464a-9aba-66b206b6911b
#elif defined(RELEASE_OR_BETA)
// Official Beta and Official Release
# define IHANDLERCONTROL_IID ce30f77e-8847-44f0-a648-a9656bd89c0d
# define ASYNCIHANDLERCONTROL_IID dca8d857-1a63-4045-8f36-8809eb093d04
# define HANDLER_CLSID 1baa303d-b4b9-45e5-9ccb-e3fca3e274b6
# define IGECKOBACKCHANNEL_IID b32983ff-ef84-4945-8f86-fb7491b4f57b
#else
// Official Aurora
# define IHANDLERCONTROL_IID 3316ce35-f892-4832-97c5-06c52c03cdba
# define ASYNCIHANDLERCONTROL_IID 15b48b76-ad38-4ad3-bd1a-d3c48a5a9947
# define HANDLER_CLSID 4a195748-dca2-45fb-9295-0a139e76a9e7
# define IGECKOBACKCHANNEL_IID dd2e4a89-999e-4d65-8b65-440c923ddb61
#endif
[uuid(2b0e83b3-fd1a-443f-9ed6-c00d39055b58)]
interface HandlerData
{
typedef struct _IA2Payload
{
IA2Data mData;
IGeckoBackChannel* mGeckoBackChannel;
} IA2Payload;
}
[object,
uuid(IHANDLERCONTROL_IID),
async_uuid(ASYNCIHANDLERCONTROL_IID),
pointer_default(unique)]
interface IHandlerControl : IUnknown
{
HRESULT Invalidate();
}
[object,
uuid(IGECKOBACKCHANNEL_IID),
pointer_default(unique)]
interface IGeckoBackChannel : IUnknown
{
[propput] HRESULT HandlerControl([in] long aPid, [in] IHandlerControl* aCtrl);
HRESULT Refresh([out] IA2Data* aOutData);
}
[uuid(1e545f07-f108-4912-9471-546827a80983)]
library AccessibleHandlerTypeLib
{
/**
* This definition is required in order for the handler implementation to
* support IDispatch (aka Automation). This is used by interpreted language
* FFIs to discover which interfaces may be controlled via IDispatch.
* (In particular, the python FFI used by NVDA needs this).
*
* In reality, the only a11y interface that is Automation compliant is
* IAccessible; our remaining interfaces are not.
*
* Once the FFI knows that IAccessible is supported, the FFI queries for
* IAccessible and is then able to resolve non-automation interfaces from
* there.
*/
[uuid(HANDLER_CLSID)]
coclass AccessibleHandler
{
[default] interface IAccessible;
};
};

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

@ -0,0 +1,38 @@
# 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/.
IA2DIR = $(topsrcdir)/other-licenses/ia2
MSAADIR = $(topsrcdir)/accessible/interfaces/msaa
GARBAGE += $(MIDL_GENERATED_FILES) midl_done
MIDL_GENERATED_FILES = \
dlldata.c \
HandlerData.h \
HandlerData_c.c \
HandlerData_i.c \
HandlerData_p.c \
HandlerData.tlb \
$(NULL)
export:: $(MIDL_GENERATED_FILES)
$(MIDL_GENERATED_FILES): midl_done
midl_done: HandlerData.acf HandlerData.idl
$(MIDL) $(MIDL_FLAGS) -I $(IA2DIR) -I $(MSAADIR) -Oicf -acf $(srcdir)/HandlerData.acf $(srcdir)/HandlerData.idl
touch $@
INSTALL_TARGETS += midl
midl_FILES := HandlerData.h \
HandlerData_i.c \
$(NULL)
midl_DEST := $(DIST)/include
midl_TARGET := midl
export:: midl
register::
regsvr32 -s $(DIST)/bin/$(SHARED_LIBRARY)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,60 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SharedLibrary('AccessibleHandler')
EXPORTS.mozilla.a11y += ['AccessibleHandler.h']
LOCAL_INCLUDES += [
'/accessible/interfaces/ia2',
'/ipc/mscom/oop',
]
SOURCES += [
'!dlldata.c',
'!HandlerData_c.c',
'!HandlerData_i.c',
'!HandlerData_p.c',
'AccessibleHandler.cpp',
'AccessibleHandlerControl.cpp',
]
GENERATED_FILES += [
'dlldata.c',
'HandlerData.h',
'HandlerData.tlb',
'HandlerData_c.c',
'HandlerData_i.c',
'HandlerData_p.c',
]
DEFFILE = SRCDIR + '/AccessibleHandler.def'
USE_LIBS += [
'mscom_oop',
]
OS_LIBS += [
'rpcrt4',
]
RCINCLUDE = 'AccessibleHandler.rc'
# Since we are defining our own COM entry points (DllRegisterServer et al),
# but we still want to be able to delegate some work to the generated code,
# we add the prefix "Proxy" to all of the generated counterparts.
DEFINES['ENTRY_PREFIX'] = 'Proxy'
DEFINES['REGISTER_PROXY_DLL'] = True
# This DLL may be loaded into other processes, so we need static libs for
# Windows 7 and Windows 8.
USE_STATIC_LIBS = True
LIBRARY_DEFINES['UNICODE'] = True
LIBRARY_DEFINES['_UNICODE'] = True
LIBRARY_DEFINES['MOZ_NO_MOZALLOC'] = True
DISABLE_STL_WRAPPING = True

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

@ -5,7 +5,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if CONFIG['COMPILE_ENVIRONMENT']:
DIRS += ['typelib']
DIRS += [
'handler',
'typelib',
]
# With --disable-accessibility, we need to compile PDocAccessible.ipdl (which
# also depends on COMPtrTypes.h), but not the C++.
@ -15,13 +18,16 @@ EXPORTS.mozilla.a11y += ['COMPtrTypes.h']
if CONFIG['ACCESSIBILITY']:
EXPORTS.mozilla.a11y += [
'DocAccessibleChild.h',
'HandlerProvider.h',
'PlatformChild.h',
'ProxyAccessible.h'
]
SOURCES += [
'!./handler/HandlerData_c.c',
'COMPtrTypes.cpp',
'DocAccessibleChild.cpp',
'HandlerProvider.cpp',
'PlatformChild.cpp',
'ProxyAccessible.cpp',
]

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

@ -62,6 +62,7 @@ static gAccessibles = 0;
#endif
MsaaIdGenerator AccessibleWrap::sIDGen;
StaticAutoPtr<nsTArray<AccessibleWrap::HandlerControllerData>> AccessibleWrap::sHandlerControllers;
static const VARIANT kVarChildIdSelf = {VT_I4};
@ -1606,3 +1607,23 @@ AccessibleWrap::ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId)
{
sIDGen.ReleaseContentProcessIDFor(aIPCContentId);
}
/* static */
void
AccessibleWrap::SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl)
{
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
if (!sHandlerControllers) {
sHandlerControllers = new nsTArray<HandlerControllerData>();
ClearOnShutdown(&sHandlerControllers);
}
HandlerControllerData ctrlData(aPid, Move(aCtrl));
if (sHandlerControllers->Contains(ctrlData)) {
return;
}
sHandlerControllers->AppendElement(Move(ctrlData));
}

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

@ -14,9 +14,11 @@
#include "ia2AccessibleComponent.h"
#include "ia2AccessibleHyperlink.h"
#include "ia2AccessibleValue.h"
#include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/a11y/MsaaIdGenerator.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "mozilla/Attributes.h"
#include "mozilla/mscom/Utils.h"
#ifdef __GNUC__
// Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
@ -188,6 +190,8 @@ public: // construction, destruction
static uint32_t GetContentProcessIdFor(dom::ContentParentId aIPCContentId);
static void ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId);
static void SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl);
protected:
virtual ~AccessibleWrap();
@ -242,6 +246,39 @@ protected:
NAVRELATION_ERROR = 0x1017,
NAVRELATION_ERROR_FOR = 0x1018
};
struct HandlerControllerData final
{
HandlerControllerData(DWORD aPid, RefPtr<IHandlerControl>&& aCtrl)
: mPid(aPid)
, mCtrl(Move(aCtrl))
{
mIsProxy = mozilla::mscom::IsProxy(mCtrl);
}
HandlerControllerData(HandlerControllerData&& aOther)
: mPid(aOther.mPid)
, mIsProxy(aOther.mIsProxy)
, mCtrl(Move(aOther.mCtrl))
{
}
bool operator==(const HandlerControllerData& aOther) const
{
return mPid == aOther.mPid;
}
bool operator==(const DWORD& aPid) const
{
return mPid == aPid;
}
DWORD mPid;
bool mIsProxy;
RefPtr<IHandlerControl> mCtrl;
};
static StaticAutoPtr<nsTArray<HandlerControllerData>> sHandlerControllers;
};
static inline AccessibleWrap*

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

@ -10,7 +10,7 @@ skip-if = (os == "linux" && debug) # linux: bug 976544
[browser_devices_get_user_media_anim.js]
[browser_devices_get_user_media_in_frame.js]
[browser_devices_get_user_media_multi_process.js]
skip-if = (e10s && debug) # bug 1347625
skip-if = e10s && (asan || debug) # bug 1347625
[browser_devices_get_user_media_screen.js]
skip-if = (os == "linux") || (os == "win" && !debug) # bug 1320994 for linux opt, bug 1338038 for windows and linux debug
[browser_devices_get_user_media_tear_off_tab.js]

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

@ -44,6 +44,7 @@ module.exports = createClass({
let rotate = direction &&
(direction == "left" || direction == "right") &&
box !== "position" &&
textContent.toString().length > LONG_TEXT_ROTATE_LIMIT;
return dom.p(

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

@ -646,6 +646,14 @@ netmonitor.security.connection=Connection:
# in the security tab describing the server certificate section.
netmonitor.security.certificate=Certificate:
# LOCALIZATION NOTE (netmonitor.context.copy): This is the label displayed
# for the copy sub-menu in the context menu for a request
netmonitor.context.copy=Copy
# LOCALIZATION NOTE (netmonitor.context.copy.accesskey): This is the access key
# for the copy sub-menu displayed in the context menu for a request
netmonitor.context.copy.accesskey=C
# LOCALIZATION NOTE (netmonitor.context.copyUrl): This is the label displayed
# on the context menu that copies the selected request's url
netmonitor.context.copyUrl=Copy URL

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

@ -50,7 +50,9 @@ RequestListContextMenu.prototype = {
let selectedRequest = this.selectedRequest;
let menu = new Menu();
menu.append(new MenuItem({
let copySubmenu = new Menu();
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-url",
label: L10N.getStr("netmonitor.context.copyUrl"),
accesskey: L10N.getStr("netmonitor.context.copyUrl.accesskey"),
@ -58,7 +60,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyUrl(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-url-params",
label: L10N.getStr("netmonitor.context.copyUrlParams"),
accesskey: L10N.getStr("netmonitor.context.copyUrlParams.accesskey"),
@ -66,7 +68,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyUrlParams(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-post-data",
label: L10N.getStr("netmonitor.context.copyPostData"),
accesskey: L10N.getStr("netmonitor.context.copyPostData.accesskey"),
@ -74,7 +76,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyPostData(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-as-curl",
label: L10N.getStr("netmonitor.context.copyAsCurl"),
accesskey: L10N.getStr("netmonitor.context.copyAsCurl.accesskey"),
@ -82,12 +84,12 @@ RequestListContextMenu.prototype = {
click: () => this.copyAsCurl(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
type: "separator",
visible: !!selectedRequest,
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-request-headers",
label: L10N.getStr("netmonitor.context.copyRequestHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyRequestHeaders.accesskey"),
@ -95,7 +97,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyRequestHeaders(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "response-list-context-copy-response-headers",
label: L10N.getStr("netmonitor.context.copyResponseHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyResponseHeaders.accesskey"),
@ -103,7 +105,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyResponseHeaders(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-response",
label: L10N.getStr("netmonitor.context.copyResponse"),
accesskey: L10N.getStr("netmonitor.context.copyResponse.accesskey"),
@ -114,7 +116,7 @@ RequestListContextMenu.prototype = {
click: () => this.copyResponse(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-image-as-data-uri",
label: L10N.getStr("netmonitor.context.copyImageAsDataUri"),
accesskey: L10N.getStr("netmonitor.context.copyImageAsDataUri.accesskey"),
@ -124,12 +126,12 @@ RequestListContextMenu.prototype = {
click: () => this.copyImageAsDataUri(),
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
type: "separator",
visible: !!selectedRequest,
}));
menu.append(new MenuItem({
copySubmenu.append(new MenuItem({
id: "request-list-context-copy-all-as-har",
label: L10N.getStr("netmonitor.context.copyAllAsHar"),
accesskey: L10N.getStr("netmonitor.context.copyAllAsHar.accesskey"),
@ -137,6 +139,13 @@ RequestListContextMenu.prototype = {
click: () => this.copyAllAsHar(),
}));
menu.append(new MenuItem({
label: L10N.getStr("netmonitor.context.copy"),
accesskey: L10N.getStr("netmonitor.context.copy.accesskey"),
visible: !!selectedRequest,
submenu: copySubmenu,
}));
menu.append(new MenuItem({
id: "request-list-context-save-all-as-har",
label: L10N.getStr("netmonitor.context.saveAllAsHar"),

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

@ -41,6 +41,7 @@ add_task(function* () {
data = yield createCurlData(requests.post, getLongString);
testIsUrlEncodedRequest(data);
testWritePostDataTextParams(data);
testWriteEmptyPostDataTextParams(data);
testDataArgumentOnGeneratedCommand(data);
data = yield createCurlData(requests.multipart, getLongString);
@ -103,6 +104,12 @@ function testWritePostDataTextParams(data) {
"Should return a serialized representation of the request parameters");
}
function testWriteEmptyPostDataTextParams(data) {
let params = CurlUtils.writePostDataTextParams(null);
is(params, "",
"Should return a empty string when no parameters provided");
}
function testDataArgumentOnGeneratedCommand(data) {
let curlCommand = Curl.generateCommand(data);
ok(curlCommand.includes("--data"),

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

@ -202,6 +202,9 @@ const CurlUtils = {
* Post data parameters.
*/
writePostDataTextParams: function (postDataText) {
if (!postDataText) {
return "";
}
let lines = postDataText.split("\r\n");
return lines[lines.length - 1];
},

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

@ -69,7 +69,7 @@ public:
// we are in the middle of updating style. If we need to use this when
// updating style, we should pass the nsStyleContext into this method and use
// that to update the properties rather than calling
// GetStyleContextForElement.
// GetStyleContext.
void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget);
void GetSpacing(nsString& aRetVal, CallerType aCallerType)

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

@ -22,7 +22,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/TypeTraits.h"
#include "Layers.h" // For Layer
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContextForElement
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContext
#include "nsContentUtils.h" // nsContentUtils::ReportToConsole
#include "nsCSSPropertyIDSet.h"
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
@ -1061,9 +1061,7 @@ KeyframeEffectReadOnly::GetTargetStyleContext()
? nsCSSPseudoElements::GetPseudoAtom(mTarget->mPseudoType)
: nullptr;
return nsComputedDOMStyle::GetStyleContextForElement(mTarget->mElement,
pseudo,
shell);
return nsComputedDOMStyle::GetStyleContext(mTarget->mElement, pseudo, shell);
}
#ifdef DEBUG

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

@ -342,9 +342,9 @@ protected:
// Looks up the style context associated with the target element, if any.
// We need to be careful to *not* call this when we are updating the style
// context. That's because calling GetStyleContextForElement when we are in
// the process of building a style context may trigger various forms of
// infinite recursion.
// context. That's because calling GetStyleContext when we are in the process
// of building a style context may trigger various forms of infinite
// recursion.
already_AddRefed<nsStyleContext> GetTargetStyleContext();
// A wrapper for marking cascade update according to the current

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

@ -93,6 +93,12 @@ public:
mTabGroup->ValidateAccess();
}
// Like ValidateAccess, but it returns a bool rather than asserting.
bool AccessAllowed() const
{
return mTabGroup->AccessAllowed();
}
// Return a pointer that can be continually checked to see if access to this
// DocGroup is valid. This pointer should live at least as long as the
// DocGroup.

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

@ -458,7 +458,7 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
// Get the computed -moz-binding directly from the style context
RefPtr<nsStyleContext> sc =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, shell);
nsComputedDOMStyle::GetStyleContextNoFlush(this, nullptr, shell);
NS_ENSURE_TRUE(sc, false);
NS_IF_ADDREF(*aResult = sc->StyleDisplay()->mBinding);

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

@ -310,6 +310,7 @@ StructuredCloneHolder::Read(nsISupports* aParent,
mBlobImplArray.Clear();
mWasmModuleArray.Clear();
mClonedSurfaces.Clear();
mInputStreamArray.Clear();
Clear();
}
}
@ -1042,6 +1043,45 @@ WriteWasmModule(JSStructuredCloneWriter* aWriter,
return false;
}
JSObject*
ReadInputStream(JSContext* aCx,
uint32_t aIndex,
StructuredCloneHolder* aHolder)
{
MOZ_ASSERT(aHolder);
MOZ_ASSERT(aIndex < aHolder->InputStreams().Length());
nsCOMPtr<nsIInputStream> inputStream = aHolder->InputStreams()[aIndex];
JS::RootedValue result(aCx);
nsresult rv = nsContentUtils::WrapNative(aCx, inputStream,
&NS_GET_IID(nsIInputStream),
&result);
if (NS_FAILED(rv)) {
return nullptr;
}
return &result.toObject();
}
bool
WriteInputStream(JSStructuredCloneWriter* aWriter,
nsIInputStream* aInputStream,
StructuredCloneHolder* aHolder)
{
MOZ_ASSERT(aWriter);
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aHolder);
// We store the position of the inputStream in the array as index.
if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_INPUTSTREAM,
aHolder->InputStreams().Length())) {
aHolder->InputStreams().AppendElement(aInputStream);
return true;
}
return false;
}
} // anonymous namespace
JSObject*
@ -1084,6 +1124,10 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
return ReadWasmModule(aCx, aIndex, this);
}
if (aTag == SCTAG_DOM_INPUTSTREAM) {
return ReadInputStream(aCx, aIndex, this);
}
return ReadFullySerializableObjects(aCx, aReader, aTag);
}
@ -1149,6 +1193,14 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
return WriteWasmModule(aWriter, module, this);
}
{
nsCOMPtr<nsISupports> base = xpc::UnwrapReflectorToISupports(aObj);
nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(base);
if (inputStream) {
return WriteInputStream(aWriter, inputStream, this);
}
}
return WriteFullySerializableObjects(aCx, aWriter, aObj);
}

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

@ -18,6 +18,8 @@
#include "nsIThread.h"
#endif
class nsIInputStream;
namespace mozilla {
class ErrorResult;
namespace layers {
@ -180,7 +182,8 @@ public:
{
return !mBlobImplArray.IsEmpty() ||
!mWasmModuleArray.IsEmpty() ||
!mClonedSurfaces.IsEmpty();
!mClonedSurfaces.IsEmpty() ||
!mInputStreamArray.IsEmpty();
}
nsTArray<RefPtr<BlobImpl>>& BlobImpls()
@ -195,6 +198,12 @@ public:
return mWasmModuleArray;
}
nsTArray<nsCOMPtr<nsIInputStream>>& InputStreams()
{
MOZ_ASSERT(mSupportsCloning, "InputStreams cannot be taken/set if cloning is not supported.");
return mInputStreamArray;
}
StructuredCloneScope CloneScope() const
{
return mStructuredCloneScope;
@ -303,6 +312,9 @@ protected:
// Used for cloning JS::WasmModules in the structured cloning algorithm.
nsTArray<RefPtr<JS::WasmModule>> mWasmModuleArray;
// Used for cloning InputStream in the structured cloning algorithm.
nsTArray<nsCOMPtr<nsIInputStream>> mInputStreamArray;
// This is used for sharing the backend of ImageBitmaps.
// The DataSourceSurface object must be thread-safely reference-counted.
// The DataSourceSurface object will not be written ever via any ImageBitmap

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

@ -60,6 +60,8 @@ enum StructuredCloneTags {
// This tag is used by both main thread and workers.
SCTAG_DOM_URLSEARCHPARAMS,
SCTAG_DOM_INPUTSTREAM,
// When adding a new tag for IDB, please don't add it to the end of the list!
// Tags that are supported by IDB must not ever change. See the static assert
// in IDBObjectStore.cpp, method CommonStructuredCloneReadCallback.

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

@ -10,6 +10,7 @@
#include "mozilla/dom/WebKitCSSMatrixBinding.h"
#include "mozilla/Preferences.h"
#include "nsCSSParser.h"
#include "nsPresContext.h"
#include "nsStyleTransformMatrix.h"
#include "RuleNodeCacheConditions.h"

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

@ -537,7 +537,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
while (ch != kNullCh && ch != kSemicolon && ch != kComma) {
++end;
ch = *end;
ch = *(end + 1);
}
}
}

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

@ -2444,7 +2444,7 @@ ComputeAnimationValue(nsCSSPropertyID aProperty,
}
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr, shell);
nsComputedDOMStyle::GetStyleContext(aElement, nullptr, shell);
if (!StyleAnimationValue::ComputeValue(aProperty, aElement, styleContext,
aInput, false, aOutput)) {
@ -2734,7 +2734,7 @@ nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
nsIPresShell* shell = element->GetUncomposedDoc()->GetShell();
RefPtr<nsStyleContext> styleContext = shell
? nsComputedDOMStyle::GetStyleContextForElement(element, nullptr, shell)
? nsComputedDOMStyle::GetStyleContext(element, nullptr, shell)
: nullptr;
if (!StyleAnimationValue::ComputeDistance(property, v1, v2, styleContext,
*aResult)) {

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

@ -1717,6 +1717,7 @@ nsMessageManagerScriptExecutor::InitChildGlobalInternal(
// Set the location information for the new global, so that tools like
// about:memory may use that information.
xpc::SetLocationForGlobal(global, aID);
xpc::SetDocGroupValidation(global);
DidCreateGlobal();
return true;

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

@ -1816,8 +1816,7 @@ bool
nsPlainTextSerializer::IsElementPreformatted(Element* aElement)
{
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
if (styleContext) {
const nsStyleText* textStyle = styleContext->StyleText();
return textStyle->WhiteSpaceOrNewlineIsSignificant();
@ -1830,8 +1829,7 @@ bool
nsPlainTextSerializer::IsElementBlock(Element* aElement)
{
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
if (styleContext) {
const nsStyleDisplay* displayStyle = styleContext->StyleDisplay();
return displayStyle->IsBlockOutsideStyle();

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

@ -3467,8 +3467,7 @@ ElementIsVisibleNoFlush(Element* aElement)
return false;
}
RefPtr<nsStyleContext> sc =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
return sc && sc->StyleVisibility()->IsVisible();
}

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

@ -817,8 +817,8 @@ nsXHTMLContentSerializer::IsElementPreformatted(nsIContent* aNode)
return false;
}
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aNode->AsElement(),
nullptr, nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aNode->AsElement(),
nullptr, nullptr);
if (styleContext) {
const nsStyleText* textStyle = styleContext->StyleText();
return textStyle->WhiteSpaceOrNewlineIsSignificant();

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

@ -9,6 +9,7 @@ support-files =
file_bug1303838.html
file_bug1303838_target.html
file_bug1303838_with_iframe.html
file_docgroup_forbid.html
file_messagemanager_unload.html
file_pluginAudio.html
file_use_counter_outer.html
@ -26,6 +27,8 @@ support-files =
tags = mcb
[browser_bug1011748.js]
[browser_bug1058164.js]
[browser_docgroup_forbid.js]
skip-if = !e10s
[browser_messagemanager_loadprocessscript.js]
[browser_messagemanager_targetframeloader.js]
[browser_messagemanager_unload.js]
@ -37,3 +40,4 @@ skip-if = true # Bug 1271028
[browser_bug1307747.js]
[browser_timeout_throttling_with_audio_playback.js]
[browser_bug1303838.js]
[browser_inputStream_structuredClone.js]

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

@ -0,0 +1,74 @@
const url = "https://example.com/browser/dom/base/test/file_docgroup_forbid.html";
function frameScript() {
let e = Services.ww.getWindowEnumerator();
let exception = false;
while (e.hasMoreElements()) {
try {
/*
* If this is a window we're not supposed to touch, we'll get an
* error very early here (during the QI).
*/
var window = e.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
var doc = window.document;
} catch (e) {
if (/accessing object in wrong DocGroup/.test(e.toString())) {
exception = true;
break;
}
throw e;
}
/*
* Do some stuff that will trigger the DocGroup assertions if we
* didn't throw.
*/
let elt = doc.createElement("div");
elt.innerHTML = "hello!";
doc.body.appendChild(elt);
let evt = new window.CustomEvent("foopy");
doc.dispatchEvent(evt);
}
sendAsyncMessage("DocGroupTest:Done", exception);
}
function promiseMessage(messageManager, message) {
return new Promise(resolve => {
let listener = (msg) => {
messageManager.removeMessageListener(message, listener);
resolve(msg);
};
messageManager.addMessageListener(message, listener);
})
}
add_task(function*() {
// This pref is normally disabled during tests, but we want to test
// it here, so we enable it.
yield new Promise(go => {
SpecialPowers.pushPrefEnv({set: [["extensions.throw_on_docgroup_mismatch.enabled", true]]}, go)
});
let url1 = url + "?tab=1";
let url2 = url + "?tab=2";
let browser1 = gBrowser.selectedBrowser;
let tab2 = gBrowser.addTab(url2, {sameProcessAsFrameLoader: browser1.frameLoader});
let browser2 = tab2.linkedBrowser;
yield BrowserTestUtils.browserLoaded(browser2, false, url2);
browser1.loadURI(url1);
yield BrowserTestUtils.browserLoaded(browser1, false, url1);
browser1.messageManager.loadFrameScript(`data:,(${frameScript})();`, false);
let exception = yield promiseMessage(browser1.messageManager, "DocGroupTest:Done");
ok(exception, "Touching two windows threw an exception (that's good!)");
gBrowser.removeTab(tab2);
});

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

@ -0,0 +1,56 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const { classes: Cc, interfaces: Ci } = Components;
const URIs = [
"about:about",
"http://example.com/browser/dom/base/test/empty.html"
];
function* runTest(input, url) {
let tab = gBrowser.addTab(url);
let browser = gBrowser.getBrowserForTab(tab);
yield BrowserTestUtils.browserLoaded(browser);
let stream = Cc['@mozilla.org/io/string-input-stream;1']
.createInstance(Ci.nsIStringInputStream);
stream.setData(input, input.length);
let data = {
inputStream: stream
};
is(data.inputStream.available(), input.length, "The length of the inputStream matches: " + input.length);
let dataBack = yield ContentTask.spawn(browser, data, function(data) {
let dataBack = {
inputStream: data.inputStream,
check: true,
};
if (content.location.href.startsWith('about:')) {
dataBack.check = data.inputStream instanceof content.Components.interfaces.nsIInputStream;
}
return dataBack;
});
ok(dataBack.check, "The inputStream is a nsIInputStream also on content.");
ok(data.inputStream instanceof Ci.nsIInputStream, "The original object was an inputStream");
ok(dataBack.inputStream instanceof Ci.nsIInputStream, "We have an inputStream back from the content.");
yield BrowserTestUtils.removeTab(tab);
}
add_task(function* test() {
let a = "a";
for (let i = 0; i < 25; ++i) {
a+=a;
}
for (let i = 0; i < URIs.length; ++i) {
yield runTest("Hello world", URIs[i]);
yield runTest(a, URIs[i]);
}
});

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

@ -0,0 +1,7 @@
<html>
<body>
<script>
document.addEventListener("foopy", function() { dump("ran event handler\n"); });
</script>
</body>
</html>

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

@ -653,7 +653,7 @@ skip-if = (toolkit == 'android') # Android: Bug 775227
[test_innersize_scrollport.html]
[test_integer_attr_with_leading_zero.html]
[test_intersectionobservers.html]
skip-if = true # Track Bug 1320704
skip-if = (os == "android") # Timing issues
[test_link_prefetch.html]
skip-if = !e10s # Track Bug 1281415
[test_link_stylesheet.html]

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

@ -1555,10 +1555,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def hasMembersInSlots(self):
return self._ownMembersInSlots != 0
conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
"SecureContext",
"CheckAnyPermissions",
"CheckAllPermissions" ]
conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func",
"SecureContext" ]
def isExposedConditionally(self, exclusions=[]):
return any(((not a in exclusions) and self.getExtendedAttribute(a)) for a in self.conditionExtendedAttributes)

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

@ -4,6 +4,9 @@
include protocol PBackground;
include protocol PBlob;
include protocol PChildToParentStream;
include protocol PFileDescriptorSet;
include protocol PParentToChildStream;
include DOMTypes;
using struct mozilla::SerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h";

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

@ -1146,8 +1146,9 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
RefPtr<nsStyleContext> parentContext;
if (mCanvasElement && mCanvasElement->IsInUncomposedDoc()) {
// Inherit from the canvas element.
parentContext = nsComputedDOMStyle::GetStyleContextForElement(
mCanvasElement, nullptr, presShell);
parentContext = nsComputedDOMStyle::GetStyleContext(mCanvasElement,
nullptr,
presShell);
}
Unused << nsRuleNode::ComputeColor(
@ -1939,9 +1940,7 @@ CanvasRenderingContext2D::ClearTarget()
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (presShell) {
canvasStyle =
nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
nullptr,
presShell);
nsComputedDOMStyle::GetStyleContext(mCanvasElement, nullptr, presShell);
if (canvasStyle) {
WritingMode wm(canvasStyle);
if (wm.IsVertical() && !wm.IsSideways()) {
@ -2649,8 +2648,7 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* aPresShell,
if (aElement && aElement->IsInUncomposedDoc()) {
// Inherit from the canvas element.
RefPtr<nsStyleContext> result =
nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr,
aPresShell);
nsComputedDOMStyle::GetStyleContext(aElement, nullptr, aPresShell);
if (!result) {
aError.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -4202,9 +4200,7 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
if (mCanvasElement && mCanvasElement->IsInUncomposedDoc()) {
// try to find the closest context
canvasStyle =
nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
nullptr,
presShell);
nsComputedDOMStyle::GetStyleContext(mCanvasElement, nullptr, presShell);
if (!canvasStyle) {
return NS_ERROR_FAILURE;
}

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

@ -2950,8 +2950,8 @@ IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell)
if (sc) {
sc = styleSet->ResolveStyleFor(elementsToCheck[i], sc, LazyComputeBehavior::Assert);
} else {
sc = nsComputedDOMStyle::GetStyleContextForElementNoFlush(elementsToCheck[i],
nullptr, aPresShell);
sc = nsComputedDOMStyle::GetStyleContextNoFlush(elementsToCheck[i],
nullptr, aPresShell);
}
if (sc->StyleDisplay()->mDisplay == StyleDisplay::None) {
return true;

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

@ -172,6 +172,9 @@
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#ifdef XP_WIN
#include "mozilla/a11y/AccessibleWrap.h"
#endif
#endif
#include "mozilla/dom/File.h"

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

@ -4925,6 +4925,20 @@ ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
#endif
}
mozilla::ipc::IPCResult
ContentParent::RecvA11yHandlerControl(const uint32_t& aPid,
const IHandlerControlHolder& aHandlerControl)
{
#if defined(XP_WIN32) && defined(ACCESSIBILITY)
MOZ_ASSERT(!aHandlerControl.IsNull());
RefPtr<IHandlerControl> proxy(aHandlerControl.Get());
a11y::AccessibleWrap::SetHandlerControl(aPid, Move(proxy));
return IPC_OK();
#else
return IPC_FAIL_NO_REASON(this);
#endif
}
} // namespace dom
} // namespace mozilla

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

@ -599,6 +599,10 @@ public:
virtual mozilla::ipc::IPCResult
RecvGetA11yContentId(uint32_t* aContentId) override;
virtual mozilla::ipc::IPCResult
RecvA11yHandlerControl(const uint32_t& aPid,
const IHandlerControlHolder& aHandlerControl) override;
virtual int32_t Pid() const override;
virtual PURLClassifierParent*

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

@ -6,6 +6,8 @@
include protocol PBlob;
include protocol PMemoryStream;
include IPCStream;
include ProtocolTypes;
using struct mozilla::void_t
@ -40,6 +42,7 @@ struct ClonedMessageData
{
SerializedStructuredCloneBuffer data;
PBlob[] blobs;
IPCStream[] inputStreams;
MessagePortIdentifier[] identfiers;
};

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

@ -16,6 +16,9 @@ include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
include protocol PPluginWidget;
include protocol PRemotePrintJob;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol PFileDescriptorSet;
include DOMTypes;
include JavaScriptTypes;
include URIParams;

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

@ -73,6 +73,7 @@ using base::ProcessId from "base/process.h";
using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h";
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using mozilla::a11y::IHandlerControlHolder from "mozilla/a11y/IPCTypes.h";
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
@ -1083,6 +1084,8 @@ parent:
async RecordChildEvents(ChildEventData[] events);
sync GetA11yContentId() returns (uint32_t aContentId);
async A11yHandlerControl(uint32_t aPid,
IHandlerControlHolder aHandlerControl);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);

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

@ -14,7 +14,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "nsContentUtils.h"
#include "nsJSEnvironment.h"
#include "MainThreadUtils.h"
@ -25,6 +25,37 @@ namespace mozilla {
namespace dom {
namespace ipc {
StructuredCloneData::StructuredCloneData()
: StructuredCloneData(StructuredCloneHolder::TransferringSupported)
{}
StructuredCloneData::StructuredCloneData(StructuredCloneData&& aOther)
: StructuredCloneData(StructuredCloneHolder::TransferringSupported)
{
*this = Move(aOther);
}
StructuredCloneData::StructuredCloneData(TransferringSupport aSupportsTransferring)
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
aSupportsTransferring,
StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
, mInitialized(false)
{}
StructuredCloneData::~StructuredCloneData()
{}
StructuredCloneData&
StructuredCloneData::operator=(StructuredCloneData&& aOther)
{
mExternalData = Move(aOther.mExternalData);
mSharedData = Move(aOther.mSharedData);
mIPCStreams = Move(aOther.mIPCStreams);
mInitialized = aOther.mInitialized;
return *this;
}
bool
StructuredCloneData::Copy(const StructuredCloneData& aData)
{
@ -50,6 +81,9 @@ StructuredCloneData::Copy(const StructuredCloneData& aData)
MOZ_ASSERT(GetSurfaces().IsEmpty());
MOZ_ASSERT(WasmModules().IsEmpty());
MOZ_ASSERT(InputStreams().IsEmpty());
InputStreams().AppendElements(aData.InputStreams());
mInitialized = true;
return true;
@ -224,6 +258,26 @@ BuildClonedMessageData(typename ParentManagerTraits<Flavor, ManagerFlavor>::Conc
blobList.AppendElement(protocolActor);
}
}
const nsTArray<nsCOMPtr<nsIInputStream>>& inputStreams = aData.InputStreams();
if (!inputStreams.IsEmpty()) {
InfallibleTArray<IPCStream>& streams = aClonedData.inputStreams();
uint32_t length = inputStreams.Length();
streams.SetCapacity(length);
for (uint32_t i = 0; i < length; ++i) {
AutoIPCStream* stream = aData.IPCStreams().AppendElement(fallible);
if (NS_WARN_IF(!stream)) {
return false;
}
if (!stream->Serialize(inputStreams[i], aManager)) {
return false;
}
streams.AppendElement(stream->TakeValue());
}
}
return true;
}
@ -343,6 +397,16 @@ UnpackClonedMessageData(typename MemoryTraits<MemoryFlavor>::ClonedMessageType&
aData.BlobImpls().AppendElement(blobImpl);
}
}
const InfallibleTArray<IPCStream>& streams = aClonedData.inputStreams();
if (!streams.IsEmpty()) {
uint32_t length = streams.Length();
aData.InputStreams().SetCapacity(length);
for (uint32_t i = 0; i < length; ++i) {
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(streams[i]);
aData.InputStreams().AppendElement(stream);
}
}
}
void

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

@ -11,6 +11,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "nsISupportsImpl.h"
#include "nsIInputStream.h"
namespace IPC {
class Message;
@ -20,6 +21,7 @@ class PickleIterator;
namespace mozilla {
namespace ipc {
class AutoIPCStream;
class PBackgroundChild;
class PBackgroundParent;
@ -150,22 +152,19 @@ private:
class StructuredCloneData : public StructuredCloneHolder
{
public:
StructuredCloneData()
: StructuredCloneData(StructuredCloneHolder::TransferringSupported)
{}
StructuredCloneData();
StructuredCloneData(const StructuredCloneData&) = delete;
StructuredCloneData(StructuredCloneData&& aOther) = default;
StructuredCloneData(StructuredCloneData&& aOther);
~StructuredCloneData()
{}
~StructuredCloneData();
StructuredCloneData&
operator=(const StructuredCloneData& aOther) = delete;
StructuredCloneData&
operator=(StructuredCloneData&& aOther) = default;
operator=(StructuredCloneData&& aOther);
const nsTArray<RefPtr<BlobImpl>>& BlobImpls() const
{
@ -177,6 +176,16 @@ public:
return mBlobImplArray;
}
const nsTArray<nsCOMPtr<nsIInputStream>>& InputStreams() const
{
return mInputStreamArray;
}
nsTArray<nsCOMPtr<nsIInputStream>>& InputStreams()
{
return mInputStreamArray;
}
bool Copy(const StructuredCloneData& aData);
void Read(JSContext* aCx,
@ -276,29 +285,33 @@ public:
return mSupportsTransferring;
}
FallibleTArray<mozilla::ipc::AutoIPCStream>& IPCStreams()
{
return mIPCStreams;
}
// For IPC serialization
void WriteIPCParams(IPC::Message* aMessage) const;
bool ReadIPCParams(const IPC::Message* aMessage, PickleIterator* aIter);
protected:
explicit StructuredCloneData(TransferringSupport aSupportsTransferring)
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
aSupportsTransferring,
StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
, mInitialized(false)
{}
explicit StructuredCloneData(TransferringSupport aSupportsTransferring);
private:
JSStructuredCloneData mExternalData;
RefPtr<SharedJSAllocatedData> mSharedData;
// This array is needed because AutoIPCStream DTOR must be executed after the
// sending of the data via IPC. This will be fixed by bug 1353475.
FallibleTArray<mozilla::ipc::AutoIPCStream> mIPCStreams;
bool mInitialized;
};
/**
* For use when transferring should not be supported.
*/
class StructuredCloneDataNoTransfers : public StructuredCloneData {
class StructuredCloneDataNoTransfers : public StructuredCloneData
{
public:
StructuredCloneDataNoTransfers()
: StructuredCloneData(StructuredCloneHolder::TransferringNotSupported)

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

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html class="reftest-wait">
<script>
const blockSize = 128;
// The sample rate is a prime number so that the resampler is not expected to
// simplify in/out fractions.
const rate = 44101;
var context = new window.OfflineAudioContext(1, 3 * blockSize, rate);
// Non-zero buffer, so it can't be optimized away.
var buffer = context.createBuffer(1, 128, rate);
buffer.getChannelData(0)[0] = 1.0;
var source = context.createBufferSource();
source.buffer = buffer;
source.loop = true;
// Initialize the resampler with a slow input rate.
// With the current (Mar 2017) implementation, very slow rates give the
// resampler a very large denominator.
source.playbackRate.setValueAtTime(rate / 0x7fffffff, 0.0);
// Change to a moderate input rate.
// With the current implementation, skip_frac_num increases by den_rate for
// each output sample and so one block before the change in playback rate is
// enough for high skip_frac_num at the time of the change.
const changeBlock = 1;
const changeBlockSeconds = changeBlock * blockSize / rate;
// With the current speex_resampler_set_rate_frac() implementation, the
// moderate resampler denominator is still large enough to trigger overflow of
// 32-bit unsigned integer arithmetic.
source.playbackRate.setValueAtTime(rate / (rate + 1), changeBlockSeconds);
source.start(0);
context.startRendering().
then(function() {
document.documentElement.removeAttribute("class");
});
</script>

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

@ -92,6 +92,7 @@ load audiocontext-double-suspend.html
load buffer-source-duration-1.html
load buffer-source-ended-1.html
load buffer-source-resampling-start-1.html
load buffer-source-slow-resampling-1.html
load doppler-1.html
HTTP load media-element-source-seek-1.html
load offline-buffer-source-ended-1.html

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

@ -190,13 +190,15 @@ namespace WebAudioUtils {
MOZ_CRASH("We should never see a NaN here");
}
if (f > FloatType(numeric_limits<IntType>::max())) {
// If the floating point value is outside of the range of maximum
// integral value for this type, just clamp to the maximum value.
// If the floating point value is outside of the range of maximum
// integral value for this type, just clamp to the maximum value.
// The equality case must also return max() due to loss of precision when
// converting max() to float.
if (f >= FloatType(numeric_limits<IntType>::max())) {
return numeric_limits<IntType>::max();
}
if (f < FloatType(numeric_limits<IntType>::min())) {
if (f <= FloatType(numeric_limits<IntType>::min())) {
// If the floating point value is outside of the range of minimum
// integral value for this type, just clamp to the minimum value.
return numeric_limits<IntType>::min();

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

@ -3,6 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PChildToParentStream;
include protocol PFileDescriptorSet;
include protocol PParentToChildStream;
include protocol PBlob;
include DOMTypes;

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

@ -203,7 +203,8 @@ public:
NotificationGetRunnable(const nsAString& aOrigin,
const nsAString& aTag,
nsINotificationStorageCallback* aCallback)
: mOrigin(aOrigin), mTag(aTag), mCallback(aCallback)
: Runnable("NotificationGetRunnable")
, mOrigin(aOrigin), mTag(aTag), mCallback(aCallback)
{}
NS_IMETHOD
@ -310,7 +311,8 @@ class FocusWindowRunnable final : public Runnable
nsMainThreadPtrHandle<nsPIDOMWindowInner> mWindow;
public:
explicit FocusWindowRunnable(const nsMainThreadPtrHandle<nsPIDOMWindowInner>& aWindow)
: mWindow(aWindow)
: Runnable("FocusWindowRunnable")
, mWindow(aWindow)
{ }
NS_IMETHOD
@ -502,8 +504,10 @@ public:
eClose
};
NotificationTask(UniquePtr<NotificationRef> aRef, NotificationAction aAction)
: mNotificationRef(Move(aRef)), mAction(aAction)
NotificationTask(const char* aName, UniquePtr<NotificationRef> aRef,
NotificationAction aAction)
: Runnable(aName)
, mNotificationRef(Move(aRef)), mAction(aAction)
{}
NS_IMETHOD
@ -619,8 +623,13 @@ NotificationPermissionRequest::GetRequester(nsIContentPermissionRequester** aReq
inline nsresult
NotificationPermissionRequest::DispatchResolvePromise()
{
return NS_DispatchToMainThread(NewRunnableMethod(this,
&NotificationPermissionRequest::ResolvePromise));
nsCOMPtr<nsIRunnable> resolver =
NewRunnableMethod("NotificationPermissionRequest::DispatchResolvePromise",
this, &NotificationPermissionRequest::ResolvePromise);
if (nsIEventTarget* target = mWindow->EventTargetFor(TaskCategory::Other)) {
return target->Dispatch(resolver.forget(), nsIEventTarget::DISPATCH_NORMAL);
}
return NS_ERROR_FAILURE;
}
nsresult
@ -1399,7 +1408,7 @@ public:
MOZ_ASSERT_IF(mWorkerPrivate->IsServiceWorker(), !doDefaultAction);
if (doDefaultAction) {
RefPtr<FocusWindowRunnable> r = new FocusWindowRunnable(mWindow);
NS_DispatchToMainThread(r);
mWorkerPrivate->DispatchToMainThread(r.forget());
}
}
};
@ -1831,11 +1840,14 @@ Notification::RequestPermissionEnabledForScope(JSContext* aCx, JSObject* /* unus
return NS_IsMainThread();
}
// static
already_AddRefed<Promise>
Notification::RequestPermission(const GlobalObject& aGlobal,
const Optional<OwningNonNull<NotificationPermissionCallback> >& aCallback,
ErrorResult& aRv)
{
AssertIsOnMainThread();
// Get principal from global to make permission request for notifications.
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aGlobal.GetAsSupports());
@ -1857,7 +1869,9 @@ Notification::RequestPermission(const GlobalObject& aGlobal,
nsCOMPtr<nsIRunnable> request =
new NotificationPermissionRequest(principal, window, promise, permissionCallback);
NS_DispatchToMainThread(request);
global->Dispatch("Notification::RequestPermission", TaskCategory::Other,
request.forget());
return promise.forget();
}
@ -2026,6 +2040,7 @@ Notification::Get(nsPIDOMWindowInner* aWindow,
const nsAString& aScope,
ErrorResult& aRv)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
@ -2052,7 +2067,8 @@ Notification::Get(nsPIDOMWindowInner* aWindow,
RefPtr<NotificationGetRunnable> r =
new NotificationGetRunnable(origin, aFilter.mTag, callback);
aRv = NS_DispatchToMainThread(r);
aRv = global->Dispatch("Notification::Get", TaskCategory::Other,
r.forget());
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
@ -2172,7 +2188,8 @@ public:
WorkerGetRunnable(PromiseWorkerProxy* aProxy,
const nsAString& aTag,
const nsAString& aScope)
: mPromiseProxy(aProxy), mTag(aTag), mScope(aScope)
: Runnable("WorkerGetRunnable")
, mPromiseProxy(aProxy), mTag(aTag), mScope(aScope)
{
MOZ_ASSERT(mPromiseProxy);
}
@ -2219,6 +2236,7 @@ private:
{}
};
// static
already_AddRefed<Promise>
Notification::WorkerGet(WorkerPrivate* aWorkerPrivate,
const GetNotificationOptions& aFilter,
@ -2243,7 +2261,7 @@ Notification::WorkerGet(WorkerPrivate* aWorkerPrivate,
new WorkerGetRunnable(proxy, aFilter.mTag, aScope);
// Since this is called from script via
// ServiceWorkerRegistration::GetNotifications, we can assert dispatch.
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
MOZ_ALWAYS_SUCCEEDS(aWorkerPrivate->DispatchToMainThread(r.forget()));
return p.forget();
}
@ -2263,8 +2281,9 @@ Notification::Close()
}
nsCOMPtr<nsIRunnable> closeNotificationTask =
new NotificationTask(Move(ref), NotificationTask::eClose);
nsresult rv = NS_DispatchToMainThread(closeNotificationTask);
new NotificationTask("Notification::Close", Move(ref),
NotificationTask::eClose);
nsresult rv = DispatchToMainThread(closeNotificationTask.forget());
if (NS_FAILED(rv)) {
DispatchTrustedEvent(NS_LITERAL_STRING("error"));
@ -2703,8 +2722,12 @@ Notification::CreateAndShow(JSContext* aCx,
// Queue a task to show the notification.
nsCOMPtr<nsIRunnable> showNotificationTask =
new NotificationTask(Move(ref), NotificationTask::eShow);
nsresult rv = NS_DispatchToMainThread(showNotificationTask);
new NotificationTask("Notification::CreateAndShow", Move(ref),
NotificationTask::eShow);
nsresult rv =
notification->DispatchToMainThread(showNotificationTask.forget());
if (NS_WARN_IF(NS_FAILED(rv))) {
notification->DispatchTrustedEvent(NS_LITERAL_STRING("error"));
}
@ -2763,5 +2786,22 @@ Notification::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
nsresult
Notification::DispatchToMainThread(already_AddRefed<nsIRunnable>&& aRunnable)
{
if (mWorkerPrivate) {
return mWorkerPrivate->DispatchToMainThread(Move(aRunnable));
}
AssertIsOnMainThread();
if (nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal()) {
if (nsIEventTarget* target = global->EventTargetFor(TaskCategory::Other)) {
return target->Dispatch(Move(aRunnable), nsIEventTarget::DISPATCH_NORMAL);
}
}
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
MOZ_ASSERT(mainThread);
return mainThread->Dispatch(Move(aRunnable), nsIEventTarget::DISPATCH_NORMAL);
}
} // namespace dom
} // namespace mozilla

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

@ -327,6 +327,8 @@ public:
static nsresult RemovePermission(nsIPrincipal* aPrincipal);
static nsresult OpenSettings(nsIPrincipal* aPrincipal);
nsresult DispatchToMainThread(already_AddRefed<nsIRunnable>&& aRunnable);
protected:
Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
const nsAString& aTitle, const nsAString& aBody,

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

@ -10,51 +10,22 @@
#include "mozilla/dom/Element.h"
#include "mozilla/Move.h"
#include "mozilla/StyleAnimationValue.h"
#include "nsICSSDeclaration.h"
#include "nsSMILCSSValueType.h"
#include "nsSMILValue.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
using namespace mozilla;
using namespace mozilla::dom;
// Helper function
static bool
GetCSSComputedValue(Element* aElem,
nsCSSPropertyID aPropID,
nsAString& aResult)
{
MOZ_ASSERT(!nsCSSProps::IsShorthand(aPropID),
"Can't look up computed value of shorthand property");
MOZ_ASSERT(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
"Shouldn't get here for non-animatable properties");
nsIDocument* doc = aElem->GetUncomposedDoc();
if (!doc) {
// This can happen if we process certain types of restyles mid-sample
// and remove anonymous animated content from the document as a result.
// See bug 534975.
return false;
}
nsIPresShell* shell = doc->GetShell();
if (!shell) {
NS_WARNING("Unable to look up computed style -- no pres shell");
return false;
}
RefPtr<nsComputedDOMStyle> computedStyle =
NS_NewComputedDOMStyle(aElem, EmptyString(), shell);
computedStyle->GetPropertyValue(aPropID, aResult);
return true;
}
// Class Methods
nsSMILCSSProperty::nsSMILCSSProperty(nsCSSPropertyID aPropID,
Element* aElement)
: mPropID(aPropID), mElement(aElement)
Element* aElement,
nsStyleContext* aBaseStyleContext)
: mPropID(aPropID)
, mElement(aElement)
, mBaseStyleContext(aBaseStyleContext)
{
MOZ_ASSERT(IsPropertyAnimatable(mPropID),
"Creating a nsSMILCSSProperty for a property "
@ -71,7 +42,10 @@ nsSMILCSSProperty::GetBaseValue() const
// SPECIAL CASE: (a) Shorthands
// (b) 'display'
if (nsCSSProps::IsShorthand(mPropID) || mPropID == eCSSProperty_display) {
// (c) No base style context
if (nsCSSProps::IsShorthand(mPropID) ||
mPropID == eCSSProperty_display ||
!mBaseStyleContext) {
// We can't look up the base (computed-style) value of shorthand
// properties because they aren't guaranteed to have a consistent computed
// value.
@ -80,47 +54,26 @@ nsSMILCSSProperty::GetBaseValue() const
// doing so involves clearing and resetting the property which can cause
// frames to be recreated which we'd like to avoid.
//
// In either case, just return a dummy value (initialized with the right
// Furthermore, if we don't (yet) have a base style context we obviously
// can't resolve a base value.
//
// In any case, just return a dummy value (initialized with the right
// type, so as not to indicate failure).
nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
Swap(baseValue, tmpVal);
return baseValue;
}
// GENERAL CASE: Non-Shorthands
// (1) Put empty string in override style for property mPropID
// (saving old override style value, so we can set it again when we're done)
nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
nsAutoString cachedOverrideStyleVal;
if (overrideDecl) {
overrideDecl->GetPropertyValue(mPropID, cachedOverrideStyleVal);
// (Don't bother clearing override style if it's already empty)
if (!cachedOverrideStyleVal.IsEmpty()) {
overrideDecl->SetPropertyValue(mPropID, EmptyString());
}
StyleAnimationValue computedValue;
if (!StyleAnimationValue::ExtractComputedValue(mPropID,
mBaseStyleContext,
computedValue)) {
return baseValue;
}
// (2) Get Computed Style
nsAutoString computedStyleVal;
bool didGetComputedVal = GetCSSComputedValue(mElement, mPropID,
computedStyleVal);
// (3) Put cached override style back (if it's non-empty)
if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) {
overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
}
// (4) Populate our nsSMILValue from the computed style
if (didGetComputedVal) {
// When we parse animation values we check if they are context-sensitive or
// not so that we don't cache animation values whose meaning may change.
// For base values however this is unnecessary since on each sample the
// compositor will fetch the (computed) base value and compare it against
// the cached (computed) value and detect changes for us.
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
computedStyleVal, baseValue,
nullptr);
}
baseValue =
nsSMILCSSValueType::ValueFromAnimationValue(mPropID, mElement,
computedValue);
return baseValue;
}

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

@ -15,6 +15,8 @@
#include "nsCSSPropertyID.h"
#include "nsCSSValue.h"
class nsStyleContext;
namespace mozilla {
namespace dom {
class Element;
@ -33,8 +35,14 @@ public:
* Constructs a new nsSMILCSSProperty.
* @param aPropID The CSS property we're interested in animating.
* @param aElement The element whose CSS property is being animated.
* @param aBaseStyleContext The style context to use when getting the base
* value. If this is nullptr and GetBaseValue is
* called, an empty nsSMILValue initialized with
* the nsSMILCSSValueType will be returned.
*/
nsSMILCSSProperty(nsCSSPropertyID aPropID, mozilla::dom::Element* aElement);
nsSMILCSSProperty(nsCSSPropertyID aPropID,
mozilla::dom::Element* aElement,
nsStyleContext* aBaseStyleContext);
// nsISMILAttr methods
virtual nsresult ValueFromString(const nsAString& aStr,
@ -62,6 +70,12 @@ protected:
// as the Compositing step, and DOM elements don't get a chance to die during
// that time.
mozilla::dom::Element* mElement;
// The style context to use when fetching base styles.
// As with mElement, since an nsISMILAttr only lives as long as the
// compositing step and since ComposeAttribute holds an owning reference to
// the base style context, we can use a non-owning reference here.
nsStyleContext* mBaseStyleContext;
};
#endif // NS_SMILCSSPROPERTY_H_

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

@ -7,6 +7,8 @@
/* representation of a value for a SMIL-animated CSS property */
#include "nsSMILCSSValueType.h"
#include "nsComputedDOMStyle.h"
#include "nsString.h"
#include "nsSMILParserUtils.h"
#include "nsSMILValue.h"
@ -361,8 +363,8 @@ ValueFromStringHelper(nsCSSPropertyID aPropID,
}
}
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElement(aTargetElement, nullptr,
aPresContext->PresShell());
nsComputedDOMStyle::GetStyleContext(aTargetElement, nullptr,
aPresContext->PresShell());
if (!styleContext) {
return false;
}
@ -417,6 +419,34 @@ nsSMILCSSValueType::ValueFromString(nsCSSPropertyID aPropID,
}
}
// static
nsSMILValue
nsSMILCSSValueType::ValueFromAnimationValue(nsCSSPropertyID aPropID,
Element* aTargetElement,
const StyleAnimationValue& aValue)
{
nsSMILValue result;
nsIDocument* doc = aTargetElement->GetUncomposedDoc();
// We'd like to avoid serializing |aValue| if possible, and since the
// string passed to CSPAllowsInlineStyle is only used for reporting violations
// and an intermediate CSS value is not likely to be particularly useful
// in that case, we just use a generic placeholder string instead.
static const nsLiteralString kPlaceholderText =
NS_LITERAL_STRING("[SVG animation of CSS]");
if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
doc->NodePrincipal(),
doc->GetDocumentURI(),
0, kPlaceholderText, nullptr)) {
return result;
}
sSingleton.Init(result);
result.mU.mPtr = new ValueWrapper(aPropID, aValue);
return result;
}
// static
bool
nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,

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

@ -16,6 +16,7 @@
class nsAString;
namespace mozilla {
class StyleAnimationValue;
namespace dom {
class Element;
} // namespace dom
@ -28,6 +29,7 @@ class nsSMILCSSValueType : public nsISMILType
{
public:
typedef mozilla::dom::Element Element;
typedef mozilla::StyleAnimationValue StyleAnimationValue;
// Singleton for nsSMILValue objects to hold onto.
static nsSMILCSSValueType sSingleton;
@ -84,6 +86,21 @@ public:
nsSMILValue& aValue,
bool* aIsContextSensitive);
/**
* Creates an nsSMILValue to wrap the given animation value.
*
* @param aPropID The property that |aValue| corresponds to.
* @param aTargetElement The target element to which the animation value
* applies.
* @param aValue The animation value to use.
* @return A new nsSMILValue. On failure, returns an
* nsSMILValue with the null type (i.e. rv.IsNull()
* returns true).
*/
static nsSMILValue ValueFromAnimationValue(nsCSSPropertyID aPropID,
Element* aTargetElement,
const StyleAnimationValue& aValue);
/**
* Creates a string representation of the given nsSMILValue.
*

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

@ -6,6 +6,7 @@
#include "nsSMILCompositor.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsHashKeys.h"
#include "nsSMILCSSProperty.h"
@ -54,9 +55,18 @@ nsSMILCompositor::ComposeAttribute(bool& aMightHavePendingStyleUpdates)
if (!mKey.mElement)
return;
// If we might need to resolve base styles, grab a suitable style context
// for initializing our nsISMILAttr with.
RefPtr<nsStyleContext> baseStyleContext;
if (MightNeedBaseStyle()) {
baseStyleContext =
nsComputedDOMStyle::GetUnanimatedStyleContextNoFlush(mKey.mElement,
nullptr, nullptr);
}
// FIRST: Get the nsISMILAttr (to grab base value from, and to eventually
// give animated value to)
UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr();
UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr(baseStyleContext);
if (!smilAttr) {
// Target attribute not found (or, out of memory)
return;
@ -115,7 +125,7 @@ nsSMILCompositor::ClearAnimationEffects()
if (!mKey.mElement || !mKey.mAttributeName)
return;
UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr();
UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr(nullptr);
if (!smilAttr) {
// Target attribute not found (or, out of memory)
return;
@ -126,12 +136,13 @@ nsSMILCompositor::ClearAnimationEffects()
// Protected Helper Functions
// --------------------------
UniquePtr<nsISMILAttr>
nsSMILCompositor::CreateSMILAttr()
nsSMILCompositor::CreateSMILAttr(nsStyleContext* aBaseStyleContext)
{
nsCSSPropertyID propID = GetCSSPropertyToAnimate();
if (propID != eCSSProperty_UNKNOWN) {
return MakeUnique<nsSMILCSSProperty>(propID, mKey.mElement.get());
return MakeUnique<nsSMILCSSProperty>(propID, mKey.mElement.get(),
aBaseStyleContext);
}
return mKey.mElement->GetAnimatedAttr(mKey.mAttributeNamespaceID,
@ -173,6 +184,24 @@ nsSMILCompositor::GetCSSPropertyToAnimate() const
return propID;
}
bool
nsSMILCompositor::MightNeedBaseStyle() const
{
if (GetCSSPropertyToAnimate() == eCSSProperty_UNKNOWN) {
return false;
}
// We should return true if at least one animation function might build on
// the base value.
for (const nsSMILAnimationFunction* func : mAnimationFunctions) {
if (!func->WillReplace()) {
return true;
}
}
return false;
}
uint32_t
nsSMILCompositor::GetFirstFuncToAffectSandwich()
{

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

@ -74,12 +74,26 @@ public:
private:
// Create a nsISMILAttr for my target, on the heap.
mozilla::UniquePtr<nsISMILAttr> CreateSMILAttr();
//
// @param aBaseStyleContext An optional style context which, if set, will be
// used when fetching the base style.
mozilla::UniquePtr<nsISMILAttr>
CreateSMILAttr(nsStyleContext* aBaseStyleContext);
// Returns the CSS property this compositor should animate, or
// eCSSProperty_UNKNOWN if this compositor does not animate a CSS property.
nsCSSPropertyID GetCSSPropertyToAnimate() const;
// Returns true if we might need to refer to base styles (i.e. we are
// targeting a CSS property and have one or more animation functions that
// don't just replace the underlying value).
//
// This might return true in some cases where we don't actually need the base
// style since it doesn't build up the animation sandwich to check if the
// functions that appear to need the base style are actually replaced by
// a function further up the stack.
bool MightNeedBaseStyle() const;
// Finds the index of the first function that will affect our animation
// sandwich. Also toggles the 'mForceCompositing' flag if it finds that any
// (used) functions have changed.

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

@ -57,5 +57,6 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_smilTimingZeroIntervals.xhtml]
[test_smilUpdatedInterval.xhtml]
[test_smilValues.xhtml]
[test_smilWithTransition.html]
[test_smilWithXlink.xhtml]
[test_smilXHR.xhtml]

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

@ -0,0 +1,72 @@
<!doctype html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1315874
-->
<head>
<meta charset="utf-8">
<title>Test SMIL does not trigger CSS Transitions (bug 1315874)</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315874">Mozilla Bug
1315874</a>
<svg>
<rect width="100%" height="100%"
style="fill: red; transition: fill 10s" id="rect">
<animate attributeName="fill" to="lime" dur="1s" fill="freeze">
</rect>
</svg>
<pre id="test">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
window.addEventListener('load', runTests, false);
var rect = document.getElementById('rect');
var svg = document.getElementsByTagName('svg')[0];
is(getComputedStyle(rect).fill, 'rgb(255, 0, 0)',
'The initial color should be red.');
function runTests() {
waitForFrame().then(function() {
svg.setCurrentTime(1);
ok(getComputedStyle(rect).fill, 'rgb(0, 255, 0)',
'The end color should be lime.');
return waitForAnimationFrames(2);
}).then(function() {
var anim = document.getAnimations()[0];
ok(!anim, 'Transition should not be created by restyling for SMIL');
SimpleTest.finish();
});
}
// Utility methods from testcommon.js
// For detail, see dom/animation/test/testcommon.js.
function waitForFrame() {
return new Promise(function(resolve, reject) {
requestAnimationFrame(function(time) {
resolve();
});
});
}
function waitForAnimationFrames(frameCount) {
return new Promise(function(resolve, reject) {
function handleFrame() {
if (--frameCount <= 0) {
resolve();
} else {
window.requestAnimationFrame(handleFrame);
}
}
window.requestAnimationFrame(handleFrame);
});
}
</script>
</pre>
</body>
</html>

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

@ -179,8 +179,7 @@ SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
styleContext = aStyleContext;
} else {
styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
}
if (!styleContext) {
@ -253,8 +252,7 @@ SVGContentUtils::GetStrokeWidth(nsSVGElement* aElement,
styleContext = aStyleContext;
} else {
styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
}
if (!styleContext) {
@ -276,9 +274,8 @@ SVGContentUtils::GetFontSize(Element *aElement)
if (!aElement)
return 1.0f;
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nullptr, nullptr);
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
if (!styleContext) {
// ReportToConsole
NS_WARNING("Couldn't get style context for content in GetFontStyle");
@ -314,9 +311,8 @@ SVGContentUtils::GetFontXHeight(Element *aElement)
if (!aElement)
return 1.0f;
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nullptr, nullptr);
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
if (!styleContext) {
// ReportToConsole
NS_WARNING("Couldn't get style context for content in GetFontStyle");
@ -325,7 +321,7 @@ SVGContentUtils::GetFontXHeight(Element *aElement)
return GetFontXHeight(styleContext);
}
float
SVGContentUtils::GetFontXHeight(nsIFrame *aFrame)
{

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

@ -127,9 +127,8 @@ SVGGeometryElement::GetFillRule()
FillRule fillRule = FillRule::FILL_WINDING; // Equivalent to StyleFillRule::Nonzero
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr,
nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(this, nullptr, nullptr);
if (styleContext) {
MOZ_ASSERT(styleContext->StyleSVG()->mFillRule == StyleFillRule::Nonzero ||
styleContext->StyleSVG()->mFillRule == StyleFillRule::Evenodd);

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

@ -328,7 +328,7 @@ SVGPathElement::BuildPath(PathBuilder* aBuilder)
Float strokeWidth = 0;
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(this, nullptr, nullptr);
if (styleContext) {
const nsStyleSVG* style = styleContext->StyleSVG();
// Note: the path that we return may be used for hit-testing, and SVG

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

@ -596,9 +596,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"InstallTrigger",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "IntersectionObserver", disabled: true},
"IntersectionObserver",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "IntersectionObserverEntry", disabled: true},
"IntersectionObserverEntry",
// IMPORTANT: Do not change this list without review from a DOM peer!
"KeyEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!

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

@ -3535,8 +3535,7 @@ IsElementVisible(Element* aElement)
// lazy frame construction and it hasn't happened yet. Check which
// one it is.
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nullptr, nullptr);
nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
if (styleContext) {
return styleContext->StyleDisplay()->mDisplay != StyleDisplay::None;
}
@ -3867,9 +3866,9 @@ EditorBase::IsPreformatted(nsIDOMNode* aNode,
content = content->GetParent();
}
if (content && content->IsElement()) {
elementStyle = nsComputedDOMStyle::GetStyleContextForElementNoFlush(content->AsElement(),
nullptr,
ps);
elementStyle =
nsComputedDOMStyle::GetStyleContextNoFlush(content->AsElement(),
nullptr, ps);
}
if (!elementStyle) {

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

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_mscom_IHandlerPayload_h
#define mozilla_mscom_IHandlerPayload_h
#include "mozilla/mscom/Ptr.h"
#include <objidl.h>
namespace mozilla {
namespace mscom {
struct HandlerPayload
{
virtual STDMETHODIMP GetHandler(CLSID* aHandlerClsid) = 0;
virtual STDMETHODIMP GetHandlerPayloadSize(REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget,
DWORD* aOutPayloadSize) = 0;
virtual STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget) = 0;
virtual REFIID MarshalAs(REFIID aIid) = 0;
};
struct IHandlerPayload : public IUnknown
, public HandlerPayload
{
virtual STDMETHODIMP Clone(IHandlerPayload** aOutNewPayload) = 0;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_IHandlerPayload_h

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

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_mscom_IHandlerProvider_h
#define mozilla_mscom_IHandlerProvider_h
#include "mozilla/NotNull.h"
#include "mozilla/mscom/Ptr.h"
#include <objidl.h>
namespace mozilla {
namespace mscom {
struct HandlerProvider
{
virtual STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) = 0;
virtual STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) = 0;
virtual STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) = 0;
virtual STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) = 0;
};
struct IHandlerProvider : public IUnknown
, public HandlerProvider
{
virtual STDMETHODIMP NewInstance(REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget,
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_IHandlerProvider_h

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

@ -78,7 +78,7 @@ Interceptor::GetClassForHandler(DWORD aDestContext, void* aDestContextPtr,
return E_INVALIDARG;
}
MOZ_ASSERT(mEventSink);
return mEventSink->GetHandler(aHandlerClsid);
return mEventSink->GetHandler(WrapNotNull(aHandlerClsid));
}
HRESULT
@ -101,10 +101,8 @@ Interceptor::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
return hr;
}
InterceptorTargetPtr<IUnknown> targetParam(mTarget.get());
DWORD payloadSize = 0;
hr = mEventSink->GetHandlerPayloadSize(riid, Move(targetParam), &payloadSize);
hr = mEventSink->GetHandlerPayloadSize(WrapNotNull(&payloadSize));
*pSize += payloadSize;
return hr;
}
@ -120,8 +118,7 @@ Interceptor::MarshalInterface(IStream* pStm, REFIID riid, void* pv,
return hr;
}
InterceptorTargetPtr<IUnknown> targetParam(mTarget.get());
return mEventSink->WriteHandlerPayload(pStm, riid, Move(targetParam));
return mEventSink->WriteHandlerPayload(WrapNotNull(pStm));
}
HRESULT
@ -367,7 +364,7 @@ Interceptor::ThreadSafeQueryInterface(REFIID aIid, IUnknown** aOutInterface)
// support it. We'll check that by looking for a successful call to
// IInterceptorSink::GetHandler()
CLSID dummy;
if (FAILED(mEventSink->GetHandler(&dummy))) {
if (FAILED(mEventSink->GetHandler(WrapNotNull(&dummy)))) {
return E_NOINTERFACE;
}
@ -381,7 +378,7 @@ Interceptor::ThreadSafeQueryInterface(REFIID aIid, IUnknown** aOutInterface)
// support it. We'll check that by looking for a successful call to
// IInterceptorSink::GetHandler()
CLSID dummy;
if (FAILED(mEventSink->GetHandler(&dummy))) {
if (FAILED(mEventSink->GetHandler(WrapNotNull(&dummy)))) {
return E_NOINTERFACE;
}

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

@ -10,7 +10,7 @@
#include "mozilla/Move.h"
#include "mozilla/Mutex.h"
#include "nsTArray.h"
#include "mozilla/mscom/IHandlerPayload.h"
#include "mozilla/mscom/IHandlerProvider.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/WeakRef.h"
#include "mozilla/RefPtr.h"
@ -26,7 +26,7 @@ DEFINE_GUID(IID_IInterceptorSink,
0x8831eb53, 0xa937, 0x42bc, 0x99, 0x21, 0xb3, 0xe1, 0x12, 0x1f, 0xdf, 0x86);
struct IInterceptorSink : public ICallFrameEvents
, public HandlerPayload
, public HandlerProvider
{
virtual STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) = 0;
};

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

@ -159,16 +159,16 @@ namespace mozilla {
namespace mscom {
/* static */ HRESULT
MainThreadHandoff::Create(IHandlerPayload* aHandlerPayload,
MainThreadHandoff::Create(IHandlerProvider* aHandlerProvider,
IInterceptorSink** aOutput)
{
RefPtr<MainThreadHandoff> handoff(new MainThreadHandoff(aHandlerPayload));
RefPtr<MainThreadHandoff> handoff(new MainThreadHandoff(aHandlerProvider));
return handoff->QueryInterface(IID_IInterceptorSink, (void**) aOutput);
}
MainThreadHandoff::MainThreadHandoff(IHandlerPayload* aHandlerPayload)
MainThreadHandoff::MainThreadHandoff(IHandlerProvider* aHandlerProvider)
: mRefCnt(0)
, mHandlerPayload(aHandlerPayload)
, mHandlerProvider(aHandlerProvider)
{
}
@ -448,43 +448,39 @@ MainThreadHandoff::SetInterceptor(IWeakReference* aInterceptor)
}
HRESULT
MainThreadHandoff::GetHandler(CLSID* aHandlerClsid)
MainThreadHandoff::GetHandler(NotNull<CLSID*> aHandlerClsid)
{
if (!mHandlerPayload) {
if (!mHandlerProvider) {
return E_NOTIMPL;
}
return mHandlerPayload->GetHandler(aHandlerClsid);
return mHandlerProvider->GetHandler(aHandlerClsid);
}
HRESULT
MainThreadHandoff::GetHandlerPayloadSize(REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget,
DWORD* aOutPayloadSize)
MainThreadHandoff::GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize)
{
if (!mHandlerPayload) {
if (!mHandlerProvider) {
return E_NOTIMPL;
}
return mHandlerPayload->GetHandlerPayloadSize(aIid, Move(aTarget),
aOutPayloadSize);
return mHandlerProvider->GetHandlerPayloadSize(aOutPayloadSize);
}
HRESULT
MainThreadHandoff::WriteHandlerPayload(IStream* aStream, REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget)
MainThreadHandoff::WriteHandlerPayload(NotNull<IStream*> aStream)
{
if (!mHandlerPayload) {
if (!mHandlerProvider) {
return E_NOTIMPL;
}
return mHandlerPayload->WriteHandlerPayload(aStream, aIid, Move(aTarget));
return mHandlerProvider->WriteHandlerPayload(aStream);
}
REFIID
MainThreadHandoff::MarshalAs(REFIID aIid)
{
if (!mHandlerPayload) {
if (!mHandlerProvider) {
return aIid;
}
return mHandlerPayload->MarshalAs(aIid);
return mHandlerProvider->MarshalAs(aIid);
}
HRESULT
@ -529,24 +525,31 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
InterceptorTargetPtr<IUnknown> existingTarget;
hr = interceptor->GetTargetForIID(aIid, existingTarget);
if (SUCCEEDED(hr)) {
bool areIUnknownsEqual = false;
// We'll start by checking the raw pointers. If they are equal, then the
// objects are equal. OTOH, if they differ, we must compare their
// IUnknown pointers to know for sure.
bool areTargetsEqual = existingTarget.get() == origInterface.get();
// This check must be done on the main thread
auto checkFn = [&existingTarget, &origInterface, &areIUnknownsEqual]() -> void {
RefPtr<IUnknown> unkExisting;
HRESULT hrExisting =
existingTarget->QueryInterface(IID_IUnknown,
(void**)getter_AddRefs(unkExisting));
RefPtr<IUnknown> unkNew;
HRESULT hrNew =
origInterface->QueryInterface(IID_IUnknown,
(void**)getter_AddRefs(unkNew));
areIUnknownsEqual = SUCCEEDED(hrExisting) && SUCCEEDED(hrNew) &&
if (!areTargetsEqual) {
// This check must be done on the main thread
auto checkFn = [&existingTarget, &origInterface, &areTargetsEqual]() -> void {
RefPtr<IUnknown> unkExisting;
HRESULT hrExisting =
existingTarget->QueryInterface(IID_IUnknown,
(void**)getter_AddRefs(unkExisting));
RefPtr<IUnknown> unkNew;
HRESULT hrNew =
origInterface->QueryInterface(IID_IUnknown,
(void**)getter_AddRefs(unkNew));
areTargetsEqual = SUCCEEDED(hrExisting) && SUCCEEDED(hrNew) &&
unkExisting == unkNew;
};
};
MainThreadInvoker invoker;
if (invoker.Invoke(NS_NewRunnableFunction(checkFn)) && areIUnknownsEqual) {
MainThreadInvoker invoker;
invoker.Invoke(NS_NewRunnableFunction(checkFn));
}
if (areTargetsEqual) {
// The existing interface and the new interface both belong to the same
// target object. Let's just use the existing one.
void* intercepted = nullptr;
@ -560,9 +563,11 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
}
}
RefPtr<IHandlerPayload> payload;
if (mHandlerPayload) {
hr = mHandlerPayload->Clone(getter_AddRefs(payload));
RefPtr<IHandlerProvider> payload;
if (mHandlerProvider) {
hr = mHandlerProvider->NewInstance(aIid,
ToInterceptorTargetPtr(origInterface),
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
MOZ_ASSERT(SUCCEEDED(hr));
if (FAILED(hr)) {
return hr;

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

@ -24,7 +24,7 @@ class MainThreadHandoff final : public IInterceptorSink
, public ICallFrameWalker
{
public:
static HRESULT Create(IHandlerPayload* aHandlerPayload,
static HRESULT Create(IHandlerProvider* aHandlerProvider,
IInterceptorSink** aOutput);
template <typename Interface>
@ -37,12 +37,12 @@ public:
template <typename Interface>
static HRESULT WrapInterface(STAUniquePtr<Interface> aTargetInterface,
IHandlerPayload* aHandlerPayload,
IHandlerProvider* aHandlerProvider,
Interface** aOutInterface)
{
MOZ_ASSERT(!IsProxy(aTargetInterface.get()));
RefPtr<IInterceptorSink> handoff;
HRESULT hr = MainThreadHandoff::Create(aHandlerPayload,
HRESULT hr = MainThreadHandoff::Create(aHandlerProvider,
getter_AddRefs(handoff));
if (FAILED(hr)) {
return hr;
@ -60,29 +60,26 @@ public:
// IInterceptorSink
STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) override;
STDMETHODIMP GetHandler(CLSID* aHandlerClsid) override;
STDMETHODIMP GetHandlerPayloadSize(REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget,
DWORD* aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget) override;
REFIID MarshalAs(REFIID aIid) override;
STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override;
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
// ICallFrameWalker
STDMETHODIMP OnWalkInterface(REFIID aIid, PVOID* aInterface, BOOL aIsInParam,
BOOL aIsOutParam) override;
private:
explicit MainThreadHandoff(IHandlerPayload* aHandlerPayload);
explicit MainThreadHandoff(IHandlerProvider* aHandlerProvider);
~MainThreadHandoff();
HRESULT FixArrayElements(ICallFrame* aFrame,
const ArrayData& aArrayData);
HRESULT FixIServiceProvider(ICallFrame* aFrame);
private:
ULONG mRefCnt;
RefPtr<IWeakReference> mInterceptor;
RefPtr<IHandlerPayload> mHandlerPayload;
ULONG mRefCnt;
RefPtr<IWeakReference> mInterceptor;
RefPtr<IHandlerProvider> mHandlerProvider;
};
} // namespace mscom

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

@ -153,6 +153,14 @@ ToSTAUniquePtr(RefPtr<T>&& aRefPtr)
return STAUniquePtr<T>(aRefPtr.forget().take());
}
template <typename T>
inline STAUniquePtr<T>
ToSTAUniquePtr(const RefPtr<T>& aRefPtr)
{
MOZ_ASSERT(NS_IsMainThread());
return STAUniquePtr<T>(do_AddRef(aRefPtr).take());
}
template <typename T>
inline STAUniquePtr<T>
ToSTAUniquePtr(T* aRawPtr)
@ -164,6 +172,15 @@ ToSTAUniquePtr(T* aRawPtr)
return STAUniquePtr<T>(aRawPtr);
}
template <typename T, typename U>
inline STAUniquePtr<T>
ToSTAUniquePtr(const InterceptorTargetPtr<U>& aTarget)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<T> newRef(static_cast<T*>(aTarget.get()));
return ToSTAUniquePtr(Move(newRef));
}
template <typename T>
inline MTAUniquePtr<T>
ToMTAUniquePtr(RefPtr<T>&& aRefPtr)
@ -171,6 +188,14 @@ ToMTAUniquePtr(RefPtr<T>&& aRefPtr)
return MTAUniquePtr<T>(aRefPtr.forget().take());
}
template <typename T>
inline MTAUniquePtr<T>
ToMTAUniquePtr(const RefPtr<T>& aRefPtr)
{
MOZ_ASSERT(IsCurrentThreadMTA());
return MTAUniquePtr<T>(do_AddRef(aRefPtr).take());
}
template <typename T>
inline MTAUniquePtr<T>
ToMTAUniquePtr(T* aRawPtr)
@ -189,6 +214,17 @@ ToProxyUniquePtr(RefPtr<T>&& aRefPtr)
return ProxyUniquePtr<T>(aRefPtr.forget().take());
}
template <typename T>
inline ProxyUniquePtr<T>
ToProxyUniquePtr(const RefPtr<T>& aRefPtr)
{
MOZ_ASSERT(IsProxy(aRawPtr));
MOZ_ASSERT((XRE_IsParentProcess() && NS_IsMainThread()) ||
(XRE_IsContentProcess() && IsCurrentThreadMTA()));
return ProxyUniquePtr<T>(do_AddRef(aRefPtr).take());
}
template <typename T>
inline ProxyUniquePtr<T>
ToProxyUniquePtr(T* aRawPtr)
@ -203,6 +239,13 @@ ToProxyUniquePtr(T* aRawPtr)
return ProxyUniquePtr<T>(aRawPtr);
}
template <typename T, typename Deleter>
inline InterceptorTargetPtr<T>
ToInterceptorTargetPtr(const UniquePtr<T, Deleter>& aTargetPtr)
{
return InterceptorTargetPtr<T>(aTargetPtr.get());
}
template <typename T, typename Deleter>
inline detail::UniquePtrGetterAddRefs<T, Deleter>
getter_AddRefs(UniquePtr<T, Deleter>& aSmartPtr)

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

@ -33,7 +33,7 @@ if CONFIG['ACCESSIBILITY']:
EXPORTS.mozilla.mscom += [
'ActivationContext.h',
'DispatchForwarder.h',
'IHandlerPayload.h',
'IHandlerProvider.h',
'Interceptor.h',
'InterceptorLog.h',
'MainThreadHandoff.h',

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

@ -8,6 +8,7 @@
#include "Module.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "nsWindowsHelpers.h"
#include <objbase.h>
@ -21,27 +22,29 @@
namespace mozilla {
namespace mscom {
Handler::Handler(IUnknown* aOuter, HRESULT& aResult)
Handler::Handler(IUnknown* aOuter, HRESULT* aResult)
: mRefCnt(0)
, mOuter(aOuter)
, mUnmarshal(nullptr)
, mHasPayload(false)
{
MOZ_ASSERT(aResult);
if (!aOuter) {
aResult = E_INVALIDARG;
*aResult = E_INVALIDARG;
return;
}
StabilizedRefCount<ULONG> stabilizer(mRefCnt);
aResult = ::CoGetStdMarshalEx(aOuter, SMEXF_HANDLER,
getter_AddRefs(mInnerUnk));
if (FAILED(aResult)) {
*aResult = ::CoGetStdMarshalEx(aOuter, SMEXF_HANDLER,
getter_AddRefs(mInnerUnk));
if (FAILED(*aResult)) {
return;
}
aResult = mInnerUnk->QueryInterface(IID_IMarshal, (void**)&mUnmarshal);
if (FAILED(aResult)) {
*aResult = mInnerUnk->QueryInterface(IID_IMarshal, (void**)&mUnmarshal);
if (FAILED(*aResult)) {
return;
}
@ -90,11 +93,12 @@ Handler::InternalAddRef()
ULONG
Handler::InternalRelease()
{
if (--mRefCnt == 0) {
ULONG newRefCnt = --mRefCnt;
if (newRefCnt == 0) {
delete this;
Module::Unlock();
}
return mRefCnt;
return newRefCnt;
}
HRESULT

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

@ -106,7 +106,7 @@ public:
static HRESULT Unregister(REFCLSID aClsid);
protected:
Handler(IUnknown* aOuter, HRESULT& aResult);
Handler(IUnknown* aOuter, HRESULT* aResult);
virtual ~Handler() {}
bool HasPayload() const { return mHasPayload; }
IUnknown* GetOuter() const { return mOuter; }

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

@ -38,6 +38,8 @@ parser = argparse.ArgumentParser(
description='Run a spidermonkey shell build job')
parser.add_argument('--dep', action='store_true',
help='do not clobber the objdir before building')
parser.add_argument('--keep', action='store_true',
help='do not delete the sanitizer output directory (for testing)')
parser.add_argument('--platform', '-p', type=str, metavar='PLATFORM',
default='', help='build platform, including a suffix ("-debug" or "") used by buildbot to override the variant\'s "debug" setting. The platform can be used to specify 32 vs 64 bits.')
parser.add_argument('--timeout', '-t', type=int, metavar='TIMEOUT',
@ -275,7 +277,7 @@ timer.daemon = True
timer.start()
ensure_dir_exists(OBJDIR, clobber=not args.dep and not args.nobuild)
ensure_dir_exists(OUTDIR)
ensure_dir_exists(OUTDIR, clobber=not args.keep)
def run_command(command, check=False, **kwargs):
@ -373,6 +375,8 @@ test_suites |= set(normalize_tests(variant.get('extra-tests', {}).get('all', [])
# Now adjust the variant's default test list with command-line arguments.
test_suites |= set(normalize_tests(args.run_tests.split(",")))
test_suites -= set(normalize_tests(args.skip_tests.split(",")))
if 'all' in args.skip_tests.split(","):
test_suites = []
# Always run all enabled tests, even if earlier ones failed. But return the
# first failed status.
@ -408,6 +412,7 @@ if args.variant in ('tsan', 'msan'):
# Summarize results
sites = Counter()
errors = Counter()
for filename in fullfiles:
with open(os.path.join(OUTDIR, filename), 'rb') as fh:
for line in fh:
@ -427,11 +432,48 @@ if args.variant in ('tsan', 'msan'):
print >> outfh, "%d %s" % (count, location)
print(open(summary_filename, 'rb').read())
max_allowed = None
if 'max-errors' in variant:
print("Found %d errors out of %d allowed" % (len(sites), variant['max-errors']))
if len(sites) > variant['max-errors']:
max_allowed = variant['max-errors']
elif 'expect-errors' in variant:
max_allowed = len(variant['expect-errors'])
if max_allowed is not None:
print("Found %d errors out of %d allowed" % (len(sites), max_allowed))
if len(sites) > max_allowed:
results.append(1)
if 'expect-errors' in variant:
# Line numbers may shift around between versions, so just look for
# matching filenames and function names. This will still produce false
# positives when functions are renamed or moved between files, or
# things change so that the actual race is in a different place. But it
# still seems preferable to saying "You introduced an additional race.
# Here are the 21 races detected; please ignore the 20 known ones in
# this other list."
for site in sites:
# Grab out the file and function names.
m = re.search(r'/([^/]+):\d+ in (.+)', site)
if m:
error = tuple(m.groups())
else:
# will get here if eg tsan symbolication fails
error = (site, '(unknown)')
errors[error] += 1
remaining = Counter(errors)
for expect in variant['expect-errors']:
# expect-errors is an array of (filename, function) tuples.
expect = tuple(expect)
if remaining[expect] == 0:
print("Did not see expected error in %s function %s" % expect)
else:
remaining[expect] -= 1
for filename, function in (e for e, c in remaining.items() if c > 0):
print("*** tsan error in %s function %s" % (filename, function))
# Gather individual results into a tarball. Note that these are
# distinguished only by pid of the JS process running within each test, so
# given the 16-bit limitation of pids, it's totally possible that some of

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

@ -7,7 +7,29 @@
"LLVM_SYMBOLIZER": "{TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer",
"JITTEST_EXTRA_ARGS": "--jitflags=debug --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt",
"JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt",
"TSAN_OPTIONS": "log_path={OUTDIR}/sanitize_log"
"TSAN_OPTIONS": "exitcode=0 log_path={OUTDIR}/sanitize_log"
},
"max-errors": 14
"[comment on expect-errors]": "Note that expect-errors may contain duplicates. These indicate that tsan reports errors as two distinct line numbers. We cannot just insert line numbers, because they will shift around between versions.",
"expect-errors": [
[ "Shape.h", "inDictionary" ],
[ "jsfriendapi.h", "GetObjectClass" ],
[ "Shape.h", "maybeSlot" ],
[ "Barrier.h", "set" ],
[ "jitprofiling.c", "iJIT_GetNewMethodID" ],
[ "Statistics.h", "count" ],
[ "Shape.h", "setOverwritten" ],
[ "TestingFunctions.cpp", "js::DefineTestingFunctions(JSContext*, JS::Handle<JSObject*>, bool, bool)" ],
[ "TestingFunctions.cpp", "js::DefineTestingFunctions(JSContext*, JS::Handle<JSObject*>, bool, bool)" ],
[ "OSObject.cpp", "js::shell::DefineOS(JSContext*, JS::Handle<JSObject*>, bool, js::shell::RCFile**, js::shell::RCFile**)" ],
[ "OSObject.cpp", "js::shell::DefineOS(JSContext*, JS::Handle<JSObject*>, bool, js::shell::RCFile**, js::shell::RCFile**)" ],
[ "ObjectGroup.h", "addendumKind" ],
[ "jsfriendapi.h", "numFixedSlots" ],
[ "Marking.cpp", "js::GCMarker::reset()" ],
[ "jsfun.h", "setResolvedLength" ],
[ "Shape.h", "incrementNumLinearSearches" ],
[ "Statistics.h", "js::gc::GCRuntime::pickChunk(js::AutoLockGC const&, js::gc::AutoMaybeStartBackgroundAllocation&)" ],
[ "jsfun.h", "needsSomeEnvironmentObject" ],
[ "TypeInference-inl.h", "setBasePropertyCount" ],
[ "Statistics.h", "js::gc::GCRuntime::getOrAllocChunk(js::AutoLockGC const&, js::gc::AutoMaybeStartBackgroundAllocation&)" ]
]
}

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

@ -0,0 +1,63 @@
var max = 40;
setJitCompilerOption("ion.warmup.trigger", max - 10);
function selfhosted() {
if (typeof getSelfHostedValue === "undefined")
return;
var NewArrayIterator = getSelfHostedValue("NewArrayIterator");
var iter = NewArrayIterator();
bailout();
// assertRecoveredOnBailout(iter, true);
}
function iterator(i) {
var array = [1, i];
var iter = array[Symbol.iterator]();
assertEq(iter.next().value, 1);
bailout();
// This sometimes fails
// assertRecoveredOnBailout(iter, true);
var result = iter.next();
assertEq(result.value, i);
assertEq(result.done, false);
assertEq(iter.next().done, true);
}
function forof(i) {
var array = [1, i];
var first = true;
for (var x of array) {
if (first) {
assertEq(x, 1);
bailout();
first = false;
} else {
assertEq(x, i);
}
}
}
var data = {
a: 'foo',
b: {c: 'd'},
arr: [1, 2, 3]
};
function fn() {
var {a, b:{c:b}, arr:[, c]} = data;
return c;
}
function destructuring() {
for (var i = 0; i < max; i++)
assertEq(fn(), 2);
}
for (var i = 0; i < max; i++) {
selfhosted();
iterator(i);
forof(i);
destructuring();
}

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

@ -12,8 +12,6 @@
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/Sprintf.h"
#include <algorithm>
#include "jsprf.h"
#include "gc/Marking.h"
@ -645,14 +643,14 @@ JitcodeGlobalTable::generateTowerHeight()
rand_ ^= mozilla::RotateLeft(rand_, 5) ^ mozilla::RotateLeft(rand_, 24);
rand_ += 0x37798849;
// Return number of lowbit zeros in new randval.
// Return 1 + number of lowbit zeros in new randval, capped at MAX_HEIGHT.
unsigned result = 0;
for (unsigned i = 0; i < 32; i++) {
for (unsigned i = 0; i < JitcodeSkiplistTower::MAX_HEIGHT - 1; i++) {
if ((rand_ >> i) & 0x1)
break;
result++;
}
return (std::max)(1U, result);
return result + 1;
}
JitcodeSkiplistTower*

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

@ -4932,10 +4932,12 @@ MObjectState::templateObjectOf(MDefinition* obj)
return obj->toNewObject()->templateObject();
else if (obj->isCreateThisWithTemplate())
return obj->toCreateThisWithTemplate()->templateObject();
else
else if (obj->isNewCallObject())
return obj->toNewCallObject()->templateObject();
else if (obj->isNewArrayIterator())
return obj->toNewArrayIterator()->templateObject();
return nullptr;
MOZ_CRASH("unreachable");
}
bool

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

@ -3556,6 +3556,11 @@ class MNewArrayIterator
AliasSet getAliasSet() const override {
return AliasSet::None();
}
MOZ_MUST_USE bool writeRecoverData(CompactBufferWriter& writer) const override;
bool canRecoverOnBailout() const override {
return true;
}
};

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

@ -10,6 +10,7 @@
#include "jsapi.h"
#include "jscntxt.h"
#include "jsiter.h"
#include "jsmath.h"
#include "jsobj.h"
#include "jsstr.h"
@ -1365,6 +1366,34 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
return true;
}
bool
MNewArrayIterator::writeRecoverData(CompactBufferWriter& writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArrayIterator));
return true;
}
RNewArrayIterator::RNewArrayIterator(CompactBufferReader& reader)
{
}
bool
RNewArrayIterator::recover(JSContext* cx, SnapshotIterator& iter) const
{
RootedObject templateObject(cx, &iter.read().toObject());
RootedValue result(cx);
JSObject* resultObject = NewArrayIteratorObject(cx);
if (!resultObject)
return false;
result.setObject(*resultObject);
iter.storeInstructionResult(result);
return true;
}
bool
MNewDerivedTypedObject::writeRecoverData(CompactBufferWriter& writer) const
{

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

@ -102,6 +102,7 @@ namespace jit {
_(NewObject) \
_(NewTypedArray) \
_(NewArray) \
_(NewArrayIterator) \
_(NewDerivedTypedObject) \
_(CreateThisWithTemplate) \
_(Lambda) \
@ -593,6 +594,14 @@ class RNewArray final : public RInstruction
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
};
class RNewArrayIterator final : public RInstruction
{
public:
RINSTRUCTION_HEADER_NUM_OP_(NewArrayIterator, 1)
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
};
class RNewDerivedTypedObject final : public RInstruction
{
public:

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

@ -134,6 +134,13 @@ IsLambdaEscaped(MLambda* lambda, JSObject* obj)
return false;
}
static inline bool
IsOptimizableObjectInstruction(MInstruction* ins)
{
return ins->isNewObject() || ins->isCreateThisWithTemplate() || ins->isNewCallObject() ||
ins->isNewArrayIterator();
}
// Returns False if the object is not escaped and if it is optimizable by
// ScalarReplacementOfObject.
//
@ -143,8 +150,8 @@ static bool
IsObjectEscaped(MInstruction* ins, JSObject* objDefault)
{
MOZ_ASSERT(ins->type() == MIRType::Object);
MOZ_ASSERT(ins->isNewObject() || ins->isGuardShape() || ins->isCreateThisWithTemplate() ||
ins->isNewCallObject() || ins->isFunctionEnvironment());
MOZ_ASSERT(IsOptimizableObjectInstruction(ins) || ins->isGuardShape() ||
ins->isFunctionEnvironment());
JitSpewDef(JitSpew_Escape, "Check object\n", ins);
JitSpewIndent spewIndent(JitSpew_Escape);
@ -1311,8 +1318,7 @@ ScalarReplacement(MIRGenerator* mir, MIRGraph& graph)
return false;
for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
if ((ins->isNewObject() || ins->isCreateThisWithTemplate() || ins->isNewCallObject()) &&
!IsObjectEscaped(*ins))
if (IsOptimizableObjectInstruction(*ins) && !IsObjectEscaped(*ins))
{
ObjectMemoryView view(graph.alloc(), *ins);
if (!replaceObject.run(view))

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

@ -4511,10 +4511,10 @@ JSCompartment::findDeadProxyZoneEdges(bool* foundAny)
if (IsDeadProxyObject(&value.toObject())) {
*foundAny = true;
CrossCompartmentKey& key = e.front().mutableKey();
Zone* wrapperZone = key.as<JSObject*>()->zone();
if (!wrapperZone->isGCMarking())
Zone* wrappedZone = key.as<JSObject*>()->zone();
if (!wrappedZone->isGCMarking())
continue;
if (!wrapperZone->gcSweepGroupEdges().put(zone()))
if (!wrappedZone->gcSweepGroupEdges().put(zone()))
return false;
}
}

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

@ -1947,8 +1947,12 @@ Debugger::slowPathOnNewScript(JSContext* cx, HandleScript script)
return JSTRAP_CONTINUE;
});
if (status == JSTRAP_ERROR)
// dispatchHook may fail due to OOM. This OOM is not handlable at the
// callsites of onNewScript in the engine.
if (status == JSTRAP_ERROR) {
cx->clearPendingException();
return;
}
MOZ_ASSERT(status == JSTRAP_CONTINUE);
}
@ -1967,8 +1971,12 @@ Debugger::slowPathOnNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> w
return JSTRAP_CONTINUE;
});
if (status == JSTRAP_ERROR)
// dispatchHook may fail due to OOM. This OOM is not handlable at the
// callsites of onNewWasmInstance in the engine.
if (status == JSTRAP_ERROR) {
cx->clearPendingException();
return;
}
MOZ_ASSERT(status == JSTRAP_CONTINUE);
}

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

@ -148,7 +148,7 @@ public:
uint32_t((TimeStamp::Now() - start).ToMilliseconds()));
if (hadSnowWhiteObjects && !mContinuation) {
mContinuation = true;
if (NS_FAILED(NS_DispatchToCurrentThread(this))) {
if (NS_FAILED(Dispatch())) {
mActive = false;
}
} else {
@ -169,13 +169,25 @@ public:
return NS_OK;
}
void Dispatch(bool aContinuation = false, bool aPurge = false)
nsresult Dispatch()
{
if (NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> self(this);
return SystemGroup::Dispatch("AsyncFreeSnowWhite",
TaskCategory::GarbageCollection,
self.forget());
} else {
return NS_DispatchToCurrentThread(this);
}
}
void Start(bool aContinuation = false, bool aPurge = false)
{
if (mContinuation) {
mContinuation = aContinuation;
}
mPurge = aPurge;
if (!mActive && NS_SUCCEEDED(NS_DispatchToCurrentThread(this))) {
if (!mActive && NS_SUCCEEDED(Dispatch())) {
mActive = true;
}
}
@ -735,7 +747,7 @@ XPCJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults)
void
XPCJSContext::DispatchDeferredDeletion(bool aContinuation, bool aPurge)
{
mAsyncSnowWhiteFreer->Dispatch(aContinuation, aPurge);
mAsyncSnowWhiteFreer->Start(aContinuation, aPurge);
}
void

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

@ -97,6 +97,7 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext* cx,
mNext(nullptr),
mGlobalJSObject(aGlobal),
mHasCallInterpositions(false),
mDocGroupValidation(false),
mIsContentXBLScope(false),
mIsAddonScope(false)
{
@ -167,6 +168,9 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext* cx,
if (addonId) {
// We forbid CPOWs unless they're specifically allowed.
priv->allowCPOWs = gAllowCPOWAddonSet ? gAllowCPOWAddonSet->has(addonId) : false;
// Automatically opt into DocGroup validation for add-on compartments.
mDocGroupValidation = true;
}
}

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

@ -1373,6 +1373,12 @@ AllowCPOWsInAddon(const nsACString& addonIdStr, bool allow)
return XPCWrappedNativeScope::AllowCPOWsInAddon(jsapi.cx(), addonId, allow);
}
void
SetDocGroupValidation(JSObject* global)
{
CompartmentPrivate::Get(global)->scope->SetDocGroupValidation();
}
} // namespace xpc
namespace mozilla {

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