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

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

@ -338,6 +338,21 @@ DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
return IPC_OK(); 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 mozilla::ipc::IPCResult
DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID, DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID, 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!"); 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); aChildDoc->SetParent(outerDoc);
outerDoc->SetChildDoc(aChildDoc); outerDoc->SetChildDoc(aChildDoc);
mChildDocs.AppendElement(aChildDoc->mActorID); mChildDocs.AppendElement(aChildDoc->mActorID);

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

@ -88,6 +88,13 @@ public:
const bool& aIsInsert, const bool& aIsInsert,
const bool& aFromUser) override; 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, virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID, const uint64_t& aWidgetID,
const uint32_t& aType) override; const uint32_t& aType) override;

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

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

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

@ -77,6 +77,18 @@ DocAccessibleChild::RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandl
return IPC_OK(); 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 void
DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent) DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent)
{ {
@ -178,6 +190,13 @@ DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID,
const bool& aFromUser) const bool& aFromUser)
{ {
if (IsConstructedInParentProcess()) { 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, return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert, aFromUser); aLen, aIsInsert, aFromUser);
} }

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

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

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

@ -53,6 +53,8 @@ parent:
async CaretMoveEvent(uint64_t aID, int32_t aOffset); async CaretMoveEvent(uint64_t aID, int32_t aOffset);
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen, async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
bool aIsInsert, bool aFromUser); 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 SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
async RoleChangedEvent(uint32_t aRole); async RoleChangedEvent(uint32_t aRole);

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

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

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

@ -22,6 +22,103 @@ namespace a11y {
mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory; 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 HRESULT
AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject) AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
{ {
@ -35,46 +132,14 @@ AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
} }
AccessibleHandlerControl::AccessibleHandlerControl() AccessibleHandlerControl::AccessibleHandlerControl()
: mRefCnt(0) : mCacheGen(0)
, mCacheGen(0)
, mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll")) , mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll"))
, mHandlerProxy(mscom::RegisterProxy()) , mHandlerProxy(mscom::RegisterProxy())
{ {
MOZ_ASSERT(mIA2Proxy); MOZ_ASSERT(mIA2Proxy);
} }
HRESULT IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
AccessibleHandlerControl::QueryInterface(REFIID aIid, void** aOutInterface)
{
if (!aOutInterface) {
return E_INVALIDARG;
}
if (aIid == IID_IUnknown || aIid == IID_IHandlerControl) {
RefPtr<IHandlerControl> ctl(this);
ctl.forget(aOutInterface);
return S_OK;
}
*aOutInterface = nullptr;
return E_NOINTERFACE;
}
ULONG
AccessibleHandlerControl::AddRef()
{
return ++mRefCnt;
}
ULONG
AccessibleHandlerControl::Release()
{
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
HRESULT HRESULT
AccessibleHandlerControl::Invalidate() AccessibleHandlerControl::Invalidate()
@ -83,6 +148,36 @@ AccessibleHandlerControl::Invalidate()
return S_OK; 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 HRESULT
AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo) AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo)
{ {

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

@ -13,37 +13,70 @@
#include "Factory.h" #include "Factory.h"
#include "HandlerData.h" #include "HandlerData.h"
#include "IUnknownImpl.h"
#include "mozilla/mscom/Registration.h" #include "mozilla/mscom/Registration.h"
#include "mozilla/NotNull.h"
namespace mozilla { namespace mozilla {
namespace a11y { 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 class AccessibleHandlerControl final : public IHandlerControl
{ {
public: public:
static HRESULT Create(AccessibleHandlerControl** aOutObject); static HRESULT Create(AccessibleHandlerControl** aOutObject);
// IUnknown DECL_IUNKNOWN
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IHandlerControl // IHandlerControl
STDMETHODIMP Invalidate() override; STDMETHODIMP Invalidate() override;
STDMETHODIMP OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert, IA2TextSegment* aText) override;
uint32_t GetCacheGen() const uint32_t GetCacheGen() const
{ {
return mCacheGen; return mCacheGen;
} }
HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo); HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
private: private:
AccessibleHandlerControl(); AccessibleHandlerControl();
~AccessibleHandlerControl() = default; ~AccessibleHandlerControl() = default;
ULONG mRefCnt;
uint32_t mCacheGen; uint32_t mCacheGen;
detail::TextChange mTextChange;
UniquePtr<mscom::RegisteredProxy> mIA2Proxy; UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mscom::RegisteredProxy> mHandlerProxy; 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 "ocidl.idl";
import "ServProv.idl"; import "ServProv.idl";
import "AccessibleText.idl";
typedef struct _IA2Data typedef struct _IA2Data
{ {
long mUniqueId; long mUniqueId;
@ -84,6 +86,9 @@ interface HandlerData
interface IHandlerControl : IUnknown interface IHandlerControl : IUnknown
{ {
HRESULT Invalidate(); HRESULT Invalidate();
HRESULT OnTextChange([in] long aHwnd, [in] long aIA2UniqueId,
[in] VARIANT_BOOL aIsInsert,
[in] IA2TextSegment* aText);
} }
[object, [object,

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

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

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

@ -43,6 +43,7 @@
#include "nsArrayUtils.h" #include "nsArrayUtils.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "mozilla/mscom/AsyncInvoker.h"
#include "oleacc.h" #include "oleacc.h"
@ -1627,3 +1628,60 @@ AccessibleWrap::SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl)
sHandlerControllers->AppendElement(Move(ctrlData)); 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); static void SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl);
bool DispatchTextChangeToHandler(bool aIsInsert, const nsString& aText,
int32_t aStart, uint32_t aLen);
protected: protected:
virtual ~AccessibleWrap(); virtual ~AccessibleWrap();

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

@ -131,18 +131,7 @@ DocAccessibleWrap::GetNativeWindow() const
return nullptr; return nullptr;
} }
HWND hWnd = ipcDoc->GetEmulatedWindowHandle(); return ipcDoc->GetNativeWindowHandle();
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());
} else if (mHWND) { } else if (mHWND) {
return mHWND; return mHWND;
} }

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

@ -132,6 +132,14 @@ a11y::ProxyTextChangeEvent(ProxyAccessible* aText, const nsString& aStr,
return; 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()); auto text = static_cast<HyperTextAccessibleWrap*>(wrapper->AsHyperText());
if (text) { if (text) {
ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen); ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen);

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

@ -11,58 +11,8 @@ const prefs = require("../preferences/service");
const { Cu, Cc, Ci } = require("chrome"); const { Cu, Cc, Ci } = require("chrome");
const { Services } = Cu.import("resource://gre/modules/Services.jsm"); 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) { function getPreferedLocales(caseSensitve) {
let locales = []; return Services.locale.getRequestedLocales();
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;
} }
exports.getPreferedLocales = getPreferedLocales; exports.getPreferedLocales = getPreferedLocales;

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

@ -2,128 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { getPreferedLocales, findClosestLocale } = require("sdk/l10n/locale"); const { 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);
}
exports.testFindClosestLocale = function(assert) { exports.testFindClosestLocale = function(assert) {
// Second param of findClosestLocale (aMatchLocales) have to be in lowercase // Second param of findClosestLocale (aMatchLocales) have to be in lowercase

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

@ -414,15 +414,6 @@ pref("media.realtime_decoder.enabled", true);
// TCPSocket // TCPSocket
pref("dom.mozTCPSocket.enabled", true); 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 // Handle hardware buttons in the b2g chrome package
pref("b2g.keys.menu.enabled", true); pref("b2g.keys.menu.enabled", true);

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

@ -576,11 +576,20 @@
return true; return true;
}, },
_isForInitialAboutBlank(aWebProgress, aLocation) { _isForInitialAboutBlank(aWebProgress, aStateFlags, aLocation) {
if (!this.mBlank || !aWebProgress.isTopLevel) { if (!this.mBlank || !aWebProgress.isTopLevel) {
return false; 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 : ""; let location = aLocation ? aLocation.spec : "";
return location == "about:blank"; return location == "about:blank";
}, },
@ -623,7 +632,9 @@
originalLocation = aRequest.originalURI; originalLocation = aRequest.originalURI;
} catch (ex) {} } 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 // 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 // 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 // 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 videoIframe = doc.querySelector("#test-video-in-iframe");
let video = videoIframe.contentDocument.querySelector("video"); let video = videoIframe.contentDocument.querySelector("video");
let awaitPause = ContentTaskUtils.waitForEvent(video, "pause"); let awaitPause = ContentTaskUtils.waitForEvent(video, "pause");
yield ContentTaskUtils.waitForCondition(() => !video.paused, "Making sure video is playing before calling pause");
video.pause(); video.pause();
yield awaitPause; yield awaitPause;
@ -66,6 +67,7 @@ add_task(function* test_setup_html() {
// media documents always use a <video> tag. // media documents always use a <video> tag.
let audio = audioIframe.contentDocument.querySelector("video"); let audio = audioIframe.contentDocument.querySelector("video");
awaitPause = ContentTaskUtils.waitForEvent(audio, "pause"); awaitPause = ContentTaskUtils.waitForEvent(audio, "pause");
yield ContentTaskUtils.waitForCondition(() => !audio.paused, "Making sure audio is playing before calling pause");
audio.pause(); audio.pause();
yield awaitPause; yield awaitPause;
}); });

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

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

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

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

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

@ -62,6 +62,37 @@ this.sessions = class extends ExtensionAPI {
return Promise.resolve(getRecentlyClosed(maxResults, extension)); 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) { restore: function(sessionId) {
let session, closedId; let session, closedId;
if (sessionId) { if (sessionId) {

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

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

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

@ -155,6 +155,7 @@ class TabTracker extends TabTrackerBase {
windowTracker.addListener("TabClose", this); windowTracker.addListener("TabClose", this);
windowTracker.addListener("TabOpen", this); windowTracker.addListener("TabOpen", this);
windowTracker.addListener("TabSelect", this);
windowTracker.addOpenListener(this._handleWindowOpen); windowTracker.addOpenListener(this._handleWindowOpen);
windowTracker.addCloseListener(this._handleWindowClose); windowTracker.addCloseListener(this._handleWindowClose);
@ -262,6 +263,14 @@ class TabTracker extends TabTrackerBase {
this.emitRemoved(nativeTab, false); this.emitRemoved(nativeTab, false);
} }
break; 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) { for (let nativeTab of window.gBrowser.tabs) {
this.emitCreated(nativeTab); 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. * Emits a "tab-attached" event for the given tab element.
* *

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

@ -55,6 +55,37 @@
} }
], ],
"functions": [ "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", "name": "getRecentlyClosed",
"type": "function", "type": "function",

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

@ -82,6 +82,8 @@ support-files =
[browser_ext_runtime_openOptionsPage.js] [browser_ext_runtime_openOptionsPage.js]
[browser_ext_runtime_openOptionsPage_uninstall.js] [browser_ext_runtime_openOptionsPage_uninstall.js]
[browser_ext_runtime_setUninstallURL.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.js]
[browser_ext_sessions_getRecentlyClosed_private.js] [browser_ext_sessions_getRecentlyClosed_private.js]
[browser_ext_sessions_getRecentlyClosed_tabs.js] [browser_ext_sessions_getRecentlyClosed_tabs.js]
@ -102,6 +104,7 @@ support-files =
[browser_ext_tabs_executeScript.js] [browser_ext_tabs_executeScript.js]
[browser_ext_tabs_executeScript_good.js] [browser_ext_tabs_executeScript_good.js]
[browser_ext_tabs_executeScript_bad.js] [browser_ext_tabs_executeScript_bad.js]
[browser_ext_tabs_executeScript_multiple.js]
[browser_ext_tabs_executeScript_no_create.js] [browser_ext_tabs_executeScript_no_create.js]
[browser_ext_tabs_executeScript_runAt.js] [browser_ext_tabs_executeScript_runAt.js]
[browser_ext_tabs_getCurrent.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) => { browser.tabs.onHighlighted.addListener((info) => {
if (info.tabIds[0] in events) { if (info.tabIds[0] in events) {
events[info.tabIds[0]].push("onHighlighted"); events[info.tabIds[0]].push("onHighlighted");
@ -43,7 +51,10 @@ add_task(function* testTabEvents() {
async function expectEvents(tabId, expectedEvents) { async function expectEvents(tabId, expectedEvents) {
browser.test.log(`Expecting events: ${expectedEvents.join(", ")}`); 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, browser.test.assertEq(expectedEvents.length, events[tabId].length,
`Got expected number of events for ${tabId}`); `Got expected number of events for ${tabId}`);
@ -61,23 +72,58 @@ add_task(function* testTabEvents() {
* @param {number} windowId * @param {number} windowId
*/ */
async function openTab(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}); let tab = await browser.tabs.create({windowId});
tabIds.push(tab.id); tabIds.push(tab.id);
browser.test.log(`Opened tab ${tab.id}`); browser.test.log(`Opened tab ${tab.id}`);
await expectEvents(tab.id, [ await expectEvents(tab.id, [
"onCreated",
"onActivated", "onActivated",
"onHighlighted", "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. * Highlights an existing tab and asserts that the correct events are fired.
* *
* @param {number} tabId * @param {number} tabId
*/ */
async function highlightTab(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}`); browser.test.log(`Highlighting tab ${tabId}`);
let tab = await browser.tabs.update(tabId, {active: true}); let tab = await browser.tabs.update(tabId, {active: true});
@ -107,6 +153,15 @@ add_task(function* testTabEvents() {
highlightTab(tabIds[2]), 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))); await Promise.all(tabIds.map(id => browser.tabs.remove(id)));
browser.test.notifyPass("tabs.highlight"); 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(); yield extension.startup();
@ -141,7 +142,7 @@ function* runTests(options) {
yield extension.unload(); yield extension.unload();
yield SpecialPowers.popPrefEnv(); Services.locale.setRequestedLocales(reqLoc);
let node = document.getElementById(pageActionId); let node = document.getElementById(pageActionId);
is(node, null, "pageAction image removed from document"); is(node, null, "pageAction image removed from document");

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

@ -109,7 +109,13 @@ this.SiteDataManager = {
}, },
_updateAppCache() { _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 site of this._sites.values()) {
for (let group of groups) { for (let group of groups) {
let uri = Services.io.newURI(group); let uri = Services.io.newURI(group);

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

@ -12,17 +12,22 @@ function test() {
"browser.cache.disk.enable", "browser.cache.disk.enable",
"browser.cache.memory.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() { registerCleanupFunction(function() {
for (let pref of prefs) { for (let pref of prefs) {
Services.prefs.clearUserPref(pref); Services.prefs.clearUserPref(pref);
} }
Services.perms.removeFromPrincipal(principal, "persistent-storage");
}); });
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
open_preferences(runTest); open_preferences(runTest);
} }
@ -31,6 +36,7 @@ function runTest(win) {
let tab = win.document; let tab = win.document;
let elements = tab.getElementById("mainPrefPane").children; let elements = tab.getElementById("mainPrefPane").children;
let offlineGroupDisabled = !SpecialPowers.getBoolPref("browser.preferences.offlineGroup.enabled");
// Test if advanced pane is opened correctly // Test if advanced pane is opened correctly
win.gotoPref("paneAdvanced"); win.gotoPref("paneAdvanced");
@ -38,6 +44,13 @@ function runTest(win) {
if (element.nodeName == "preferences") { if (element.nodeName == "preferences") {
continue; 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"); let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneAdvanced") { if (attributeValue == "paneAdvanced") {
is_element_visible(element, "Advanced elements should be visible"); is_element_visible(element, "Advanced elements should be visible");

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

@ -1,8 +1,9 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/PlacesUtils.jsm"); const { interfaces: Ci, utils: Cu } = Components;
Components.utils.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
@ -12,17 +13,22 @@ function test() {
"browser.cache.disk.enable", "browser.cache.disk.enable",
"browser.cache.memory.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() { registerCleanupFunction(function() {
for (let pref of prefs) { for (let pref of prefs) {
Services.prefs.clearUserPref(pref); Services.prefs.clearUserPref(pref);
} }
Services.perms.removeFromPrincipal(principal, "persistent-storage");
}); });
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
open_preferences(runTest); open_preferences(runTest);
} }
@ -31,18 +37,26 @@ function runTest(win) {
let tab = win.document; let tab = win.document;
let elements = tab.getElementById("mainPrefPane").children; let elements = tab.getElementById("mainPrefPane").children;
let offlineGroupDisabled = !SpecialPowers.getBoolPref("browser.preferences.offlineGroup.enabled");
// Test if advanced pane is opened correctly // Test if privacy pane is opened correctly
win.gotoPref("paneAdvanced"); win.gotoPref("panePrivacy");
for (let element of elements) { for (let element of elements) {
if (element.nodeName == "preferences") { if (element.nodeName == "preferences") {
continue; 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"); let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneAdvanced") { if (attributeValue == "panePrivacy") {
is_element_visible(element, "Advanced elements should be visible"); is_element_visible(element, "Privacy elements should be visible");
} else { } 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() { function getLocale() {
const localePref = "general.useragent.locale"; return Services.locale.getRequestedLocale() || undefined;
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;
}
} }
function promiseEvent(aTarget, aEventName, aPreventDefault) { function promiseEvent(aTarget, aEventName, aPreventDefault) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -15,13 +15,13 @@
"unpack": true "unpack": true
}, },
{ {
"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8", "version": "sccache rev 7a3847276d05deb564cb84a16b8c551b690aaa3e",
"algorithm": "sha512", "algorithm": "sha512",
"visibility": "public", "visibility": "public",
"filename": "sccache2.tar.bz2", "filename": "sccache2.tar.bz2",
"unpack": true, "unpack": true,
"digest": "7dee5c5602b3830cb8ac45ebaa8542714bbac0e50eabbff58a06972a02ceeab75ed7c56ff22a23f760b8317ae8e9a01cdecfaf75a7acbd2a4cdd817967170d2e", "digest": "09c6b9407978a4ffa0638b412cde9517ebbdb9c8e8449f4dc6745f4da5c8025e29b4c99dfa1ddb84623d0dde8a3aac513f73e92fdb3a148e4c9a4e7931907964",
"size": 1179901 "size": 1628305
}, },
{ {
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0", "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 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() { getLocale() {
return getStringPref("general.useragent.locale", "en-US"); return Services.locale.getRequestedLocale() || "en-US";
} }
getStrings(data) { getStrings(data) {

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

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

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

@ -201,6 +201,7 @@
.annotationLayer .underlineAnnotation, .annotationLayer .underlineAnnotation,
.annotationLayer .squigglyAnnotation, .annotationLayer .squigglyAnnotation,
.annotationLayer .strikeoutAnnotation, .annotationLayer .strikeoutAnnotation,
.annotationLayer .lineAnnotation svg line,
.annotationLayer .fileAttachmentAnnotation { .annotationLayer .fileAttachmentAnnotation {
cursor: pointer; 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> <p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
</div> </div>
<div class="row"> <div class="row">
<!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. --> <input type="password" id="password" class="toolbarField">
<input id="password" class="toolbarField">
</div> </div>
<div class="buttonRow"> <div class="buttonRow">
<button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button> <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_FILE = "directoryLinks.json";
const DIRECTORY_LINKS_TYPE = "application/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 // The preference that tells where to obtain directory links
const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source"; const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source";
@ -166,8 +160,6 @@ var DirectoryLinksProvider = {
return Object.freeze({ return Object.freeze({
enhanced: PREF_NEWTAB_ENHANCED, enhanced: PREF_NEWTAB_ENHANCED,
linksURL: PREF_DIRECTORY_SOURCE, 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 * @return the selected locale or "en-US" if none is selected
*/ */
get locale() { get locale() {
let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false); return Services.locale.getRequestedLocale() || "en-US";
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";
}, },
/** /**
@ -236,14 +209,11 @@ var DirectoryLinksProvider = {
case this._observedPrefs.linksURL: case this._observedPrefs.linksURL:
delete this.__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); this._fetchAndCacheLinksIfNecessary(true);
break; break;
} }
} else if (aTopic === "intl:requested-locales-changed") {
this._fetchAndCacheLinksIfNecessary(true);
} }
}, },
@ -690,6 +660,7 @@ var DirectoryLinksProvider = {
init: function DirectoryLinksProvider_init() { init: function DirectoryLinksProvider_init() {
this._setDefaultEnhanced(); this._setDefaultEnhanced();
this._addPrefsObserver(); this._addPrefsObserver();
Services.obs.addObserver(this, "intl:requested-locales-changed");
// setup directory file path and last download timestamp // setup directory file path and last download timestamp
this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE); this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE);
this._lastDownloadMS = 0; this._lastDownloadMS = 0;
@ -1213,6 +1184,7 @@ var DirectoryLinksProvider = {
delete this.__linksURL; delete this.__linksURL;
this._removePrefsObserver(); this._removePrefsObserver();
this._removeObservers(); this._removeObservers();
Services.obs.removeObserver(this, "intl:requested-locales-changed");
}, },
addObserver: function DirectoryLinksProvider_addObserver(aObserver) { 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); const kTestURL = "data:application/json," + JSON.stringify(kURLData);
// DirectoryLinksProvider preferences // DirectoryLinksProvider preferences
const kLocalePref = DirectoryLinksProvider._observedPrefs.prefSelectedLocale;
const kSourceUrlPref = DirectoryLinksProvider._observedPrefs.linksURL; const kSourceUrlPref = DirectoryLinksProvider._observedPrefs.linksURL;
const kPingUrlPref = "browser.newtabpage.directory.ping"; const kPingUrlPref = "browser.newtabpage.directory.ping";
const kNewtabEnhancedPref = "browser.newtabpage.enhanced"; const kNewtabEnhancedPref = "browser.newtabpage.enhanced";
@ -51,7 +50,8 @@ const kFailURL = kBaseUrl + kFailPath;
const kPingUrl = kBaseUrl + kPingPath; const kPingUrl = kBaseUrl + kPingPath;
// app/profile/firefox.js are not avaialble in xpcshell: hence, preset them // 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(kSourceUrlPref, kTestURL);
Services.prefs.setCharPref(kPingUrlPref, kPingUrl); Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
Services.prefs.setBoolPref(kNewtabEnhancedPref, true); Services.prefs.setBoolPref(kNewtabEnhancedPref, true);
@ -201,7 +201,7 @@ function promiseSetupDirectoryLinksProvider(options = {}) {
return Task.spawn(function*() { return Task.spawn(function*() {
let linksURL = options.linksURL || kTestURL; let linksURL = options.linksURL || kTestURL;
yield DirectoryLinksProvider.init(); yield DirectoryLinksProvider.init();
yield promiseDirectoryDownloadOnPrefChange(kLocalePref, options.locale || "en-US"); Services.locale.setRequestedLocales([options.locale || "en-US"]);
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, linksURL); yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, linksURL);
do_check_eq(DirectoryLinksProvider._linksURL, linksURL); do_check_eq(DirectoryLinksProvider._linksURL, linksURL);
DirectoryLinksProvider._lastDownloadMS = options.lastDownloadMS || 0; DirectoryLinksProvider._lastDownloadMS = options.lastDownloadMS || 0;
@ -210,7 +210,7 @@ function promiseSetupDirectoryLinksProvider(options = {}) {
function promiseCleanDirectoryLinksProvider() { function promiseCleanDirectoryLinksProvider() {
return Task.spawn(function*() { return Task.spawn(function*() {
yield promiseDirectoryDownloadOnPrefChange(kLocalePref, "en-US"); Services.locale.setRequestedLocales(["en-US"]);
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kTestURL); yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kTestURL);
yield DirectoryLinksProvider._clearFrequencyCap(); yield DirectoryLinksProvider._clearFrequencyCap();
yield DirectoryLinksProvider._loadInadjacentSites(); yield DirectoryLinksProvider._loadInadjacentSites();
@ -233,7 +233,7 @@ function run_test() {
do_register_cleanup(function() { do_register_cleanup(function() {
server.stop(function() { }); server.stop(function() { });
DirectoryLinksProvider.reset(); DirectoryLinksProvider.reset();
Services.prefs.clearUserPref(kLocalePref); Services.locale.setRequestedLocales(origReqLocales);
Services.prefs.clearUserPref(kSourceUrlPref); Services.prefs.clearUserPref(kSourceUrlPref);
Services.prefs.clearUserPref(kPingUrlPref); Services.prefs.clearUserPref(kPingUrlPref);
Services.prefs.clearUserPref(kNewtabEnhancedPref); Services.prefs.clearUserPref(kNewtabEnhancedPref);

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

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

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

@ -6,6 +6,12 @@
"use strict"; "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 * Extracts any urlencoded form data sections (e.g. "?foo=bar&baz=42") from a
* POST request. * POST request.
@ -112,7 +118,8 @@ function getAbbreviatedMimeType(mimeType) {
if (!mimeType) { if (!mimeType) {
return ""; 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); void loadComplete(in nsresult aStatus);
[noscript] readonly attribute boolean loadCompleted; [noscript] readonly attribute boolean loadCompleted;
[noscript] readonly attribute boolean isStopped;
/** /**
* Checks if the document wants to prevent unloading by firing beforeunload on * 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. * 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 " "Restyle request during restyling should be requested only on "
"the main-thread. e.g. after the parallel traversal"); "the main-thread. e.g. after the parallel traversal");
if (ServoStyleSet::IsInServoTraversal()) { 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 // We can't call Servo_NoteExplicitHints here since AtomicRefCell does not
// allow us mutate ElementData of the |aElement| in SequentialTask. // 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 // which will be called right before the second traversal that we do for
// updating CSS animations. // updating CSS animations.
// In that case PreTraverse() will return true so that we know to do the // 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()); MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
bool foundElementsNeedingRestyle = false; bool foundElementsNeedingRestyle = false;
for (auto& elementsToRestyle : mElementsToRestyle) { for (size_t i = 0; i < kCascadeLevelCount; ++i) {
for (auto iter = elementsToRestyle.Iter(); !iter.Done(); iter.Next()) { CascadeLevel cascadeLevel = CascadeLevel(i);
for (auto iter = mElementsToRestyle[cascadeLevel].Iter();
!iter.Done(); iter.Next()) {
bool postedRestyle = iter.Data(); bool postedRestyle = iter.Data();
// Ignore throttled restyle. // Ignore throttled restyle.
if (!postedRestyle) { if (!postedRestyle) {
@ -1003,7 +1005,10 @@ EffectCompositor::PreTraverseInSubtree(Element* aRoot)
// We can't call PostRestyleEvent directly here since we are still in the // We can't call PostRestyleEvent directly here since we are still in the
// middle of the servo traversal. // middle of the servo traversal.
mPresContext->RestyleManager()->AsServo()-> mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(target.mElement, eRestyle_CSSAnimations); PostRestyleEventForAnimations(target.mElement,
cascadeLevel == CascadeLevel::Transitions
? eRestyle_CSSTransitions
: eRestyle_CSSAnimations);
foundElementsNeedingRestyle = true; foundElementsNeedingRestyle = true;
@ -1048,14 +1053,21 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
PseudoElementHashEntry::KeyType key = { aElement, pseudoType }; 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. // Ignore throttled restyle and no restyle request.
continue; continue;
} }
mPresContext->RestyleManager()->AsServo()-> mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(aElement, eRestyle_CSSAnimations); PostRestyleEventForAnimations(aElement,
cascadeLevel == CascadeLevel::Transitions
? eRestyle_CSSTransitions
: eRestyle_CSSAnimations);
EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType); EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
if (effects) { if (effects) {
@ -1066,7 +1078,7 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
} }
} }
elementsToRestyle.Remove(key); elementSet.Remove(key);
found = true; found = true;
} }
return found; return found;

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

@ -142,6 +142,25 @@ protected:
virtual bool IncludeInContext(nsINode *aNode); 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<nsIDocument> mDocument;
nsCOMPtr<nsISelection> mSelection; nsCOMPtr<nsISelection> mSelection;
RefPtr<nsRange> mRange; RefPtr<nsRange> mRange;
@ -1009,6 +1028,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
if (!mDocument) if (!mDocument)
return NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_INITIALIZED;
AutoReleaseDocumentIfNeeded autoReleaseDocument(this);
aOutputString.Truncate(); aOutputString.Truncate();
nsString output; nsString output;

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

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

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

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

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

@ -247,6 +247,13 @@ interface nsIDocumentEncoder : nsISupports
*/ */
const unsigned long OutputDisallowLineBreaking = (1 << 27); 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. * Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode. * @param aDocument Document to encode.

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

@ -313,7 +313,12 @@ public:
virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener, virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
bool aOriginalOpener) = 0; 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 * 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_element_closest.html]
[test_elementTraversal.html] [test_elementTraversal.html]
[test_encodeToStringWithMaxLength.html] [test_encodeToStringWithMaxLength.html]
[test_encodeToStringWithRequiresReinitAfterOutput.html]
[test_error.html] [test_error.html]
[test_EventSource_redirects.html] [test_EventSource_redirects.html]
[test_explicit_user_agent.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() CanvasRenderingContext2D::EnsureWritablePath()
{ {
EnsureTarget(); EnsureTarget();
if (!IsTargetValid()) { // NOTE: IsTargetValid() may be false here (mTarget == sErrorTarget) but we
return; // go ahead and create a path anyway since callers depend on that.
}
if (mDSPathBuilder) { if (mDSPathBuilder) {
return; 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 1298576-1.html
load 1334366-1.html load 1334366-1.html
load 1334647-1.html load 1334647-1.html
load 1357092.html

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

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

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

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

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

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

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

@ -213,8 +213,22 @@ TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
if (!sDidCheckTouchDeviceSupport) { if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true; sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent(); 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; 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 #else
enabled = false; enabled = false;
#endif #endif

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

@ -315,6 +315,23 @@ function test_DataTransfer(dt)
is(dt.mozItemCount, 3, "setDataAt node itemCount"); is(dt.mozItemCount, 3, "setDataAt node itemCount");
checkOneDataItem(dt, ["application/-moz-node"], ["draggable"], 2, "setDataAt node item at index 2"); 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); dt.mozClearDataAt("text/html", 1);
is(dt.mozItemCount, 3, "clearDataAt itemCount"); is(dt.mozItemCount, 3, "clearDataAt itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"], checkOneDataItem(dt, ["text/plain", "text/html"],

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

@ -59,6 +59,7 @@
#include "mozilla/layout/RenderFrameChild.h" #include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/net/NeckoChild.h" #include "mozilla/net/NeckoChild.h"
#include "mozilla/net/CaptivePortalService.h" #include "mozilla/net/CaptivePortalService.h"
#include "mozilla/Omnijar.h"
#include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h" #include "mozilla/plugins/PluginModuleParent.h"
#include "mozilla/widget/ScreenManager.h" #include "mozilla/widget/ScreenManager.h"
@ -1230,7 +1231,7 @@ GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
if (!dirSvc) { if (!dirSvc) {
return false; return false;
} }
rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, rv = dirSvc->Get(NS_GRE_DIR,
NS_GET_IID(nsIFile), getter_AddRefs(appDir)); NS_GET_IID(nsIFile), getter_AddRefs(appDir));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return false; return false;
@ -1264,6 +1265,18 @@ GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
return true; 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 static bool
StartMacOSContentSandbox() StartMacOSContentSandbox()
{ {
@ -1307,6 +1320,13 @@ StartMacOSContentSandbox()
} }
bool isFileProcess = cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE); 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; MacSandboxInfo info;
info.type = MacSandboxType_Content; info.type = MacSandboxType_Content;
@ -1316,7 +1336,11 @@ StartMacOSContentSandbox()
PR_GetEnv("MOZ_SANDBOX_LOGGING"); PR_GetEnv("MOZ_SANDBOX_LOGGING");
info.appPath.assign(appPath.get()); info.appPath.assign(appPath.get());
info.appBinaryPath.assign(appBinaryPath.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()); info.appTempDir.assign(tempDirPath.get());
if (profileDir) { if (profileDir) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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