MozReview-Commit-ID: 9Ne0XZtlRh5
This commit is contained in:
Kartikaya Gupta 2017-04-18 08:36:05 -04:00
Родитель 0e0ea44db7 bb87f43c09
Коммит 9945c16d87
306 изменённых файлов: 13526 добавлений и 10849 удалений

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

@ -238,8 +238,8 @@ default all::
include $(topsrcdir)/config/rules.mk
ifdef SCCACHE_VERBOSE_STATS
# This won't contain stats for both halves of a universal build, but I can live with that.
default::
-$(CCACHE) --show-stats --stats-format=json > sccache-stats.json
@echo "===SCCACHE STATS==="
-$(CCACHE) --show-stats
@echo "==================="

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

@ -338,6 +338,21 @@ DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
return IPC_OK();
}
#if defined(XP_WIN)
mozilla::ipc::IPCResult
DocAccessibleParent::RecvSyncTextChangeEvent(const uint64_t& aID,
const nsString& aStr,
const int32_t& aStart,
const uint32_t& aLen,
const bool& aIsInsert,
const bool& aFromUser)
{
return RecvTextChangeEvent(aID, aStr, aStart, aLen, aIsInsert, aFromUser);
}
#endif // defined(XP_WIN)
mozilla::ipc::IPCResult
DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID,
@ -436,6 +451,11 @@ DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
return IPC_FAIL(this, "binding to proxy that can't be a outerDoc!");
}
if (outerDoc->ChildrenCount() == 1) {
MOZ_ASSERT(outerDoc->ChildAt(0)->AsDoc());
outerDoc->ChildAt(0)->AsDoc()->Unbind();
}
aChildDoc->SetParent(outerDoc);
outerDoc->SetChildDoc(aChildDoc);
mChildDocs.AppendElement(aChildDoc->mActorID);

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

@ -88,6 +88,13 @@ public:
const bool& aIsInsert,
const bool& aFromUser) override;
#if defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvSyncTextChangeEvent(const uint64_t& aID, const nsString& aStr,
const int32_t& aStart, const uint32_t& aLen,
const bool& aIsInsert,
const bool& aFromUser) override;
#endif // defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID,
const uint32_t& aType) override;

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

@ -54,15 +54,9 @@ template <class Derived>
void
ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc)
{
// DocAccessibleParent::AddChildDoc tolerates replacing one document with
// another. We must reflect that here.
MOZ_ASSERT(aChildDoc);
MOZ_ASSERT(mChildren.Length() <= 1);
if (mChildren.IsEmpty()) {
mChildren.AppendElement(aChildDoc);
} else {
mChildren.ReplaceElementAt(0, aChildDoc);
}
MOZ_ASSERT(mChildren.Length() == 0);
mChildren.AppendElement(aChildDoc);
mOuterDoc = true;
}

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

@ -77,6 +77,18 @@ DocAccessibleChild::RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandl
return IPC_OK();
}
HWND
DocAccessibleChild::GetNativeWindowHandle() const
{
if (mEmulatedWindowHandle) {
return mEmulatedWindowHandle;
}
auto tab = static_cast<dom::TabChild*>(Manager());
MOZ_ASSERT(tab);
return reinterpret_cast<HWND>(tab->GetNativeWindowHandle());
}
void
DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent)
{
@ -178,6 +190,13 @@ DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID,
const bool& aFromUser)
{
if (IsConstructedInParentProcess()) {
if (aStr.Contains(L'\xfffc')) {
// The AT is going to need to reenter content while the event is being
// dispatched synchronously.
return PDocAccessibleChild::SendSyncTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert,
aFromUser);
}
return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert, aFromUser);
}

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

@ -33,7 +33,7 @@ public:
RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
const IAccessibleHolder& aEmulatedWindowCOMProxy) override;
HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
HWND GetNativeWindowHandle() const;
IAccessible* GetEmulatedWindowIAccessible() const { return mEmulatedWindowProxy.get(); }
IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }

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

@ -53,6 +53,8 @@ parent:
async CaretMoveEvent(uint64_t aID, int32_t aOffset);
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
bool aIsInsert, bool aFromUser);
sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,
uint32_t aLen, bool aIsInsert, bool aFromUser);
async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
async RoleChangedEvent(uint32_t aRole);

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

@ -12,6 +12,7 @@
#include "AccessibleHandler.h"
#include "AccessibleHandlerControl.h"
#include "AccessibleTextTearoff.h"
#include "Factory.h"
#include "HandlerData.h"
@ -183,6 +184,12 @@ AccessibleHandler::QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
return S_OK;
}
if (aIid == IID_IAccessibleText || aIid == IID_IAccessibleHypertext) {
RefPtr<IAccessibleHypertext> textTearoff(new AccessibleTextTearoff(this));
textTearoff.forget(aOutInterface);
return S_OK;
}
if (aIid == IID_IProvideClassInfo) {
RefPtr<IProvideClassInfo> clsInfo(this);
clsInfo.forget(aOutInterface);

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

@ -22,6 +22,103 @@ namespace a11y {
mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
namespace detail {
TextChange::TextChange()
: mIA2UniqueId(0)
, mIsInsert(false)
, mText()
{
}
TextChange::TextChange(long aIA2UniqueId, bool aIsInsert,
NotNull<IA2TextSegment*> aText)
: mIA2UniqueId(aIA2UniqueId)
, mIsInsert(aIsInsert)
, mText{BSTRCopy(aText->text), aText->start, aText->end}
{
}
TextChange::TextChange(TextChange&& aOther)
: mText()
{
*this = Move(aOther);
}
TextChange::TextChange(const TextChange& aOther)
: mText()
{
*this = aOther;
}
TextChange&
TextChange::operator=(TextChange&& aOther)
{
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
aOther.mIA2UniqueId = 0;
::SysFreeString(mText.text);
mText = aOther.mText;
aOther.mText.text = nullptr;
return *this;
}
TextChange&
TextChange::operator=(const TextChange& aOther)
{
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
::SysFreeString(mText.text);
mText = {BSTRCopy(aOther.mText.text), aOther.mText.start, aOther.mText.end};
return *this;
}
TextChange::~TextChange()
{
::SysFreeString(mText.text);
}
HRESULT
TextChange::GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment)
{
if (mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutOldSegment, mText);
}
HRESULT
TextChange::GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment)
{
if (!mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutNewSegment, mText);
}
/* static */ BSTR
TextChange::BSTRCopy(const BSTR& aIn)
{
return ::SysAllocStringLen(aIn, ::SysStringLen(aIn));
}
/* static */ HRESULT
TextChange::SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc)
{
aDest = {BSTRCopy(aSrc.text), aSrc.start, aSrc.end};
if (aSrc.text && !aDest.text) {
return E_OUTOFMEMORY;
}
if (!::SysStringLen(aDest.text)) {
return S_FALSE;
}
return S_OK;
}
} // namespace detail
HRESULT
AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
{
@ -35,46 +132,14 @@ AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
}
AccessibleHandlerControl::AccessibleHandlerControl()
: mRefCnt(0)
, mCacheGen(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;
}
IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
HRESULT
AccessibleHandlerControl::Invalidate()
@ -83,6 +148,36 @@ AccessibleHandlerControl::Invalidate()
return S_OK;
}
HRESULT
AccessibleHandlerControl::OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert,
IA2TextSegment* aText)
{
if (!aText) {
return E_INVALIDARG;
}
mTextChange = detail::TextChange(aIA2UniqueId, aIsInsert, WrapNotNull(aText));
NotifyWinEvent(aIsInsert ? IA2_EVENT_TEXT_INSERTED : IA2_EVENT_TEXT_REMOVED,
reinterpret_cast<HWND>(static_cast<uintptr_t>(aHwnd)),
OBJID_CLIENT, aIA2UniqueId);
return S_OK;
}
HRESULT
AccessibleHandlerControl::GetNewText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutNewText)
{
return mTextChange.GetNew(aIA2UniqueId, aOutNewText);
}
HRESULT
AccessibleHandlerControl::GetOldText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutOldText)
{
return mTextChange.GetOld(aIA2UniqueId, aOutOldText);
}
HRESULT
AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo)
{

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

@ -13,37 +13,70 @@
#include "Factory.h"
#include "HandlerData.h"
#include "IUnknownImpl.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/NotNull.h"
namespace mozilla {
namespace a11y {
namespace detail {
class TextChange final
{
public:
TextChange();
TextChange(long aIA2UniqueId, bool aIsInsert, NotNull<IA2TextSegment*> aText);
TextChange(TextChange&& aOther);
TextChange(const TextChange& aOther);
TextChange& operator=(TextChange&& aOther);
TextChange& operator=(const TextChange& aOther);
~TextChange();
HRESULT GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment);
HRESULT GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment);
private:
static BSTR BSTRCopy(const BSTR& aIn);
static HRESULT SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc);
long mIA2UniqueId;
bool mIsInsert;
IA2TextSegment mText;
};
} // namespace detail
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;
DECL_IUNKNOWN
// IHandlerControl
STDMETHODIMP Invalidate() override;
STDMETHODIMP OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert, IA2TextSegment* aText) override;
uint32_t GetCacheGen() const
{
return mCacheGen;
}
HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
private:
AccessibleHandlerControl();
~AccessibleHandlerControl() = default;
ULONG mRefCnt;
uint32_t mCacheGen;
detail::TextChange mTextChange;
UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
};

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

@ -0,0 +1,359 @@
/* -*- 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 "AccessibleTextTearoff.h"
#include "AccessibleHandlerControl.h"
#include "AccessibleText_i.c"
#include "AccessibleHypertext_i.c"
#include "Factory.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace a11y {
AccessibleTextTearoff::AccessibleTextTearoff(AccessibleHandler* aHandler)
: mHandler(aHandler)
{
MOZ_ASSERT(aHandler);
}
HRESULT
AccessibleTextTearoff::ResolveAccText()
{
if (mAccTextProxy) {
return S_OK;
}
RefPtr<IUnknown> proxy(mHandler->GetProxy());
if (!proxy) {
return E_UNEXPECTED;
}
return proxy->QueryInterface(IID_IAccessibleText,
getter_AddRefs(mAccTextProxy));
}
HRESULT
AccessibleTextTearoff::ResolveAccHypertext()
{
if (mAccHypertextProxy) {
return S_OK;
}
RefPtr<IUnknown> proxy(mHandler->GetProxy());
if (!proxy) {
return E_UNEXPECTED;
}
return proxy->QueryInterface(IID_IAccessibleHypertext,
getter_AddRefs(mAccHypertextProxy));
}
IMPL_IUNKNOWN_QUERY_HEAD(AccessibleTextTearoff)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleText)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleHypertext)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mHandler)
HRESULT
AccessibleTextTearoff::addSelection(long startOffset, long endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->addSelection(startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_attributes(long offset, long *startOffset,
long *endOffset, BSTR *textAttributes)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_attributes(offset, startOffset, endOffset,
textAttributes);
}
HRESULT
AccessibleTextTearoff::get_caretOffset(long *offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_caretOffset(offset);
}
HRESULT
AccessibleTextTearoff::get_characterExtents(long offset,
enum IA2CoordinateType coordType,
long *x, long *y, long *width,
long *height)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_characterExtents(offset, coordType, x, y, width,
height);
}
HRESULT
AccessibleTextTearoff::get_nSelections(long *nSelections)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_nSelections(nSelections);
}
HRESULT
AccessibleTextTearoff::get_offsetAtPoint(long x, long y,
enum IA2CoordinateType coordType,
long *offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_offsetAtPoint(x, y, coordType, offset);
}
HRESULT
AccessibleTextTearoff::get_selection(long selectionIndex, long *startOffset,
long *endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_selection(selectionIndex, startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_text(long startOffset, long endOffset, BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_text(startOffset, endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textBeforeOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textBeforeOffset(offset, boundaryType, startOffset,
endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textAfterOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textAfterOffset(offset, boundaryType,
startOffset, endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textAtOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textAtOffset(offset, boundaryType, startOffset,
endOffset, text);
}
HRESULT
AccessibleTextTearoff::removeSelection(long selectionIndex)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->removeSelection(selectionIndex);
}
HRESULT
AccessibleTextTearoff::setCaretOffset(long offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->setCaretOffset(offset);
}
HRESULT
AccessibleTextTearoff::setSelection(long selectionIndex, long startOffset,
long endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->setSelection(selectionIndex, startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_nCharacters(long *nCharacters)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_nCharacters(nCharacters);
}
HRESULT
AccessibleTextTearoff::scrollSubstringTo(long startIndex, long endIndex,
enum IA2ScrollType scrollType)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->scrollSubstringTo(startIndex, endIndex, scrollType);
}
HRESULT
AccessibleTextTearoff::scrollSubstringToPoint(long startIndex, long endIndex,
enum IA2CoordinateType coordinateType,
long x, long y)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->scrollSubstringToPoint(startIndex, endIndex,
coordinateType, x, y);
}
HRESULT
AccessibleTextTearoff::get_newText(IA2TextSegment *newText)
{
if (!newText) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetSingleton());
MOZ_ASSERT(ctl);
if (!ctl) {
return S_OK;
}
long id;
HRESULT hr = mHandler->get_uniqueID(&id);
if (FAILED(hr)) {
return hr;
}
return ctl->GetNewText(id, WrapNotNull(newText));
}
HRESULT
AccessibleTextTearoff::get_oldText(IA2TextSegment *oldText)
{
if (!oldText) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetSingleton());
MOZ_ASSERT(ctl);
if (!ctl) {
return S_OK;
}
long id;
HRESULT hr = mHandler->get_uniqueID(&id);
if (FAILED(hr)) {
return hr;
}
return ctl->GetOldText(id, WrapNotNull(oldText));
}
HRESULT
AccessibleTextTearoff::get_nHyperlinks(long *hyperlinkCount)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_nHyperlinks(hyperlinkCount);
}
HRESULT
AccessibleTextTearoff::get_hyperlink(long index,
IAccessibleHyperlink **hyperlink)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_hyperlink(index, hyperlink);
}
HRESULT
AccessibleTextTearoff::get_hyperlinkIndex(long charIndex, long *hyperlinkIndex)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_hyperlinkIndex(charIndex, hyperlinkIndex);
}
} // namespace a11y
} // namespace mozilla

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

@ -0,0 +1,88 @@
/* -*- 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_AccessibleTextTearoff_h
#define mozilla_a11y_AccessibleTextTearoff_h
#include "AccessibleHandler.h"
#include "AccessibleHypertext.h"
#include "IUnknownImpl.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class AccessibleTextTearoff final : public IAccessibleHypertext
{
public:
explicit AccessibleTextTearoff(AccessibleHandler* aHandler);
DECL_IUNKNOWN
// IAccessibleText
STDMETHODIMP addSelection(long startOffset, long endOffset) override;
STDMETHODIMP get_attributes(long offset, long *startOffset, long *endOffset,
BSTR *textAttributes) override;
STDMETHODIMP get_caretOffset(long *offset) override;
STDMETHODIMP get_characterExtents(long offset,
enum IA2CoordinateType coordType, long *x,
long *y, long *width, long *height) override;
STDMETHODIMP get_nSelections(long *nSelections) override;
STDMETHODIMP get_offsetAtPoint(long x, long y,
enum IA2CoordinateType coordType,
long *offset) override;
STDMETHODIMP get_selection(long selectionIndex, long *startOffset,
long *endOffset) override;
STDMETHODIMP get_text(long startOffset, long endOffset, BSTR *text) override;
STDMETHODIMP get_textBeforeOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP get_textAfterOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP get_textAtOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP removeSelection(long selectionIndex) override;
STDMETHODIMP setCaretOffset(long offset) override;
STDMETHODIMP setSelection(long selectionIndex, long startOffset,
long endOffset) override;
STDMETHODIMP get_nCharacters(long *nCharacters) override;
STDMETHODIMP scrollSubstringTo(long startIndex, long endIndex,
enum IA2ScrollType scrollType) override;
STDMETHODIMP scrollSubstringToPoint(long startIndex, long endIndex,
enum IA2CoordinateType coordinateType,
long x, long y) override;
STDMETHODIMP get_newText(IA2TextSegment *newText) override;
STDMETHODIMP get_oldText(IA2TextSegment *oldText) override;
// IAccessibleHypertext
STDMETHODIMP get_nHyperlinks(long *hyperlinkCount) override;
STDMETHODIMP get_hyperlink(long index,
IAccessibleHyperlink **hyperlink) override;
STDMETHODIMP get_hyperlinkIndex(long charIndex, long *hyperlinkIndex) override;
private:
~AccessibleTextTearoff() = default;
HRESULT ResolveAccText();
HRESULT ResolveAccHypertext();
RefPtr<AccessibleHandler> mHandler;
RefPtr<IAccessibleText> mAccTextProxy;
RefPtr<IAccessibleHypertext> mAccHypertextProxy;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_AccessibleTextTearoff_h

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

@ -9,6 +9,8 @@
import "ocidl.idl";
import "ServProv.idl";
import "AccessibleText.idl";
typedef struct _IA2Data
{
long mUniqueId;
@ -84,6 +86,9 @@ interface HandlerData
interface IHandlerControl : IUnknown
{
HRESULT Invalidate();
HRESULT OnTextChange([in] long aHwnd, [in] long aIA2UniqueId,
[in] VARIANT_BOOL aIsInsert,
[in] IA2TextSegment* aText);
}
[object,

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

@ -20,6 +20,7 @@ SOURCES += [
'!HandlerData_p.c',
'AccessibleHandler.cpp',
'AccessibleHandlerControl.cpp',
'AccessibleTextTearoff.cpp',
]
GENERATED_FILES += [

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

@ -43,6 +43,7 @@
#include "nsArrayUtils.h"
#include "mozilla/Preferences.h"
#include "nsIXULRuntime.h"
#include "mozilla/mscom/AsyncInvoker.h"
#include "oleacc.h"
@ -1627,3 +1628,60 @@ AccessibleWrap::SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl)
sHandlerControllers->AppendElement(Move(ctrlData));
}
bool
AccessibleWrap::DispatchTextChangeToHandler(bool aIsInsert,
const nsString& aText,
int32_t aStart, uint32_t aLen)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!sHandlerControllers || sHandlerControllers->IsEmpty()) {
return false;
}
HWND hwnd = GetHWNDFor(this);
MOZ_ASSERT(hwnd);
if (!hwnd) {
return false;
}
long msaaId = GetChildIDFor(this);
DWORD ourPid = ::GetCurrentProcessId();
// The handler ends up calling NotifyWinEvent, which should only be done once
// since it broadcasts the same event to every process who is subscribed.
// OTOH, if our chrome process contains a handler, we should prefer to
// broadcast the event from that process, as we want any DLLs injected by ATs
// to receive the event synchronously. Otherwise we simply choose the first
// handler in the list, for the lack of a better heuristic.
nsTArray<HandlerControllerData>::index_type ctrlIndex =
sHandlerControllers->IndexOf(ourPid);
if (ctrlIndex == nsTArray<HandlerControllerData>::NoIndex) {
ctrlIndex = 0;
}
HandlerControllerData& controller = sHandlerControllers->ElementAt(ctrlIndex);
MOZ_ASSERT(controller.mPid);
MOZ_ASSERT(controller.mCtrl);
VARIANT_BOOL isInsert = aIsInsert ? VARIANT_TRUE : VARIANT_FALSE;
IA2TextSegment textSegment{::SysAllocStringLen(aText.get(), aText.Length()),
aStart, static_cast<long>(aLen)};
ASYNC_INVOKER_FOR(IHandlerControl) invoker(controller.mCtrl,
Some(controller.mIsProxy));
HRESULT hr = ASYNC_INVOKE(invoker, OnTextChange, PtrToLong(hwnd), msaaId,
isInsert, &textSegment);
::SysFreeString(textSegment.text);
return SUCCEEDED(hr);
}

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

@ -192,6 +192,8 @@ public: // construction, destruction
static void SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl);
bool DispatchTextChangeToHandler(bool aIsInsert, const nsString& aText,
int32_t aStart, uint32_t aLen);
protected:
virtual ~AccessibleWrap();

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

@ -131,18 +131,7 @@ DocAccessibleWrap::GetNativeWindow() const
return nullptr;
}
HWND hWnd = ipcDoc->GetEmulatedWindowHandle();
if (hWnd) {
return hWnd;
}
auto tab = static_cast<dom::TabChild*>(ipcDoc->Manager());
MOZ_ASSERT(tab);
if (!tab) {
return nullptr;
}
return reinterpret_cast<HWND>(tab->GetNativeWindowHandle());
return ipcDoc->GetNativeWindowHandle();
} else if (mHWND) {
return mHWND;
}

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

@ -132,6 +132,14 @@ a11y::ProxyTextChangeEvent(ProxyAccessible* aText, const nsString& aStr,
return;
}
static const bool useHandler =
Preferences::GetBool("accessibility.handler.enabled", false);
if (useHandler) {
wrapper->DispatchTextChangeToHandler(aInsert, aStr, aStart, aLen);
return;
}
auto text = static_cast<HyperTextAccessibleWrap*>(wrapper->AsHyperText());
if (text) {
ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen);

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

@ -11,58 +11,8 @@ const prefs = require("../preferences/service");
const { Cu, Cc, Ci } = require("chrome");
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
/**
* Gets the currently selected locale for display.
* Gets all usable locale that we can use sorted by priority of relevance
* @return Array of locales, begins with highest priority
*/
const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
const PREF_SELECTED_LOCALE = "general.useragent.locale";
const PREF_ACCEPT_LANGUAGES = "intl.accept_languages";
function getPreferedLocales(caseSensitve) {
let locales = [];
function addLocale(locale) {
locale = locale.trim();
if (!caseSensitve)
locale = locale.toLowerCase();
if (locales.indexOf(locale) === -1)
locales.push(locale);
}
// Most important locale is OS one. But we use it, only if
// "intl.locale.matchOS" pref is set to `true`.
// Currently only used for multi-locales mobile builds.
// http://mxr.mozilla.org/mozilla-central/source/mobile/android/installer/Makefile.in#46
if (prefs.get(PREF_MATCH_OS_LOCALE, false)) {
let localeService = Cc["@mozilla.org/intl/nslocaleservice;1"].
getService(Ci.nsILocaleService);
let osLocale = localeService.getLocaleComponentForUserAgent();
addLocale(osLocale);
}
// In some cases, mainly on Fennec and on Linux version,
// `general.useragent.locale` is a special 'localized' value, like:
// "chrome://global/locale/intl.properties"
let browserUiLocale = prefs.getLocalized(PREF_SELECTED_LOCALE, "") ||
prefs.get(PREF_SELECTED_LOCALE, "");
if (browserUiLocale)
addLocale(browserUiLocale);
// Third priority is the list of locales used for web content
let contentLocales = prefs.getLocalized(PREF_ACCEPT_LANGUAGES, "") ||
prefs.get(PREF_ACCEPT_LANGUAGES, "");
if (contentLocales) {
// This list is a string of locales seperated by commas.
// There is spaces after commas, so strip each item
for (let locale of contentLocales.split(","))
addLocale(locale.replace(/(^\s+)|(\s+$)/g, ""));
}
// Finally, we ensure that en-US is the final fallback if it wasn't added
addLocale("en-US");
return locales;
return Services.locale.getRequestedLocales();
}
exports.getPreferedLocales = getPreferedLocales;

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

@ -2,128 +2,7 @@
* 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/. */
const { getPreferedLocales, findClosestLocale } = require("sdk/l10n/locale");
const prefs = require("sdk/preferences/service");
const { Cc, Ci, Cu } = require("chrome");
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
const BundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
const PREF_SELECTED_LOCALE = "general.useragent.locale";
const PREF_ACCEPT_LANGUAGES = "intl.accept_languages";
function assertPrefered(assert, expected, msg) {
assert.equal(JSON.stringify(getPreferedLocales()), JSON.stringify(expected),
msg);
}
exports.testGetPreferedLocales = function(assert) {
prefs.set(PREF_MATCH_OS_LOCALE, false);
prefs.set(PREF_SELECTED_LOCALE, "");
prefs.set(PREF_ACCEPT_LANGUAGES, "");
assertPrefered(assert, ["en-us"],
"When all preferences are empty, we only have en-us");
prefs.set(PREF_SELECTED_LOCALE, "fr");
prefs.set(PREF_ACCEPT_LANGUAGES, "jp");
assertPrefered(assert, ["fr", "jp", "en-us"],
"We first have useragent locale, then web one and finally en-US");
prefs.set(PREF_SELECTED_LOCALE, "en-US");
prefs.set(PREF_ACCEPT_LANGUAGES, "en-US");
assertPrefered(assert, ["en-us"],
"We do not have duplicates");
prefs.set(PREF_SELECTED_LOCALE, "en-US");
prefs.set(PREF_ACCEPT_LANGUAGES, "fr");
assertPrefered(assert, ["en-us", "fr"],
"en-US can be first if specified by higher priority preference");
// Reset what we changed
prefs.reset(PREF_MATCH_OS_LOCALE);
prefs.reset(PREF_SELECTED_LOCALE);
prefs.reset(PREF_ACCEPT_LANGUAGES);
}
// In some cases, mainly on Fennec and on Linux version,
// `general.useragent.locale` is a special 'localized' value, like:
// "chrome://global/locale/intl.properties"
exports.testPreferedLocalizedLocale = function(assert) {
prefs.set(PREF_MATCH_OS_LOCALE, false);
let bundleURL = "chrome://global/locale/intl.properties";
prefs.setLocalized(PREF_SELECTED_LOCALE, bundleURL);
let contentLocale = "ja";
prefs.set(PREF_ACCEPT_LANGUAGES, contentLocale);
// Read manually the expected locale value from the property file
let expectedLocale = BundleService.createBundle(bundleURL).
GetStringFromName(PREF_SELECTED_LOCALE).
toLowerCase();
// First add the useragent locale
let expectedLocaleList = [expectedLocale];
// Then the content locale
if (expectedLocaleList.indexOf(contentLocale) == -1)
expectedLocaleList.push(contentLocale);
// Add default "en-us" fallback if the main language is not already en-us
if (expectedLocaleList.indexOf("en-us") == -1)
expectedLocaleList.push("en-us");
assertPrefered(assert, expectedLocaleList, "test localized pref value");
// Reset what we have changed
prefs.reset(PREF_MATCH_OS_LOCALE);
prefs.reset(PREF_SELECTED_LOCALE);
prefs.reset(PREF_ACCEPT_LANGUAGES);
}
// On Linux the PREF_ACCEPT_LANGUAGES pref can be a localized pref.
exports.testPreferedContentLocale = function(assert) {
prefs.set(PREF_MATCH_OS_LOCALE, false);
let noLocale = "",
bundleURL = "chrome://global/locale/intl.properties";
prefs.set(PREF_SELECTED_LOCALE, noLocale);
prefs.setLocalized(PREF_ACCEPT_LANGUAGES, bundleURL);
// Read the expected locale values from the property file
let expectedLocaleList = BundleService.createBundle(bundleURL).
GetStringFromName(PREF_ACCEPT_LANGUAGES).
split(",").
map(locale => locale.trim().toLowerCase());
// Add default "en-us" fallback if the main language is not already en-us
if (expectedLocaleList.indexOf("en-us") == -1)
expectedLocaleList.push("en-us");
assertPrefered(assert, expectedLocaleList, "test localized content locale pref value");
// Reset what we have changed
prefs.reset(PREF_MATCH_OS_LOCALE);
prefs.reset(PREF_SELECTED_LOCALE);
prefs.reset(PREF_ACCEPT_LANGUAGES);
}
exports.testPreferedOsLocale = function(assert) {
prefs.set(PREF_MATCH_OS_LOCALE, true);
prefs.set(PREF_SELECTED_LOCALE, "");
prefs.set(PREF_ACCEPT_LANGUAGES, "");
let expectedLocale = Services.locale.getAppLocaleAsLangTag().toLowerCase();
let expectedLocaleList = [expectedLocale];
// Add default "en-us" fallback if the main language is not already en-us
if (expectedLocale != "en-us")
expectedLocaleList.push("en-us");
assertPrefered(assert, expectedLocaleList, "Ensure that we select OS locale when related preference is set");
// Reset what we have changed
prefs.reset(PREF_MATCH_OS_LOCALE);
prefs.reset(PREF_SELECTED_LOCALE);
prefs.reset(PREF_ACCEPT_LANGUAGES);
}
const { findClosestLocale } = require("sdk/l10n/locale");
exports.testFindClosestLocale = function(assert) {
// Second param of findClosestLocale (aMatchLocales) have to be in lowercase

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

@ -414,15 +414,6 @@ pref("media.realtime_decoder.enabled", true);
// TCPSocket
pref("dom.mozTCPSocket.enabled", true);
// "Preview" landing of bug 710563, which is bogged down in analysis
// of talos regression. This is a needed change for higher-framerate
// CSS animations, and incidentally works around an apparent bug in
// our handling of requestAnimationFrame() listeners, which are
// supposed to enable this REPEATING_PRECISE_CAN_SKIP behavior. The
// secondary bug isn't really worth investigating since it's obseleted
// by bug 710563.
pref("layout.frame_rate.precise", true);
// Handle hardware buttons in the b2g chrome package
pref("b2g.keys.menu.enabled", true);

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

@ -576,11 +576,20 @@
return true;
},
_isForInitialAboutBlank(aWebProgress, aLocation) {
_isForInitialAboutBlank(aWebProgress, aStateFlags, aLocation) {
if (!this.mBlank || !aWebProgress.isTopLevel) {
return false;
}
// If the state has STATE_STOP, and no requests were in flight, then this
// must be the initial "stop" for the initial about:blank document.
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
if (aStateFlags & nsIWebProgressListener.STATE_STOP &&
this.mRequestCount == 0 &&
!aLocation) {
return true;
}
let location = aLocation ? aLocation.spec : "";
return location == "about:blank";
},
@ -623,7 +632,9 @@
originalLocation = aRequest.originalURI;
} catch (ex) {}
let ignoreBlank = this._isForInitialAboutBlank(aWebProgress, location);
let ignoreBlank = this._isForInitialAboutBlank(aWebProgress, aStateFlags,
location);
// If we were ignoring some messages about the initial about:blank, and we
// got the STATE_STOP for it, we'll want to pay attention to those messages
// from here forward. Similarly, if we conclude that this state change

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

@ -59,6 +59,7 @@ add_task(function* test_setup_html() {
let videoIframe = doc.querySelector("#test-video-in-iframe");
let video = videoIframe.contentDocument.querySelector("video");
let awaitPause = ContentTaskUtils.waitForEvent(video, "pause");
yield ContentTaskUtils.waitForCondition(() => !video.paused, "Making sure video is playing before calling pause");
video.pause();
yield awaitPause;
@ -66,6 +67,7 @@ add_task(function* test_setup_html() {
// media documents always use a <video> tag.
let audio = audioIframe.contentDocument.querySelector("video");
awaitPause = ContentTaskUtils.waitForEvent(audio, "pause");
yield ContentTaskUtils.waitForCondition(() => !audio.paused, "Making sure audio is playing before calling pause");
audio.pause();
yield awaitPause;
});

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

@ -19,11 +19,14 @@
#include "nsCOMArray.h"
#include "nsDirectoryServiceUtils.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/intl/LocaleService.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
#include "nsIPrefLocalizedString.h"
using mozilla::intl::LocaleService;
namespace mozilla {
namespace browser {
@ -125,31 +128,18 @@ AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
}
// we didn't have a defaultLocale, use the user agent locale
nsCString locale;
nsCOMPtr<nsIPrefLocalizedString> prefString;
rv = prefs->GetComplexValue("general.useragent.locale",
NS_GET_IID(nsIPrefLocalizedString),
getter_AddRefs(prefString));
if (NS_SUCCEEDED(rv)) {
nsAutoString wLocale;
prefString->GetData(getter_Copies(wLocale));
CopyUTF16toUTF8(wLocale, locale);
} else {
rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
}
nsAutoCString locale;
LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale);
nsCOMPtr<nsIFile> curLocalePlugins;
rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFile> curLocalePlugins;
rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins));
if (NS_SUCCEEDED(rv)) {
curLocalePlugins->AppendNative(locale);
rv = curLocalePlugins->Exists(&exists);
if (NS_SUCCEEDED(rv) && exists) {
array.AppendObject(curLocalePlugins);
return; // all done
}
curLocalePlugins->AppendNative(locale);
rv = curLocalePlugins->Exists(&exists);
if (NS_SUCCEEDED(rv) && exists) {
array.AppendObject(curLocalePlugins);
return; // all done
}
}
}

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

@ -57,7 +57,7 @@ DistributionCustomizer.prototype = {
},
get _locale() {
let locale = this._prefs.getCharPref("general.useragent.locale", "en-US");
const locale = Services.locale.getRequestedLocale() || "en-US";
this.__defineGetter__("_locale", () => locale);
return this._locale;
},

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

@ -62,6 +62,37 @@ this.sessions = class extends ExtensionAPI {
return Promise.resolve(getRecentlyClosed(maxResults, extension));
},
forgetClosedTab: function(windowId, sessionId) {
let window = context.extension.windowManager.get(windowId).window;
let closedTabData = SessionStore.getClosedTabData(window, false);
let closedTabIndex = closedTabData.findIndex((closedTab) => {
return closedTab.closedId === parseInt(sessionId, 10);
});
if (closedTabIndex < 0) {
return Promise.reject({message: `Could not find closed tab using sessionId ${sessionId}.`});
}
SessionStore.forgetClosedTab(window, closedTabIndex);
return Promise.resolve();
},
forgetClosedWindow: function(sessionId) {
let closedWindowData = SessionStore.getClosedWindowData(false);
let closedWindowIndex = closedWindowData.findIndex((closedWindow) => {
return closedWindow.closedId === parseInt(sessionId, 10);
});
if (closedWindowIndex < 0) {
return Promise.reject({message: `Could not find closed window using sessionId ${sessionId}.`});
}
SessionStore.forgetClosedWindow(closedWindowIndex);
return Promise.resolve();
},
restore: function(sessionId) {
let session, closedId;
if (sessionId) {

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

@ -99,11 +99,15 @@ this.tabs = class extends ExtensionAPI {
let self = {
tabs: {
onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
let nativeTab = event.originalTarget;
let tabId = tabTracker.getId(nativeTab);
let windowId = windowTracker.getId(nativeTab.ownerGlobal);
fire.async({tabId, windowId});
onActivated: new SingletonEventManager(context, "tabs.onActivated", fire => {
let listener = (eventName, event) => {
fire.async(event);
};
tabTracker.on("tab-activated", listener);
return () => {
tabTracker.off("tab-activated", listener);
};
}).api(),
onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
@ -123,11 +127,15 @@ this.tabs = class extends ExtensionAPI {
* the tabId in an array to match the API.
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
*/
onHighlighted: new WindowEventManager(context, "tabs.onHighlighted", "TabSelect", (fire, event) => {
let nativeTab = event.originalTarget;
let tabIds = [tabTracker.getId(nativeTab)];
let windowId = windowTracker.getId(nativeTab.ownerGlobal);
fire.async({tabIds, windowId});
onHighlighted: new SingletonEventManager(context, "tabs.onHighlighted", fire => {
let listener = (eventName, event) => {
fire.async({tabIds: [event.tabId], windowId: event.windowId});
};
tabTracker.on("tab-activated", listener);
return () => {
tabTracker.off("tab-activated", listener);
};
}).api(),
onAttached: new SingletonEventManager(context, "tabs.onAttached", fire => {

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

@ -155,6 +155,7 @@ class TabTracker extends TabTrackerBase {
windowTracker.addListener("TabClose", this);
windowTracker.addListener("TabOpen", this);
windowTracker.addListener("TabSelect", this);
windowTracker.addOpenListener(this._handleWindowOpen);
windowTracker.addCloseListener(this._handleWindowClose);
@ -262,6 +263,14 @@ class TabTracker extends TabTrackerBase {
this.emitRemoved(nativeTab, false);
}
break;
case "TabSelect":
// Because we are delaying calling emitCreated above, we also need to
// delay sending this event because it shouldn't fire before onCreated.
Promise.resolve().then(() => {
this.emitActivated(nativeTab);
});
break;
}
}
@ -307,6 +316,9 @@ class TabTracker extends TabTrackerBase {
for (let nativeTab of window.gBrowser.tabs) {
this.emitCreated(nativeTab);
}
// emitActivated to trigger tab.onActivated/tab.onHighlighted for a newly opened window.
this.emitActivated(window.gBrowser.tabs[0]);
}
}
@ -328,6 +340,19 @@ class TabTracker extends TabTrackerBase {
}
}
/**
* Emits a "tab-activated" event for the given tab element.
*
* @param {NativeTab} nativeTab
* The tab element which has been activated.
* @private
*/
emitActivated(nativeTab) {
this.emit("tab-activated", {
tabId: this.getId(nativeTab),
windowId: windowTracker.getId(nativeTab.ownerGlobal)});
}
/**
* Emits a "tab-attached" event for the given tab element.
*

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

@ -55,6 +55,37 @@
}
],
"functions": [
{
"name": "forgetClosedTab",
"type": "function",
"description": "Forget a recently closed tab.",
"async": true,
"parameters": [
{
"name": "windowId",
"type": "integer",
"description": "The windowId of the window to which the recently closed tab to be forgotten belongs."
},
{
"name": "sessionId",
"type": "string",
"description": "The sessionId (closedId) of the recently closed tab to be forgotten."
}
]
},
{
"name": "forgetClosedWindow",
"type": "function",
"description": "Forget a recently closed window.",
"async": true,
"parameters": [
{
"name": "sessionId",
"type": "string",
"description": "The sessionId (closedId) of the recently closed window to be forgotten."
}
]
},
{
"name": "getRecentlyClosed",
"type": "function",

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

@ -82,6 +82,8 @@ support-files =
[browser_ext_runtime_openOptionsPage.js]
[browser_ext_runtime_openOptionsPage_uninstall.js]
[browser_ext_runtime_setUninstallURL.js]
[browser_ext_sessions_forgetClosedTab.js]
[browser_ext_sessions_forgetClosedWindow.js]
[browser_ext_sessions_getRecentlyClosed.js]
[browser_ext_sessions_getRecentlyClosed_private.js]
[browser_ext_sessions_getRecentlyClosed_tabs.js]
@ -102,6 +104,7 @@ support-files =
[browser_ext_tabs_executeScript.js]
[browser_ext_tabs_executeScript_good.js]
[browser_ext_tabs_executeScript_bad.js]
[browser_ext_tabs_executeScript_multiple.js]
[browser_ext_tabs_executeScript_no_create.js]
[browser_ext_tabs_executeScript_runAt.js]
[browser_ext_tabs_getCurrent.js]

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

@ -0,0 +1,70 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* test_sessions_forget_closed_tab() {
function background() {
browser.test.onMessage.addListener((msg, windowId, sessionId) => {
if (msg === "check-sessions") {
browser.sessions.getRecentlyClosed().then(recentlyClosed => {
browser.test.sendMessage("recentlyClosed", recentlyClosed);
});
} else if (msg === "forget-tab") {
browser.sessions.forgetClosedTab(windowId, sessionId).then(
() => {
browser.test.sendMessage("forgot-tab");
},
error => {
browser.test.assertEq(error.message,
`Could not find closed tab using sessionId ${sessionId}.`);
browser.test.sendMessage("forget-reject");
}
);
}
});
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["sessions", "tabs"],
},
background,
});
yield extension.startup();
let tabUrl = "http://example.com";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl);
yield BrowserTestUtils.removeTab(tab);
tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl);
yield BrowserTestUtils.removeTab(tab);
extension.sendMessage("check-sessions");
let recentlyClosed = yield extension.awaitMessage("recentlyClosed");
let recentlyClosedLength = recentlyClosed.length;
let recentlyClosedTab = recentlyClosed[0].tab;
// Check that forgetting a tab works properly
extension.sendMessage("forget-tab", recentlyClosedTab.windowId,
recentlyClosedTab.sessionId);
yield extension.awaitMessage("forgot-tab");
extension.sendMessage("check-sessions");
let remainingClosed = yield extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1,
"One tab was forgotten.");
is(remainingClosed[0].tab.sessionId, recentlyClosed[1].tab.sessionId,
"The correct tab was forgotten.");
// Check that re-forgetting the same tab fails properly
extension.sendMessage("forget-tab", recentlyClosedTab.windowId,
recentlyClosedTab.sessionId);
yield extension.awaitMessage("forget-reject");
extension.sendMessage("check-sessions");
remainingClosed = yield extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1,
"No extra tab was forgotten.");
is(remainingClosed[0].tab.sessionId, recentlyClosed[1].tab.sessionId,
"The correct tab remains.");
yield extension.unload();
});

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

@ -0,0 +1,72 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* test_sessions_forget_closed_window() {
function* openAndCloseWindow(url = "http://example.com") {
let win = yield BrowserTestUtils.openNewBrowserWindow();
yield BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, url);
yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
yield BrowserTestUtils.closeWindow(win);
}
function background() {
browser.test.onMessage.addListener((msg, sessionId) => {
if (msg === "check-sessions") {
browser.sessions.getRecentlyClosed().then(recentlyClosed => {
browser.test.sendMessage("recentlyClosed", recentlyClosed);
});
} else if (msg === "forget-window") {
browser.sessions.forgetClosedWindow(sessionId).then(
() => {
browser.test.sendMessage("forgot-window");
},
error => {
browser.test.assertEq(error.message,
`Could not find closed window using sessionId ${sessionId}.`);
browser.test.sendMessage("forget-reject");
}
);
}
});
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["sessions", "tabs"],
},
background,
});
yield extension.startup();
yield openAndCloseWindow("about:config");
yield openAndCloseWindow("about:robots");
extension.sendMessage("check-sessions");
let recentlyClosed = yield extension.awaitMessage("recentlyClosed");
let recentlyClosedLength = recentlyClosed.length;
let recentlyClosedWindow = recentlyClosed[0].window;
// Check that forgetting a window works properly
extension.sendMessage("forget-window", recentlyClosedWindow.sessionId);
yield extension.awaitMessage("forgot-window");
extension.sendMessage("check-sessions");
let remainingClosed = yield extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1,
"One window was forgotten.");
is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId,
"The correct window was forgotten.");
// Check that re-forgetting the same window fails properly
extension.sendMessage("forget-window", recentlyClosedWindow.sessionId);
yield extension.awaitMessage("forget-reject");
extension.sendMessage("check-sessions");
remainingClosed = yield extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1,
"No extra window was forgotten.");
is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId,
"The correct window remains.");
yield extension.unload();
});

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

@ -0,0 +1,50 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* testExecuteScript() {
const BASE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
const URL = BASE + "file_dummy.html";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL, true);
async function background() {
try {
await browser.tabs.executeScript({code: "this.foo = 'bar'"});
await browser.tabs.executeScript({file: "script.js"});
let [result1] = await browser.tabs.executeScript({code: "[this.foo, this.bar]"});
let [result2] = await browser.tabs.executeScript({file: "script2.js"});
browser.test.assertEq("bar,baz", String(result1), "executeScript({code}) result");
browser.test.assertEq("bar,baz", String(result2), "executeScript({file}) result");
browser.test.notifyPass("executeScript-multiple");
} catch (e) {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFail("executeScript-multiple");
}
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["http://mochi.test/"],
},
background,
files: {
"script.js": function() {
this.bar = "baz";
},
"script2.js": "[this.foo, this.bar]",
},
});
yield extension.startup();
yield extension.awaitFinish("executeScript-multiple");
yield extension.unload();
yield BrowserTestUtils.removeTab(tab);
});

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

@ -25,6 +25,14 @@ add_task(function* testTabEvents() {
}
});
browser.tabs.onCreated.addListener((info) => {
if (info.id in events) {
events[info.id].push("onCreated");
} else {
events[info.id] = ["onCreated"];
}
});
browser.tabs.onHighlighted.addListener((info) => {
if (info.tabIds[0] in events) {
events[info.tabIds[0]].push("onHighlighted");
@ -43,7 +51,10 @@ add_task(function* testTabEvents() {
async function expectEvents(tabId, expectedEvents) {
browser.test.log(`Expecting events: ${expectedEvents.join(", ")}`);
await new Promise(resolve => setTimeout(resolve, 0));
// Wait up to 5000 ms for the expected number of events.
for (let i = 0; i < 50 && (!events[tabId] || events[tabId].length < expectedEvents.length); i++) {
await new Promise(resolve => setTimeout(resolve, 100));
}
browser.test.assertEq(expectedEvents.length, events[tabId].length,
`Got expected number of events for ${tabId}`);
@ -61,23 +72,58 @@ add_task(function* testTabEvents() {
* @param {number} windowId
*/
async function openTab(windowId) {
browser.test.assertEq(0, Object.keys(events).length,
"No events remaining before testing openTab.");
let tab = await browser.tabs.create({windowId});
tabIds.push(tab.id);
browser.test.log(`Opened tab ${tab.id}`);
await expectEvents(tab.id, [
"onCreated",
"onActivated",
"onHighlighted",
]);
}
/**
* Opens a new window and asserts that the correct events are fired.
*
* @param {Array} urls A list of urls for which to open tabs in the new window.
*/
async function openWindow(urls) {
browser.test.assertEq(0, Object.keys(events).length,
"No events remaining before testing openWindow.");
let window = await browser.windows.create({url: urls});
browser.test.log(`Opened new window ${window.id}`);
for (let [i] of urls.entries()) {
let tab = window.tabs[i];
tabIds.push(tab.id);
let expectedEvents = [
"onCreated",
"onActivated",
"onHighlighted",
];
if (i !== 0) {
expectedEvents.splice(1);
}
await expectEvents(window.tabs[i].id, expectedEvents);
}
}
/**
* Highlights an existing tab and asserts that the correct events are fired.
*
* @param {number} tabId
*/
async function highlightTab(tabId) {
browser.test.assertEq(0, Object.keys(events).length,
"No events remaining before testing highlightTab.");
browser.test.log(`Highlighting tab ${tabId}`);
let tab = await browser.tabs.update(tabId, {active: true});
@ -107,6 +153,15 @@ add_task(function* testTabEvents() {
highlightTab(tabIds[2]),
]);
await Promise.all([
openWindow(["http://example.com"]),
openWindow(["http://example.com", "http://example.org"]),
openWindow(["http://example.com", "http://example.org", "http://example.net"]),
]);
browser.test.assertEq(0, Object.keys(events).length,
"No events remaining after tests.");
await Promise.all(tabIds.map(id => browser.tabs.remove(id)));
browser.test.notifyPass("tabs.highlight");

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

@ -133,7 +133,8 @@ function* runTests(options) {
});
});
yield SpecialPowers.pushPrefEnv({set: [["general.useragent.locale", "es-ES"]]});
let reqLoc = Services.locale.getRequestedLocales();
Services.locale.setRequestedLocales(["es-ES"]);
yield extension.startup();
@ -141,7 +142,7 @@ function* runTests(options) {
yield extension.unload();
yield SpecialPowers.popPrefEnv();
Services.locale.setRequestedLocales(reqLoc);
let node = document.getElementById(pageActionId);
is(node, null, "pageAction image removed from document");

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

@ -109,7 +109,13 @@ this.SiteDataManager = {
},
_updateAppCache() {
let groups = this._appCache.getGroups();
let groups = null;
try {
groups = this._appCache.getGroups();
} catch (e) {
return;
}
for (let site of this._sites.values()) {
for (let group of groups) {
let uri = Services.io.newURI(group);

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

@ -12,17 +12,22 @@ function test() {
"browser.cache.disk.enable",
"browser.cache.memory.enable",
];
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
// Adding one fake site so that the SiteDataManager would run.
// Otherwise, without any site then it would just return so we would end up in not testing SiteDataManager.
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://www.foo.com");
Services.perms.addFromPrincipal(principal, "persistent-storage", Ci.nsIPermissionManager.ALLOW_ACTION);
registerCleanupFunction(function() {
for (let pref of prefs) {
Services.prefs.clearUserPref(pref);
}
Services.perms.removeFromPrincipal(principal, "persistent-storage");
});
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
open_preferences(runTest);
}
@ -31,6 +36,7 @@ function runTest(win) {
let tab = win.document;
let elements = tab.getElementById("mainPrefPane").children;
let offlineGroupDisabled = !SpecialPowers.getBoolPref("browser.preferences.offlineGroup.enabled");
// Test if advanced pane is opened correctly
win.gotoPref("paneAdvanced");
@ -38,6 +44,13 @@ function runTest(win) {
if (element.nodeName == "preferences") {
continue;
}
// The siteDataGroup in the Storage Management project will replace the offlineGroup eventually,
// so during the transition period, we have to check the pref to see if the offlineGroup
// should be hidden always. See the bug 1354530 for the details.
if (element.id == "offlineGroup" && offlineGroupDisabled) {
is_element_hidden(element, "Disabled offlineGroup should be hidden");
continue;
}
let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneAdvanced") {
is_element_visible(element, "Advanced elements should be visible");

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

@ -1,8 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
const { interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
function test() {
waitForExplicitFinish();
@ -12,17 +13,22 @@ function test() {
"browser.cache.disk.enable",
"browser.cache.memory.enable",
];
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
// Adding one fake site so that the SiteDataManager would run.
// Otherwise, without any site then it would just return so we would end up in not testing SiteDataManager.
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://www.foo.com");
Services.perms.addFromPrincipal(principal, "persistent-storage", Ci.nsIPermissionManager.ALLOW_ACTION);
registerCleanupFunction(function() {
for (let pref of prefs) {
Services.prefs.clearUserPref(pref);
}
Services.perms.removeFromPrincipal(principal, "persistent-storage");
});
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
open_preferences(runTest);
}
@ -31,18 +37,26 @@ function runTest(win) {
let tab = win.document;
let elements = tab.getElementById("mainPrefPane").children;
let offlineGroupDisabled = !SpecialPowers.getBoolPref("browser.preferences.offlineGroup.enabled");
// Test if advanced pane is opened correctly
win.gotoPref("paneAdvanced");
// Test if privacy pane is opened correctly
win.gotoPref("panePrivacy");
for (let element of elements) {
if (element.nodeName == "preferences") {
continue;
}
// The siteDataGroup in the Storage Management project will replace the offlineGroup eventually,
// so during the transition period, we have to check the pref to see if the offlineGroup
// should be hidden always. See the bug 1354530 for the details.
if (element.id == "offlineGroup" && offlineGroupDisabled) {
is_element_hidden(element, "Disabled offlineGroup should be hidden");
continue;
}
let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneAdvanced") {
is_element_visible(element, "Advanced elements should be visible");
if (attributeValue == "panePrivacy") {
is_element_visible(element, "Privacy elements should be visible");
} else {
is_element_hidden(element, "Non-Advanced elements should be hidden");
is_element_hidden(element, "Non-Privacy elements should be hidden");
}
}

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

@ -21,22 +21,7 @@ function isSubObjectOf(expectedObj, actualObj, name) {
}
function getLocale() {
const localePref = "general.useragent.locale";
return getLocalizedPref(localePref, Services.prefs.getCharPref(localePref));
}
/**
* Wrapper for nsIPrefBranch::getComplexValue.
* @param aPrefName
* The name of the pref to get.
* @returns aDefault if the requested pref doesn't exist.
*/
function getLocalizedPref(aPrefName, aDefault) {
try {
return Services.prefs.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data;
} catch (ex) {
return aDefault;
}
return Services.locale.getRequestedLocale() || undefined;
}
function promiseEvent(aTarget, aEventName, aPreventDefault) {

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

@ -12,5 +12,4 @@ ac_add_options --enable-clang-plugin
. $topsrcdir/build/win32/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -13,5 +13,4 @@ ac_add_options --enable-clang-plugin
. $topsrcdir/build/win32/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -13,5 +13,4 @@ ac_add_options --enable-clang-plugin
. $topsrcdir/build/win32/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -14,5 +14,4 @@ ac_add_options --enable-clang-plugin
. $topsrcdir/build/win64/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -15,5 +15,4 @@ ac_add_options --enable-clang-plugin
. $topsrcdir/build/win64/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -24,12 +24,12 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.xz",
"unpack": true,
"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
"size": 1020700
"digest": "770bec21b71c386a5a89c9dede3b5dfbf47f7b22d395d5e4642d9c309a44fa05bf4a3a7b6d48b0bc737eafe3e3a8ce90005dcbad51a1aba4d326d5216b29dca1",
"size": 2173064
}
]

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

@ -1,8 +1,8 @@
[
{
"version": "clang 3.8.0, libgcc 4.8.5",
"size": 140319580,
"digest": "34e219d7e8eaffa81710631c34d21355563d06335b3c00851e94c1f42f9098788fded8463dd0f67dd699f77b47a0245dd7aff754943a7a03fb5fd145a808254f",
"version": "clang 3.9.0",
"size": 166261192,
"digest": "52f3fc23f0f5c98050f8b0ac7c92a6752d067582a16f712a5a58074be98975d594f9e36249fc2be7f1cc2ca6d509c663faaf2bea66f949243cc1f41651638ba6",
"algorithm": "sha512",
"filename": "clang.tar.xz",
"unpack": true
@ -24,12 +24,12 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.xz",
"unpack": true,
"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
"size": 1020700
"digest": "770bec21b71c386a5a89c9dede3b5dfbf47f7b22d395d5e4642d9c309a44fa05bf4a3a7b6d48b0bc737eafe3e3a8ce90005dcbad51a1aba4d326d5216b29dca1",
"size": 2173064
}
]

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

@ -32,12 +32,12 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.xz",
"unpack": true,
"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
"size": 1020700
"digest": "770bec21b71c386a5a89c9dede3b5dfbf47f7b22d395d5e4642d9c309a44fa05bf4a3a7b6d48b0bc737eafe3e3a8ce90005dcbad51a1aba4d326d5216b29dca1",
"size": 2173064
}
]

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

@ -24,13 +24,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.xz",
"unpack": true,
"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
"size": 1020700
"digest": "770bec21b71c386a5a89c9dede3b5dfbf47f7b22d395d5e4642d9c309a44fa05bf4a3a7b6d48b0bc737eafe3e3a8ce90005dcbad51a1aba4d326d5216b29dca1",
"size": 2173064
},
{
"version": "clang + llvm 3.9.0, built from SVN r290136",

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

@ -16,13 +16,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "a285c7c6468ad7438262dfec90f65981e84abf2adbb1aa075c0ec1759b4f98ce5d5f14a3d555274f970704210a00738ba7d95db2fc320f7780e6b99bcb0ffb6c",
"size": 1143715
"digest": "6c93ee3ef4bcc129ade3e58629ba4be224a1dec5e1d864ba4017d1bc2a17febb0ca32e4e6d2575c8cc6e0a8235ca07be485b8c6c1cf1a0c0e91e3c23caa515b8",
"size": 1603430
},
{
"version": "cctools port from commit hash 84ce22dbb22a26ce7f392e9de0ee39c2efe6fd68",

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

@ -1,8 +1,8 @@
[
{
"version": "clang 3.8.0, libgcc 4.9.4 + PR64905",
"size": 155933720,
"digest": "7a3a9a5ff455554d120596fe4bc06c19e41ecbd1e67b1e95e778c0b8ce6d9472f30fd4a27c66d48d9c047aac7a077f23f87397711dd6f33175f95cf4a2ada862",
"version": "clang 3.9.0",
"size": 166261192,
"digest": "52f3fc23f0f5c98050f8b0ac7c92a6752d067582a16f712a5a58074be98975d594f9e36249fc2be7f1cc2ca6d509c663faaf2bea66f949243cc1f41651638ba6",
"algorithm": "sha512",
"filename": "clang.tar.xz",
"unpack": true
@ -16,9 +16,9 @@
"unpack": true
},
{
"size": 1349196,
"size": 6075028,
"visibility": "public",
"digest": "438a36523a74cbc4a58226647e0501fa64a1b63f32931dc364a75d699df8accb45afdf26f4cb61c6ac7f58be530205acb6da22008bec19603c6f6fda3a12a8cc",
"digest": "0b962ba55a5a2fbae44218683bdf6ea0dfe8165aba436173a065f7190976184586b9acf4c23478bc5b6d81a3e00f681bf16df0536c9c9718ad0570d064f69027",
"algorithm": "sha512",
"unpack": true,
"filename": "cctools.tar.xz"

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

@ -24,13 +24,13 @@
"filename": "MacOSX10.7.sdk.tar.bz2"
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.xz",
"unpack": true,
"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
"size": 1020700
"digest": "770bec21b71c386a5a89c9dede3b5dfbf47f7b22d395d5e4642d9c309a44fa05bf4a3a7b6d48b0bc737eafe3e3a8ce90005dcbad51a1aba4d326d5216b29dca1",
"size": 2173064
},
{
"version": "https://github.com/mozilla/libdmg-hfsplus rev ba04b00435a0853f1499d751617177828ee8ec00",

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

@ -24,12 +24,12 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "a285c7c6468ad7438262dfec90f65981e84abf2adbb1aa075c0ec1759b4f98ce5d5f14a3d555274f970704210a00738ba7d95db2fc320f7780e6b99bcb0ffb6c",
"size": 1143715
"digest": "6c93ee3ef4bcc129ade3e58629ba4be224a1dec5e1d864ba4017d1bc2a17febb0ca32e4e6d2575c8cc6e0a8235ca07be485b8c6c1cf1a0c0e91e3c23caa515b8",
"size": 1603430
}
]

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

@ -14,13 +14,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e",
"size": 1179901
"digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1628305
},
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",

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

@ -14,13 +14,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e",
"size": 1179901
"digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1628305
},
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",

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

@ -14,13 +14,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e",
"size": 1179901
"digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1628305
},
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",

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

@ -15,13 +15,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e",
"size": 1179901
"digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1628305
},
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",

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

@ -15,13 +15,13 @@
"unpack": true
},
{
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
"version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512",
"visibility": "public",
"filename": "sccache2.tar.bz2",
"unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e",
"size": 1179901
"digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1628305
},
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",

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

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.8.183
Current extension version is: 1.8.229

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

@ -314,7 +314,7 @@ class ChromeActions {
}
getLocale() {
return getStringPref("general.useragent.locale", "en-US");
return Services.locale.getRequestedLocale() || "en-US";
}
getStrings(data) {

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

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

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

@ -201,6 +201,7 @@
.annotationLayer .underlineAnnotation,
.annotationLayer .squigglyAnnotation,
.annotationLayer .strikeoutAnnotation,
.annotationLayer .lineAnnotation svg line,
.annotationLayer .fileAttachmentAnnotation {
cursor: pointer;
}

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

@ -280,8 +280,7 @@ See https://github.com/adobe-type-tools/cmap-resources
<p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
</div>
<div class="row">
<!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. -->
<input id="password" class="toolbarField">
<input type="password" id="password" class="toolbarField">
</div>
<div class="buttonRow">
<button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>

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

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

@ -49,12 +49,6 @@ XPCOMUtils.defineLazyGetter(this, "gUnicodeConverter", function() {
const DIRECTORY_LINKS_FILE = "directoryLinks.json";
const DIRECTORY_LINKS_TYPE = "application/json";
// The preference that tells whether to match the OS locale
const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
// The preference that tells what locale the user selected
const PREF_SELECTED_LOCALE = "general.useragent.locale";
// The preference that tells where to obtain directory links
const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source";
@ -166,8 +160,6 @@ var DirectoryLinksProvider = {
return Object.freeze({
enhanced: PREF_NEWTAB_ENHANCED,
linksURL: PREF_DIRECTORY_SOURCE,
matchOSLocale: PREF_MATCH_OS_LOCALE,
prefSelectedLocale: PREF_SELECTED_LOCALE,
});
},
@ -188,26 +180,7 @@ var DirectoryLinksProvider = {
* @return the selected locale or "en-US" if none is selected
*/
get locale() {
let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false);
if (matchOS) {
return Cc["@mozilla.org/intl/ospreferences;1"].
getService(Ci.mozIOSPreferences).systemLocale;
}
try {
let locale = Services.prefs.getComplexValue(PREF_SELECTED_LOCALE,
Ci.nsIPrefLocalizedString);
if (locale) {
return locale.data;
}
} catch (e) {}
try {
return Services.prefs.getCharPref(PREF_SELECTED_LOCALE);
} catch (e) {}
return "en-US";
return Services.locale.getRequestedLocale() || "en-US";
},
/**
@ -236,14 +209,11 @@ var DirectoryLinksProvider = {
case this._observedPrefs.linksURL:
delete this.__linksURL;
// fallthrough
// Force directory download on changes to fetch related prefs
case this._observedPrefs.matchOSLocale:
case this._observedPrefs.prefSelectedLocale:
this._fetchAndCacheLinksIfNecessary(true);
break;
}
} else if (aTopic === "intl:requested-locales-changed") {
this._fetchAndCacheLinksIfNecessary(true);
}
},
@ -690,6 +660,7 @@ var DirectoryLinksProvider = {
init: function DirectoryLinksProvider_init() {
this._setDefaultEnhanced();
this._addPrefsObserver();
Services.obs.addObserver(this, "intl:requested-locales-changed");
// setup directory file path and last download timestamp
this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE);
this._lastDownloadMS = 0;
@ -1213,6 +1184,7 @@ var DirectoryLinksProvider = {
delete this.__linksURL;
this._removePrefsObserver();
this._removeObservers();
Services.obs.removeObserver(this, "intl:requested-locales-changed");
},
addObserver: function DirectoryLinksProvider_addObserver(aObserver) {

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

@ -34,7 +34,6 @@ const kURLData = {"directory": [{"url": "http://example.com", "title": "LocalSou
const kTestURL = "data:application/json," + JSON.stringify(kURLData);
// DirectoryLinksProvider preferences
const kLocalePref = DirectoryLinksProvider._observedPrefs.prefSelectedLocale;
const kSourceUrlPref = DirectoryLinksProvider._observedPrefs.linksURL;
const kPingUrlPref = "browser.newtabpage.directory.ping";
const kNewtabEnhancedPref = "browser.newtabpage.enhanced";
@ -51,7 +50,8 @@ const kFailURL = kBaseUrl + kFailPath;
const kPingUrl = kBaseUrl + kPingPath;
// app/profile/firefox.js are not avaialble in xpcshell: hence, preset them
Services.prefs.setCharPref(kLocalePref, "en-US");
const origReqLocales = Services.locale.getRequestedLocales();
Services.locale.setRequestedLocales(["en-US"]);
Services.prefs.setCharPref(kSourceUrlPref, kTestURL);
Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
Services.prefs.setBoolPref(kNewtabEnhancedPref, true);
@ -201,7 +201,7 @@ function promiseSetupDirectoryLinksProvider(options = {}) {
return Task.spawn(function*() {
let linksURL = options.linksURL || kTestURL;
yield DirectoryLinksProvider.init();
yield promiseDirectoryDownloadOnPrefChange(kLocalePref, options.locale || "en-US");
Services.locale.setRequestedLocales([options.locale || "en-US"]);
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, linksURL);
do_check_eq(DirectoryLinksProvider._linksURL, linksURL);
DirectoryLinksProvider._lastDownloadMS = options.lastDownloadMS || 0;
@ -210,7 +210,7 @@ function promiseSetupDirectoryLinksProvider(options = {}) {
function promiseCleanDirectoryLinksProvider() {
return Task.spawn(function*() {
yield promiseDirectoryDownloadOnPrefChange(kLocalePref, "en-US");
Services.locale.setRequestedLocales(["en-US"]);
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kTestURL);
yield DirectoryLinksProvider._clearFrequencyCap();
yield DirectoryLinksProvider._loadInadjacentSites();
@ -233,7 +233,7 @@ function run_test() {
do_register_cleanup(function() {
server.stop(function() { });
DirectoryLinksProvider.reset();
Services.prefs.clearUserPref(kLocalePref);
Services.locale.setRequestedLocales(origReqLocales);
Services.prefs.clearUserPref(kSourceUrlPref);
Services.prefs.clearUserPref(kPingUrlPref);
Services.prefs.clearUserPref(kNewtabEnhancedPref);

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

@ -13,12 +13,6 @@ const { getAbbreviatedMimeType } = require("../utils/request-utils");
const { div, span } = DOM;
const CONTENT_MIME_TYPE_ABBREVIATIONS = {
"ecmascript": "js",
"javascript": "js",
"x-javascript": "js"
};
const RequestListColumnType = createClass({
displayName: "RequestListColumnType",
@ -35,7 +29,6 @@ const RequestListColumnType = createClass({
let abbrevType;
if (mimeType) {
abbrevType = getAbbreviatedMimeType(mimeType);
abbrevType = CONTENT_MIME_TYPE_ABBREVIATIONS[abbrevType] || abbrevType;
}
return (

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

@ -6,6 +6,12 @@
"use strict";
const CONTENT_MIME_TYPE_ABBREVIATIONS = {
"ecmascript": "js",
"javascript": "js",
"x-javascript": "js"
};
/**
* Extracts any urlencoded form data sections (e.g. "?foo=bar&baz=42") from a
* POST request.
@ -112,7 +118,8 @@ function getAbbreviatedMimeType(mimeType) {
if (!mimeType) {
return "";
}
return (mimeType.split(";")[0].split("/")[1] || "").split("+")[0];
let abbrevType = (mimeType.split(";")[0].split("/")[1] || "").split("+")[0];
return CONTENT_MIME_TYPE_ABBREVIATIONS[abbrevType] || abbrevType;
}
/**

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

@ -43,6 +43,8 @@ interface nsIContentViewer : nsISupports
void loadComplete(in nsresult aStatus);
[noscript] readonly attribute boolean loadCompleted;
[noscript] readonly attribute boolean isStopped;
/**
* Checks if the document wants to prevent unloading by firing beforeunload on
* the document, and if it does, prompts the user. The result is returned.

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

@ -316,12 +316,12 @@ EffectCompositor::PostRestyleForAnimation(dom::Element* aElement,
"Restyle request during restyling should be requested only on "
"the main-thread. e.g. after the parallel traversal");
if (ServoStyleSet::IsInServoTraversal()) {
// FIXME: Bug 1302946: We will handle eRestyle_CSSTransitions.
MOZ_ASSERT(hint == eRestyle_CSSAnimations);
MOZ_ASSERT(hint == eRestyle_CSSAnimations ||
hint == eRestyle_CSSTransitions);
// We can't call Servo_NoteExplicitHints here since AtomicRefCell does not
// allow us mutate ElementData of the |aElement| in SequentialTask.
// Instead we call Servo_NoteExplicitHints for the element in PreTraverse() right
// Instead we call Servo_NoteExplicitHints for the element in PreTraverse()
// which will be called right before the second traversal that we do for
// updating CSS animations.
// In that case PreTraverse() will return true so that we know to do the
@ -982,8 +982,10 @@ EffectCompositor::PreTraverseInSubtree(Element* aRoot)
MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
bool foundElementsNeedingRestyle = false;
for (auto& elementsToRestyle : mElementsToRestyle) {
for (auto iter = elementsToRestyle.Iter(); !iter.Done(); iter.Next()) {
for (size_t i = 0; i < kCascadeLevelCount; ++i) {
CascadeLevel cascadeLevel = CascadeLevel(i);
for (auto iter = mElementsToRestyle[cascadeLevel].Iter();
!iter.Done(); iter.Next()) {
bool postedRestyle = iter.Data();
// Ignore throttled restyle.
if (!postedRestyle) {
@ -1003,7 +1005,10 @@ EffectCompositor::PreTraverseInSubtree(Element* aRoot)
// We can't call PostRestyleEvent directly here since we are still in the
// middle of the servo traversal.
mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(target.mElement, eRestyle_CSSAnimations);
PostRestyleEventForAnimations(target.mElement,
cascadeLevel == CascadeLevel::Transitions
? eRestyle_CSSTransitions
: eRestyle_CSSAnimations);
foundElementsNeedingRestyle = true;
@ -1048,14 +1053,21 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
PseudoElementHashEntry::KeyType key = { aElement, pseudoType };
for (auto& elementsToRestyle : mElementsToRestyle) {
if (!elementsToRestyle.Get(key)) {
for (size_t i = 0; i < kCascadeLevelCount; ++i) {
CascadeLevel cascadeLevel = CascadeLevel(i);
auto& elementSet = mElementsToRestyle[cascadeLevel];
if (!elementSet.Get(key)) {
// Ignore throttled restyle and no restyle request.
continue;
}
mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(aElement, eRestyle_CSSAnimations);
PostRestyleEventForAnimations(aElement,
cascadeLevel == CascadeLevel::Transitions
? eRestyle_CSSTransitions
: eRestyle_CSSAnimations);
EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
if (effects) {
@ -1066,7 +1078,7 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
}
}
elementsToRestyle.Remove(key);
elementSet.Remove(key);
found = true;
}
return found;

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

@ -142,6 +142,25 @@ protected:
virtual bool IncludeInContext(nsINode *aNode);
class MOZ_STACK_CLASS AutoReleaseDocumentIfNeeded final
{
public:
explicit AutoReleaseDocumentIfNeeded(nsDocumentEncoder* aEncoder)
: mEncoder(aEncoder)
{
}
~AutoReleaseDocumentIfNeeded()
{
if (mEncoder->mFlags & RequiresReinitAfterOutput) {
mEncoder->mDocument = nullptr;
}
}
private:
nsDocumentEncoder* mEncoder;
};
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsISelection> mSelection;
RefPtr<nsRange> mRange;
@ -1009,6 +1028,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
if (!mDocument)
return NS_ERROR_NOT_INITIALIZED;
AutoReleaseDocumentIfNeeded autoReleaseDocument(this);
aOutputString.Truncate();
nsString output;

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

@ -5507,7 +5507,7 @@ nsGlobalWindow::GetInnerSize(CSSIntSize& aSize)
{
MOZ_ASSERT(IsOuterWindow());
EnsureSizeUpToDate();
EnsureSizeAndPositionUpToDate();
NS_ENSURE_STATE(mDocShell);
@ -5983,10 +5983,7 @@ nsGlobalWindow::GetInnerScreenRect()
return nsRect();
}
nsGlobalWindow* rootWindow = nsGlobalWindow::Cast(GetPrivateRoot());
if (rootWindow) {
rootWindow->FlushPendingNotifications(FlushType::Layout);
}
EnsureSizeAndPositionUpToDate();
if (!mDocShell) {
return nsRect();
@ -6463,7 +6460,7 @@ nsGlobalWindow::GetScrollXY(bool aDoFlush)
if (aDoFlush) {
FlushPendingNotifications(FlushType::Layout);
} else {
EnsureSizeUpToDate();
EnsureSizeAndPositionUpToDate();
}
nsIScrollableFrame *sf = GetScrollFrame();
@ -13221,7 +13218,7 @@ nsGlobalWindow::FlushPendingNotifications(FlushType aType)
}
void
nsGlobalWindow::EnsureSizeUpToDate()
nsGlobalWindow::EnsureSizeAndPositionUpToDate()
{
MOZ_ASSERT(IsOuterWindow());

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

@ -423,7 +423,7 @@ public:
bool aOriginalOpener) override;
// Outer windows only.
virtual void EnsureSizeUpToDate() override;
virtual void EnsureSizeAndPositionUpToDate() override;
virtual void EnterModalState() override;
virtual void LeaveModalState() override;

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

@ -247,6 +247,13 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputDisallowLineBreaking = (1 << 27);
/**
* Release reference of nsIDocument after using encodeTo* method to recycle
* this encoder without holding nsIDocument. To use this encoder again,
* we have to call init again.
*/
const unsigned long RequiresReinitAfterOutput = (1 << 28);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

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

@ -313,7 +313,12 @@ public:
virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
bool aOriginalOpener) = 0;
virtual void EnsureSizeUpToDate() = 0;
/**
* Ensure the size and position of this window are up-to-date by doing
* a layout flush in the parent (which will in turn, do a layout flush
* in its parent, etc.).
*/
virtual void EnsureSizeAndPositionUpToDate() = 0;
/**
* Callback for notifying a window about a modal dialog being

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

@ -629,6 +629,7 @@ skip-if = toolkit == 'android' || e10s # showmodaldialog
[test_element_closest.html]
[test_elementTraversal.html]
[test_encodeToStringWithMaxLength.html]
[test_encodeToStringWithRequiresReinitAfterOutput.html]
[test_error.html]
[test_EventSource_redirects.html]
[test_explicit_user_agent.html]

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

@ -0,0 +1,101 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1352882
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1352882 - RequiresReinitAfterOutput</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
function getEncoder() {
const de = SpecialPowers.Ci.nsIDocumentEncoder;
const Cc = SpecialPowers.Cc;
// Create a plaintext encoder without flags.
var encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
.createInstance(de);
encoder.init(document, "text/plain", encoder.RequiresReinitAfterOutput);
return encoder;
}
function testPlaintextSerializerWithRequiresReinitAfterOutput() {
var encoder = getEncoder();
var str = encoder.encodeToString();
ok(str, "encodingToString should be successful");
SimpleTest.doesThrow(() => {
encoder.encodeToString();
}, 'encodeToString should throw exception if it has RequiresReinitAfterOutput and it is called twice');
encoder.init(document, "text/plain", encoder.RequiresReinitAfterOutput);
str = encoder.encodeToString();
ok(str, "encodingToString should be successful after calling init again");
encoder = getEncoder();
str = encoder.encodeToStringWithMaxLength(1000);
ok(str, "encodingToString should be successful");
SimpleTest.doesThrow(() => {
encoder.encodeToStringWithMaxLength(1000);
}, 'encodeToStringWithMaxLength should throw exception if it has RequiresReinitAfterOutput and it is called twice');
encoder.init(document, "text/plain", encoder.RequiresReinitAfterOutput);
str = encoder.encodeToStringWithMaxLength(1000);
ok(str, "encodingToStringWithMaxLength should be successful after calling init again");
encoder = getEncoder();
var stream = {
close: function() {
},
flush: function() {
},
write: function(buffer, length) {
return length;
},
writeFrom: function(buffer, length) {
return length;
},
};
encoder.setCharset("utf-8");
encoder.encodeToStream(stream);
ok(str, "encodingToStream should be successful");
SimpleTest.doesThrow(() => {
encoder.encodeToStream(stream);
}, 'encodeToStream should throw exception if it has RequiresReinitAfterOutput and it is called twice');
encoder.init(document, "text/plain", encoder.RequiresReinitAfterOutput);
encoder.encodeToStream(stream);
ok(true, "encodingToStream should be successful after calling init again");
stream.close();
SimpleTest.finish();
}
addLoadEvent(testPlaintextSerializerWithRequiresReinitAfterOutput);
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1352882">Mozilla Bug 1352882</a>
<p id="display"></p>
<div id="content" style="display: none">
The <em>Mozilla</em> project is a global community of <strong>people</strong> who believe that openness, innovation, and opportunity are key to the continued health of the Internet. We have worked together since 1998 to ensure that the Internet is developed in a way that benefits everyone. We are best known for creating the Mozilla Firefox web browser.
The Mozilla project uses a community-based approach to create world-class open source software and to develop new types of collaborative activities. We create communities of people involved in making the Internet experience better for all of us.
As a result of these efforts, we have distilled a set of principles that we believe are critical for the Internet to continue to benefit the public good as well as commercial aspects of life. We set out these principles below.
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -3801,9 +3801,8 @@ void
CanvasRenderingContext2D::EnsureWritablePath()
{
EnsureTarget();
if (!IsTargetValid()) {
return;
}
// NOTE: IsTargetValid() may be false here (mTarget == sErrorTarget) but we
// go ahead and create a path anyway since callers depend on that.
if (mDSPathBuilder) {
return;

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

@ -0,0 +1,10 @@
<html>
<head>
<script>
o1 = document.createElement("canvas");
o1.setAttribute("width", "100000");
o2 = o1.getContext("2d");
o2.bezierCurveTo(64, 1, 1, 1, 1, 1);
</script>
</head>
</html>

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

@ -42,4 +42,4 @@ load 1305312-1.html
load 1298576-1.html
load 1334366-1.html
load 1334647-1.html
load 1357092.html

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

@ -10,6 +10,7 @@
#include "nsUConvPropertySearch.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "nsIObserverService.h"
#include "mozilla/intl/LocaleService.h"
using mozilla::intl::LocaleService;
@ -29,21 +30,17 @@ static constexpr nsUConvProp nonParticipatingDomains[] = {
#include "nonparticipatingdomains.properties.h"
};
NS_IMPL_ISUPPORTS(FallbackEncoding, nsIObserver)
FallbackEncoding* FallbackEncoding::sInstance = nullptr;
bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true;
FallbackEncoding::FallbackEncoding()
{
MOZ_COUNT_CTOR(FallbackEncoding);
MOZ_ASSERT(!FallbackEncoding::sInstance,
"Singleton already exists.");
}
FallbackEncoding::~FallbackEncoding()
{
MOZ_COUNT_DTOR(FallbackEncoding);
}
void
FallbackEncoding::Get(nsACString& aFallback)
{
@ -118,6 +115,16 @@ FallbackEncoding::PrefChanged(const char*, void*)
FallbackEncoding::sInstance->Invalidate();
}
NS_IMETHODIMP
FallbackEncoding::Observe(nsISupports *aSubject, const char *aTopic,
const char16_t *aData)
{
MOZ_ASSERT(FallbackEncoding::sInstance,
"Observe callback called with null fallback cache.");
FallbackEncoding::sInstance->Invalidate();
return NS_OK;
}
void
FallbackEncoding::Initialize()
{
@ -127,11 +134,13 @@ FallbackEncoding::Initialize()
Preferences::RegisterCallback(FallbackEncoding::PrefChanged,
"intl.charset.fallback.override",
nullptr);
Preferences::RegisterCallback(FallbackEncoding::PrefChanged,
"general.useragent.locale",
nullptr);
Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain,
"intl.charset.fallback.tld");
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(sInstance, "intl:requested-locales-changed", true);
}
}
void
@ -139,6 +148,10 @@ FallbackEncoding::Shutdown()
{
MOZ_ASSERT(FallbackEncoding::sInstance,
"Releasing non-existent fallback cache.");
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(sInstance, "intl:requested-locales-changed");
}
delete FallbackEncoding::sInstance;
FallbackEncoding::sInstance = nullptr;
}

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

@ -7,14 +7,17 @@
#ifndef mozilla_dom_FallbackEncoding_h_
#define mozilla_dom_FallbackEncoding_h_
#include "nsIObserver.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
class FallbackEncoding
class FallbackEncoding : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
/**
* Whether FromTopLevelDomain() should be used.
@ -68,7 +71,7 @@ private:
static FallbackEncoding* sInstance;
FallbackEncoding();
~FallbackEncoding();
virtual ~FallbackEncoding() {};
/**
* Invalidates the cache.

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

@ -337,8 +337,8 @@ DataTransfer::GetTypes(nsTArray<nsString>& aTypes, CallerType aCallerType) const
// reasons.
nsAutoString type;
item->GetInternalType(type);
if (item->Kind() == DataTransferItem::KIND_STRING || type.EqualsASCII(kFileMime)) {
// If the entry has kind KIND_STRING, we want to add it to the list.
if (item->Kind() != DataTransferItem::KIND_FILE || type.EqualsASCII(kFileMime)) {
// If the entry has kind KIND_STRING or KIND_OTHER we want to add it to the list.
aTypes.AppendElement(type);
}
}

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

@ -213,8 +213,22 @@ TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
// But touch events are only actually supported if APZ is enabled. If
// APZ is disabled globally, we can check that once and incorporate that
// into the cached state. If APZ is enabled, we need to further check
// based on the widget, which we do below (and don't cache that result).
sIsTouchDeviceSupportPresent &= gfxPlatform::AsyncPanZoomEnabled();
}
enabled = sIsTouchDeviceSupportPresent;
if (enabled && aDocShell) {
// APZ might be disabled on this particular widget, in which case
// TouchEvent support will also be disabled. Try to detect that.
nsPresContext* pc = nullptr;
aDocShell->GetPresContext(&pc);
if (pc && pc->GetRootWidget()) {
enabled &= pc->GetRootWidget()->AsyncPanZoomEnabled();
}
}
#else
enabled = false;
#endif

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

@ -315,6 +315,23 @@ function test_DataTransfer(dt)
is(dt.mozItemCount, 3, "setDataAt node itemCount");
checkOneDataItem(dt, ["application/-moz-node"], ["draggable"], 2, "setDataAt node item at index 2");
// Try to add and then remove a non-string type to the DataTransfer and ensure
// that the type appears in DataTransfer.types. These calls need to be called
// with SpecialPowers.wrap(), as adding and removing non-string/file types to
// DataTransfer is chrome-only.
{
SpecialPowers.wrap(dt).mozSetDataAt("application/-x-body", document.body, 0);
let found = false;
for (let i = 0; i < dt.types.length; ++i) {
if (dt.types[i] == "application/-x-body") {
found = true;
break;
}
}
ok(found, "Data should appear in datatransfer.types despite having a non-string type");
SpecialPowers.wrap(dt).mozClearDataAt("application/-x-body", 0);
}
dt.mozClearDataAt("text/html", 1);
is(dt.mozItemCount, 3, "clearDataAt itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],

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

@ -59,6 +59,7 @@
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/CaptivePortalService.h"
#include "mozilla/Omnijar.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h"
#include "mozilla/widget/ScreenManager.h"
@ -1230,7 +1231,7 @@ GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
if (!dirSvc) {
return false;
}
rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
rv = dirSvc->Get(NS_GRE_DIR,
NS_GET_IID(nsIFile), getter_AddRefs(appDir));
if (NS_FAILED(rv)) {
return false;
@ -1264,6 +1265,18 @@ GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
return true;
}
// Returns whether or not the currently running build is a development build -
// where development build means "the files in the .app are symlinks to the src
// directory". This check is implemented by looking for omni.ja in
// .app/Contents/Resources/.
static bool
IsDevelopmentBuild()
{
nsCOMPtr<nsIFile> path = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
// If the path doesn't exist, we're a dev build.
return path == nullptr;
}
static bool
StartMacOSContentSandbox()
{
@ -1307,6 +1320,13 @@ StartMacOSContentSandbox()
}
bool isFileProcess = cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE);
char *developer_repo_dir = nullptr;
if (IsDevelopmentBuild()) {
// If this is a developer build the resources in the .app are symlinks to
// outside of the .app. Therefore in non-release builds we allow reads from
// the whole repository. MOZ_DEVELOPER_REPO_DIR is set by mach run.
developer_repo_dir = PR_GetEnv("MOZ_DEVELOPER_REPO_DIR");
}
MacSandboxInfo info;
info.type = MacSandboxType_Content;
@ -1316,7 +1336,11 @@ StartMacOSContentSandbox()
PR_GetEnv("MOZ_SANDBOX_LOGGING");
info.appPath.assign(appPath.get());
info.appBinaryPath.assign(appBinaryPath.get());
info.appDir.assign(appDir.get());
if (developer_repo_dir != nullptr) {
info.appDir.assign(developer_repo_dir);
} else {
info.appDir.assign(appDir.get());
}
info.appTempDir.assign(tempDirPath.get());
if (profileDir) {

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

@ -753,12 +753,12 @@ ADTSTrackDemuxer::GetNextFrame(const adts::Frame& aFrame)
UpdateState(aFrame);
frame->mTime = Duration(mFrameIndex - 1).ToMicroseconds();
frame->mDuration = Duration(1).ToMicroseconds();
frame->mDuration = Duration(1);
frame->mTimecode = frame->mTime;
frame->mKeyframe = true;
MOZ_ASSERT(frame->mTime >= 0);
MOZ_ASSERT(frame->mDuration > 0);
MOZ_ASSERT(frame->mDuration.IsPositive());
ADTSLOGV("GetNext() End mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
" mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64

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

@ -605,12 +605,12 @@ MP3TrackDemuxer::GetNextFrame(const MediaByteRange& aRange)
UpdateState(aRange);
frame->mTime = Duration(mFrameIndex - 1).ToMicroseconds();
frame->mDuration = Duration(1).ToMicroseconds();
frame->mDuration = Duration(1);
frame->mTimecode = frame->mTime;
frame->mKeyframe = true;
MOZ_ASSERT(frame->mTime >= 0);
MOZ_ASSERT(frame->mDuration > 0);
MOZ_ASSERT(frame->mDuration.IsPositive());
if (mNumParsedFrames == 1) {
// First frame parsed, let's read VBR info if available.

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

@ -22,6 +22,7 @@ using namespace mozilla::gfx;
using layers::ImageContainer;
using layers::PlanarYCbCrImage;
using layers::PlanarYCbCrData;
using media::TimeUnit;
const char* AudioData::sTypeName = "audio";
const char* VideoData::sTypeName = "video";
@ -173,7 +174,7 @@ VideoData::VideoData(int64_t aOffset,
, mFrameID(aFrameID)
, mSentToCompositor(false)
{
NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
MOZ_ASSERT(!mDuration.IsNegative(), "Frame must have non-negative duration.");
mKeyframe = aKeyframe;
mTimecode = aTimecode;
}
@ -222,22 +223,21 @@ VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
}
void
VideoData::UpdateDuration(int64_t aDuration)
VideoData::UpdateDuration(const TimeUnit& aDuration)
{
MOZ_ASSERT(aDuration >= 0);
MOZ_ASSERT(!aDuration.IsNegative());
mDuration = aDuration;
}
void
VideoData::UpdateTimestamp(int64_t aTimestamp)
VideoData::UpdateTimestamp(const TimeUnit& aTimestamp)
{
MOZ_ASSERT(aTimestamp >= 0);
MOZ_ASSERT(!aTimestamp.IsNegative());
int64_t updatedDuration = GetEndTime() - aTimestamp;
MOZ_ASSERT(updatedDuration >= 0);
auto updatedDuration = GetEndTime() - aTimestamp;
MOZ_ASSERT(!updatedDuration.IsNegative());
mTime = aTimestamp;
mTime = aTimestamp.ToMicroseconds();
mDuration = updatedDuration;
}
@ -286,7 +286,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
ImageContainer* aContainer,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const TimeUnit& aDuration,
const YCbCrBuffer& aBuffer,
bool aKeyframe,
int64_t aTimecode,
@ -297,7 +297,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
// send to media streams if necessary.
RefPtr<VideoData> v(new VideoData(aOffset,
aTime,
aDuration,
aDuration.ToMicroseconds(),
aKeyframe,
aTimecode,
aInfo.mDisplay,
@ -311,7 +311,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
RefPtr<VideoData> v(new VideoData(aOffset,
aTime,
aDuration,
aDuration.ToMicroseconds(),
aKeyframe,
aTimecode,
aInfo.mDisplay,
@ -370,7 +370,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
ImageContainer* aContainer,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const TimeUnit& aDuration,
const YCbCrBuffer& aBuffer,
const YCbCrBuffer::Plane &aAlphaPlane,
bool aKeyframe,
@ -382,7 +382,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
// send to media streams if necessary.
RefPtr<VideoData> v(new VideoData(aOffset,
aTime,
aDuration,
aDuration.ToMicroseconds(),
aKeyframe,
aTimecode,
aInfo.mDisplay,
@ -396,7 +396,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
RefPtr<VideoData> v(new VideoData(aOffset,
aTime,
aDuration,
aDuration.ToMicroseconds(),
aKeyframe,
aTimecode,
aInfo.mDisplay,
@ -436,14 +436,14 @@ already_AddRefed<VideoData>
VideoData::CreateFromImage(const IntSize& aDisplay,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const TimeUnit& aDuration,
const RefPtr<Image>& aImage,
bool aKeyframe,
int64_t aTimecode)
{
RefPtr<VideoData> v(new VideoData(aOffset,
aTime,
aDuration,
aDuration.ToMicroseconds(),
aKeyframe,
aTimecode,
aDisplay,

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

@ -19,6 +19,7 @@
#include "nsTArray.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/PodOperations.h"
#include "TimeUnits.h"
namespace mozilla {
@ -295,7 +296,7 @@ public:
, mOffset(aOffset)
, mTime(aTimestamp)
, mTimecode(aTimestamp)
, mDuration(aDuration)
, mDuration(media::TimeUnit::FromMicroseconds(aDuration))
, mFrames(aFrames)
, mKeyframe(false)
{
@ -315,14 +316,17 @@ public:
int64_t mTimecode;
// Duration of sample, in microseconds.
int64_t mDuration;
media::TimeUnit mDuration;
// Amount of frames for contained data.
const uint32_t mFrames;
bool mKeyframe;
int64_t GetEndTime() const { return mTime + mDuration; }
media::TimeUnit GetEndTime() const
{
return media::TimeUnit::FromMicroseconds(mTime) + mDuration;
}
bool AdjustForStartTime(int64_t aStartTime)
{
@ -350,7 +354,6 @@ protected:
, mOffset(0)
, mTime(0)
, mTimecode(0)
, mDuration(0)
, mFrames(aFrames)
, mKeyframe(false)
{
@ -489,7 +492,7 @@ public:
ImageContainer* aContainer,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const media::TimeUnit& aDuration,
const YCbCrBuffer& aBuffer,
bool aKeyframe,
int64_t aTimecode,
@ -500,7 +503,7 @@ public:
ImageContainer* aContainer,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const media::TimeUnit& aDuration,
const YCbCrBuffer& aBuffer,
const YCbCrBuffer::Plane& aAlphaPlane,
bool aKeyframe,
@ -511,7 +514,7 @@ public:
const VideoInfo& aInfo,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const media::TimeUnit& aDuration,
layers::TextureClient* aBuffer,
bool aKeyframe,
int64_t aTimecode,
@ -521,7 +524,7 @@ public:
const IntSize& aDisplay,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
const media::TimeUnit& aDuration,
const RefPtr<Image>& aImage,
bool aKeyframe,
int64_t aTimecode);
@ -558,8 +561,8 @@ public:
void MarkSentToCompositor();
bool IsSentToCompositor() { return mSentToCompositor; }
void UpdateDuration(int64_t aDuration);
void UpdateTimestamp(int64_t aTimestamp);
void UpdateDuration(const media::TimeUnit& aDuration);
void UpdateTimestamp(const media::TimeUnit& aTimestamp);
protected:
~VideoData();

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

@ -1405,17 +1405,19 @@ private:
{
MOZ_ASSERT(aVideo);
SLOG("DropVideoUpToSeekTarget() frame [%" PRId64 ", %" PRId64 "]",
aVideo->mTime, aVideo->GetEndTime());
const int64_t target = mSeekJob.mTarget->GetTime().ToMicroseconds();
aVideo->mTime, aVideo->GetEndTime().ToMicroseconds());
const auto target = mSeekJob.mTarget->GetTime();
// If the frame end time is less than the seek target, we won't want
// to display this frame after the seek, so discard it.
if (target >= aVideo->GetEndTime()) {
SLOG("DropVideoUpToSeekTarget() pop video frame [%" PRId64 ", %" PRId64 "] target=%" PRId64,
aVideo->mTime, aVideo->GetEndTime(), target);
aVideo->mTime, aVideo->GetEndTime().ToMicroseconds(),
target.ToMicroseconds());
mFirstVideoFrameAfterSeek = aVideo;
} else {
if (target >= aVideo->mTime && aVideo->GetEndTime() >= target) {
if (target.ToMicroseconds() >= aVideo->mTime &&
aVideo->GetEndTime() >= target) {
// The seek target lies inside this frame's time slice. Adjust the
// frame's start time to match the seek target.
aVideo->UpdateTimestamp(target);
@ -1424,7 +1426,8 @@ private:
SLOG("DropVideoUpToSeekTarget() found video frame [%" PRId64 ", %" PRId64 "] "
"containing target=%" PRId64,
aVideo->mTime, aVideo->GetEndTime(), target);
aVideo->mTime, aVideo->GetEndTime().ToMicroseconds(),
target.ToMicroseconds());
MOZ_ASSERT(VideoQueue().GetSize() == 0,
"Should be the 1st sample after seeking");
@ -3173,9 +3176,9 @@ MediaDecoderStateMachine::RequestAudioData()
mAudioDataRequest.Complete();
// audio->GetEndTime() is not always mono-increasing in chained ogg.
mDecodedAudioEndTime = std::max(
TimeUnit::FromMicroseconds(aAudio->GetEndTime()), mDecodedAudioEndTime);
aAudio->GetEndTime(), mDecodedAudioEndTime);
LOGV("OnAudioDecoded [%" PRId64 ",%" PRId64 "]", aAudio->mTime,
aAudio->GetEndTime());
aAudio->GetEndTime().ToMicroseconds());
mStateObj->HandleAudioDecoded(aAudio);
},
[this, self] (const MediaResult& aError) {
@ -3219,9 +3222,9 @@ MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
mVideoDataRequest.Complete();
// Handle abnormal or negative timestamps.
mDecodedVideoEndTime = std::max(
mDecodedVideoEndTime, TimeUnit::FromMicroseconds(aVideo->GetEndTime()));
mDecodedVideoEndTime, aVideo->GetEndTime());
LOGV("OnVideoDecoded [%" PRId64 ",%" PRId64 "]", aVideo->mTime,
aVideo->GetEndTime());
aVideo->GetEndTime().ToMicroseconds());
mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
},
[this, self] (const MediaResult& aError) {

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

@ -1724,7 +1724,8 @@ MediaFormatReader::NotifyNewOutput(
auto& decoder = GetDecoderData(aTrack);
for (auto& sample : aResults) {
LOGV("Received new %s sample time:%" PRId64 " duration:%" PRId64,
TrackTypeToStr(aTrack), sample->mTime, sample->mDuration);
TrackTypeToStr(aTrack), sample->mTime,
sample->mDuration.ToMicroseconds());
decoder.mOutput.AppendElement(sample);
decoder.mNumSamplesOutput++;
decoder.mNumOfConsecutiveError = 0;
@ -2010,9 +2011,8 @@ MediaFormatReader::HandleDemuxedSamples(
if (sample->mKeyframe) {
ScheduleUpdate(aTrack);
} else {
TimeInterval time =
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
TimeUnit::FromMicroseconds(sample->GetEndTime()));
auto time = TimeInterval(
TimeUnit::FromMicroseconds(sample->mTime), sample->GetEndTime());
InternalSeekTarget seekTarget =
decoder.mTimeThreshold.refOr(InternalSeekTarget(time, false));
LOG("Stream change occurred on a non-keyframe. Seeking to:%" PRId64,
@ -2219,7 +2219,7 @@ MediaFormatReader::Update(TrackType aTrack)
decoder.mSizeOfQueue -= 1;
decoder.mLastSampleTime =
Some(TimeInterval(TimeUnit::FromMicroseconds(output->mTime),
TimeUnit::FromMicroseconds(output->GetEndTime())));
output->GetEndTime()));
decoder.mNumSamplesOutputTotal++;
ReturnOutput(output, aTrack);
// We have a decoded sample ready to be returned.
@ -2379,7 +2379,7 @@ MediaFormatReader::ReturnOutput(MediaData* aData, TrackType aTrack)
MOZ_ASSERT(GetDecoderData(aTrack).HasPromise());
MOZ_DIAGNOSTIC_ASSERT(aData->mType != MediaData::NULL_DATA);
LOG("Resolved data promise for %s [%" PRId64 ", %" PRId64 "]", TrackTypeToStr(aTrack),
aData->mTime, aData->GetEndTime());
aData->mTime, aData->GetEndTime().ToMicroseconds());
if (aTrack == TrackInfo::kAudioTrack) {
AudioData* audioData = static_cast<AudioData*>(aData);

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

@ -47,7 +47,7 @@ public:
MOZ_ASSERT(!mEndOfStream);
MOZ_ASSERT(aItem);
NS_ADDREF(aItem);
MOZ_ASSERT(aItem->GetEndTime() >= aItem->mTime);
MOZ_ASSERT(aItem->GetEndTime().ToMicroseconds() >= aItem->mTime);
nsDeque::Push(aItem);
mPushEvent.Notify(RefPtr<T>(aItem));
}
@ -104,7 +104,7 @@ public:
}
T* last = static_cast<T*>(nsDeque::Peek());
T* first = static_cast<T*>(nsDeque::PeekFront());
return last->GetEndTime() - first->mTime;
return last->GetEndTime().ToMicroseconds() - first->mTime;
}
void LockedForEach(nsDequeFunctor& aFunctor) const {
@ -121,7 +121,7 @@ public:
size_t i;
for (i = GetSize() - 1; i > 0; --i) {
T* v = static_cast<T*>(ObjectAt(i));
if (v->GetEndTime() < aTime)
if (v->GetEndTime().ToMicroseconds() < aTime)
break;
}
// Elements less than i have a end time before aTime. It's also possible

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

@ -165,6 +165,10 @@ public:
return mValue.value() > 0;
}
bool IsNegative() const {
return mValue.value() < 0;
}
bool operator == (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() == aOther.mValue.value();

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

@ -142,7 +142,7 @@ bool AndroidMediaReader::DecodeVideoFrame(bool& aKeyframeSkip,
int64_t durationUs;
mPlugin->GetDuration(mPlugin, &durationUs);
durationUs = std::max<int64_t>(durationUs - mLastVideoFrame->mTime, 0);
mLastVideoFrame->UpdateDuration(durationUs);
mLastVideoFrame->UpdateDuration(TimeUnit::FromMicroseconds(durationUs));
mVideoQueue.Push(mLastVideoFrame);
mLastVideoFrame = nullptr;
}
@ -176,7 +176,7 @@ bool AndroidMediaReader::DecodeVideoFrame(bool& aKeyframeSkip,
v = VideoData::CreateFromImage(mInfo.mVideo.mDisplay,
pos,
frame.mTimeUs,
1, // We don't know the duration yet.
TimeUnit::FromMicroseconds(1), // We don't know the duration yet.
currentImage,
frame.mKeyFrame,
-1);
@ -221,7 +221,7 @@ bool AndroidMediaReader::DecodeVideoFrame(bool& aKeyframeSkip,
mDecoder->GetImageContainer(),
pos,
frame.mTimeUs,
1, // We don't know the duration yet.
TimeUnit::FromMicroseconds(1), // We don't know the duration yet.
b,
frame.mKeyFrame,
-1,
@ -248,12 +248,12 @@ bool AndroidMediaReader::DecodeVideoFrame(bool& aKeyframeSkip,
// timestamp of the previous frame. We can then return the previously
// decoded frame, and it will have a valid timestamp.
int64_t duration = v->mTime - mLastVideoFrame->mTime;
mLastVideoFrame->UpdateDuration(duration);
mLastVideoFrame->UpdateDuration(TimeUnit::FromMicroseconds(duration));
// We have the start time of the next frame, so we can push the previous
// frame into the queue, except if the end time is below the threshold,
// in which case it wouldn't be displayed anyway.
if (mLastVideoFrame->GetEndTime() < aTimeThreshold.ToMicroseconds()) {
if (mLastVideoFrame->GetEndTime() < aTimeThreshold) {
mLastVideoFrame = nullptr;
continue;
}

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

@ -981,13 +981,13 @@ FlacTrackDemuxer::GetNextFrame(const flac::Frame& aFrame)
}
frame->mTime = aFrame.Time().ToMicroseconds();
frame->mDuration = aFrame.Duration().ToMicroseconds();
frame->mDuration = aFrame.Duration();
frame->mTimecode = frame->mTime;
frame->mOffset = aFrame.Offset();
frame->mKeyframe = true;
MOZ_ASSERT(frame->mTime >= 0);
MOZ_ASSERT(frame->mDuration >= 0);
MOZ_ASSERT(!frame->mDuration.IsNegative());
return frame.forget();
}

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

@ -462,7 +462,8 @@ MP4TrackDemuxer::GetNextSample()
"@ pts:%" PRId64 " dur:%" PRId64
" dts:%" PRId64,
keyframe ? "" : "non-", sample->mTime,
sample->mDuration, sample->mTimecode)
sample->mDuration.ToMicroseconds(),
sample->mTimecode)
.get());
sample->mKeyframe = keyframe;
}
@ -472,7 +473,8 @@ MP4TrackDemuxer::GetNextSample()
NS_WARNING(
nsPrintfCString("Invalid H264 frame @ pts:%" PRId64 " dur:%" PRId64
" dts:%" PRId64,
sample->mTime, sample->mDuration, sample->mTimecode)
sample->mTime, sample->mDuration.ToMicroseconds(),
sample->mTimecode)
.get());
// We could reject the sample now, however demuxer errors are fatal.
// So we keep the invalid frame, relying on the H264 decoder to

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

@ -191,7 +191,7 @@ ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer,
crypto.mKeyId,
crypto.mIV,
aSample->mTime,
aSample->mDuration,
aSample->mDuration.ToMicroseconds(),
crypto.mPlainSizes,
crypto.mEncryptedSizes,
crypto.mValid);
@ -636,15 +636,16 @@ ChromiumCDMParent::RecvDecoded(const CDMVideoFrame& aFrame)
b.mPlanes[2].mSkip = 0;
gfx::IntRect pictureRegion(0, 0, aFrame.mImageWidth(), aFrame.mImageHeight());
RefPtr<VideoData> v = VideoData::CreateAndCopyData(mVideoInfo,
mImageContainer,
mLastStreamOffset,
aFrame.mTimestamp(),
aFrame.mDuration(),
b,
false,
-1,
pictureRegion);
RefPtr<VideoData> v = VideoData::CreateAndCopyData(
mVideoInfo,
mImageContainer,
mLastStreamOffset,
aFrame.mTimestamp(),
media::TimeUnit::FromMicroseconds(aFrame.mDuration()),
b,
false,
-1,
pictureRegion);
// Return the shmem to the CDM so the shmem can be reused to send us
// another frame.

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

@ -45,13 +45,15 @@ VideoDecoderChild::RecvOutput(const VideoDataIPDL& aData)
// it gets deallocated.
RefPtr<Image> image = new GPUVideoImage(GetManager(), aData.sd(), aData.frameSize());
RefPtr<VideoData> video = VideoData::CreateFromImage(aData.display(),
aData.base().offset(),
aData.base().time(),
aData.base().duration(),
image,
aData.base().keyframe(),
aData.base().timecode());
RefPtr<VideoData> video = VideoData::CreateFromImage(
aData.display(),
aData.base().offset(),
aData.base().time(),
media::TimeUnit::FromMicroseconds(aData.base().duration()),
image,
aData.base().keyframe(),
aData.base().timecode());
mDecodedData.AppendElement(Move(video));
return IPC_OK();
}
@ -230,7 +232,7 @@ VideoDecoderChild::Decode(MediaRawData* aSample)
MediaRawDataIPDL sample(MediaDataIPDL(aSample->mOffset,
aSample->mTime,
aSample->mTimecode,
aSample->mDuration,
aSample->mDuration.ToMicroseconds(),
aSample->mFrames,
aSample->mKeyframe),
buffer);

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

@ -139,7 +139,7 @@ VideoDecoderParent::RecvInput(const MediaRawDataIPDL& aData)
data->mOffset = aData.base().offset();
data->mTime = aData.base().time();
data->mTimecode = aData.base().timecode();
data->mDuration = aData.base().duration();
data->mDuration = media::TimeUnit::FromMicroseconds(aData.base().duration());
data->mKeyframe = aData.base().keyframe();
DeallocShmem(aData.buffer());
@ -187,7 +187,8 @@ VideoDecoderParent::ProcessDecodedData(
VideoDataIPDL output(
MediaDataIPDL(data->mOffset, data->mTime, data->mTimecode,
data->mDuration, data->mFrames, data->mKeyframe),
data->mDuration.ToMicroseconds(),
data->mFrames, data->mKeyframe),
video->mDisplay,
texture ? texture->GetSize() : IntSize(),
texture ? mParent->StoreImage(video->mImage, texture)

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