зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound. a=merge
This commit is contained in:
Коммит
e09b8cecbf
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "nsMai.h"
|
||||
|
||||
#include "ProxyAccessible.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
|
@ -20,12 +20,17 @@ extern "C" {
|
|||
static void
|
||||
getCurrentValueCB(AtkValue *obj, GValue *value)
|
||||
{
|
||||
ProxyAccessible* proxy = nullptr;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
|
||||
if (!accWrap)
|
||||
return;
|
||||
if (!accWrap) {
|
||||
proxy = GetProxy(ATK_OBJECT(obj));
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset (value, 0, sizeof (GValue));
|
||||
double accValue = accWrap->CurValue();
|
||||
double accValue = accWrap ? accWrap->CurValue() : proxy->CurValue();
|
||||
if (IsNaN(accValue))
|
||||
return;
|
||||
|
||||
|
@ -36,12 +41,17 @@ getCurrentValueCB(AtkValue *obj, GValue *value)
|
|||
static void
|
||||
getMaximumValueCB(AtkValue *obj, GValue *value)
|
||||
{
|
||||
ProxyAccessible* proxy = nullptr;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
|
||||
if (!accWrap)
|
||||
return;
|
||||
if (!accWrap) {
|
||||
proxy = GetProxy(ATK_OBJECT(obj));
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset(value, 0, sizeof (GValue));
|
||||
double accValue = accWrap->MaxValue();
|
||||
double accValue = accWrap ? accWrap->MaxValue() : proxy->MaxValue();
|
||||
if (IsNaN(accValue))
|
||||
return;
|
||||
|
||||
|
@ -52,12 +62,17 @@ getMaximumValueCB(AtkValue *obj, GValue *value)
|
|||
static void
|
||||
getMinimumValueCB(AtkValue *obj, GValue *value)
|
||||
{
|
||||
ProxyAccessible* proxy = nullptr;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
|
||||
if (!accWrap)
|
||||
return;
|
||||
if (!accWrap) {
|
||||
proxy = GetProxy(ATK_OBJECT(obj));
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset(value, 0, sizeof (GValue));
|
||||
double accValue = accWrap->MinValue();
|
||||
double accValue = accWrap ? accWrap->MinValue() : proxy->MinValue();
|
||||
if (IsNaN(accValue))
|
||||
return;
|
||||
|
||||
|
@ -68,12 +83,17 @@ getMinimumValueCB(AtkValue *obj, GValue *value)
|
|||
static void
|
||||
getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
|
||||
{
|
||||
ProxyAccessible* proxy = nullptr;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
|
||||
if (!accWrap)
|
||||
return;
|
||||
if (!accWrap) {
|
||||
proxy = GetProxy(ATK_OBJECT(obj));
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset(minimumIncrement, 0, sizeof (GValue));
|
||||
double accValue = accWrap->Step();
|
||||
double accValue = accWrap ? accWrap->Step() : proxy->Step();
|
||||
if (IsNaN(accValue))
|
||||
accValue = 0; // zero if the minimum increment is undefined
|
||||
|
||||
|
@ -84,12 +104,17 @@ getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
|
|||
static gboolean
|
||||
setCurrentValueCB(AtkValue *obj, const GValue *value)
|
||||
{
|
||||
ProxyAccessible* proxy = nullptr;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
|
||||
if (!accWrap)
|
||||
return FALSE;
|
||||
if (!accWrap) {
|
||||
proxy = GetProxy(ATK_OBJECT(obj));
|
||||
if (!proxy) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
double accValue =g_value_get_double(value);
|
||||
return accWrap->SetCurValue(accValue);
|
||||
return accWrap ? accWrap->SetCurValue(accValue) : proxy->SetCurValue(accValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -533,8 +533,9 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
|||
// accessibles in subtree then we don't care about the change.
|
||||
Accessible* child = document->GetAccessible(aChildNode);
|
||||
if (!child) {
|
||||
a11y::TreeWalker walker(document->GetContainerAccessible(aChildNode),
|
||||
aChildNode, a11y::TreeWalker::eWalkCache);
|
||||
Accessible* container = document->GetContainerAccessible(aChildNode);
|
||||
a11y::TreeWalker walker(container ? container : document, aChildNode,
|
||||
a11y::TreeWalker::eWalkCache);
|
||||
child = walker.NextChild();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "TableCellAccessible.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsAccUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
@ -1430,5 +1431,205 @@ DocAccessibleChild::RecvUnselectAll(const uint64_t& aID,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvDoAction(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
bool* aSuccess)
|
||||
{
|
||||
*aSuccess = false;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aSuccess = acc->DoAction(aIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvActionCount(const uint64_t& aID,
|
||||
uint8_t* aCount)
|
||||
{
|
||||
*aCount = 0;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aCount = acc->ActionCount();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvActionDescriptionAt(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
nsString* aDescription)
|
||||
{
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
acc->ActionDescriptionAt(aIndex, *aDescription);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvActionNameAt(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
nsString* aName)
|
||||
{
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
acc->ActionNameAt(aIndex, *aName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvAccessKey(const uint64_t& aID,
|
||||
uint32_t* aKey,
|
||||
uint32_t* aModifierMask)
|
||||
{
|
||||
*aKey = 0;
|
||||
*aModifierMask = 0;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
KeyBinding kb = acc->AccessKey();
|
||||
*aKey = kb.Key();
|
||||
*aModifierMask = kb.ModifierMask();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvKeyboardShortcut(const uint64_t& aID,
|
||||
uint32_t* aKey,
|
||||
uint32_t* aModifierMask)
|
||||
{
|
||||
*aKey = 0;
|
||||
*aModifierMask = 0;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
KeyBinding kb = acc->KeyboardShortcut();
|
||||
*aKey = kb.Key();
|
||||
*aModifierMask = kb.ModifierMask();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvCurValue(const uint64_t& aID,
|
||||
double* aValue)
|
||||
{
|
||||
*aValue = UnspecifiedNaN<double>();
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aValue = acc->CurValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvSetCurValue(const uint64_t& aID,
|
||||
const double& aValue,
|
||||
bool* aRetVal)
|
||||
{
|
||||
*aRetVal = false;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aRetVal = acc->SetCurValue(aValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvMinValue(const uint64_t& aID,
|
||||
double* aValue)
|
||||
{
|
||||
*aValue = UnspecifiedNaN<double>();
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aValue = acc->MinValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvMaxValue(const uint64_t& aID,
|
||||
double* aValue)
|
||||
{
|
||||
*aValue = UnspecifiedNaN<double>();
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aValue = acc->MaxValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvStep(const uint64_t& aID,
|
||||
double* aStep)
|
||||
{
|
||||
*aStep = UnspecifiedNaN<double>();
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
*aStep = acc->Step();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvTakeFocus(const uint64_t& aID)
|
||||
{
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
acc->TakeFocus();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvChildAtPoint(const uint64_t& aID,
|
||||
const int32_t& aX,
|
||||
const int32_t& aY,
|
||||
const uint32_t& aWhich,
|
||||
uint64_t* aChild,
|
||||
bool* aOk)
|
||||
{
|
||||
*aChild = 0;
|
||||
*aOk = false;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc && !acc->IsDefunct() && !nsAccUtils::MustPrune(acc)) {
|
||||
Accessible* child =
|
||||
acc->ChildAtPoint(aX, aY,
|
||||
static_cast<Accessible::EWhichChildAtPoint>(aWhich));
|
||||
if (child) {
|
||||
*aChild = reinterpret_cast<uint64_t>(child->UniqueID());
|
||||
*aOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvBounds(const uint64_t& aID,
|
||||
nsIntRect* aRect)
|
||||
{
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc && !acc->IsDefunct()) {
|
||||
*aRect = acc->Bounds();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -351,6 +351,56 @@ public:
|
|||
|
||||
virtual bool RecvUnselectAll(const uint64_t& aID,
|
||||
bool* aSuccess) override;
|
||||
|
||||
virtual bool RecvDoAction(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
bool* aSuccess) override;
|
||||
|
||||
virtual bool RecvActionCount(const uint64_t& aID,
|
||||
uint8_t* aCount) override;
|
||||
|
||||
virtual bool RecvActionDescriptionAt(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
nsString* aDescription) override;
|
||||
|
||||
virtual bool RecvActionNameAt(const uint64_t& aID,
|
||||
const uint8_t& aIndex,
|
||||
nsString* aName) override;
|
||||
|
||||
virtual bool RecvAccessKey(const uint64_t& aID,
|
||||
uint32_t* aKey,
|
||||
uint32_t* aModifierMask) override;
|
||||
|
||||
virtual bool RecvKeyboardShortcut(const uint64_t& aID,
|
||||
uint32_t* aKey,
|
||||
uint32_t* aModifierMask) override;
|
||||
|
||||
virtual bool RecvCurValue(const uint64_t& aID,
|
||||
double* aValue);
|
||||
|
||||
virtual bool RecvSetCurValue(const uint64_t& aID,
|
||||
const double& aValue,
|
||||
bool* aRetVal);
|
||||
|
||||
virtual bool RecvMinValue(const uint64_t& aID,
|
||||
double* aValue);
|
||||
|
||||
virtual bool RecvMaxValue(const uint64_t& aID,
|
||||
double* aValue);
|
||||
|
||||
virtual bool RecvStep(const uint64_t& aID,
|
||||
double* aStep);
|
||||
|
||||
virtual bool RecvTakeFocus(const uint64_t& aID) override;
|
||||
|
||||
virtual bool RecvChildAtPoint(const uint64_t& aID,
|
||||
const int32_t& aX,
|
||||
const int32_t& aY,
|
||||
const uint32_t& aWhich,
|
||||
uint64_t* aChild,
|
||||
bool* aOk) override;
|
||||
|
||||
virtual bool RecvBounds(const uint64_t& aID, nsIntRect* aRect) override;
|
||||
private:
|
||||
|
||||
Accessible* IdToAccessible(const uint64_t& aID) const;
|
||||
|
|
|
@ -191,7 +191,24 @@ child:
|
|||
prio(high) sync RemoveItemFromSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
|
||||
prio(high) sync SelectAll(uint64_t aID) returns(bool aSuccess);
|
||||
prio(high) sync UnselectAll(uint64_t aID) returns(bool aSuccess);
|
||||
|
||||
|
||||
prio(high) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
|
||||
prio(high) sync ActionCount(uint64_t aID) returns(uint8_t aCount);
|
||||
prio(high) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription);
|
||||
prio(high) sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName);
|
||||
prio(high) sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
|
||||
prio(high) sync KeyboardShortcut(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
|
||||
|
||||
prio(high) sync CurValue(uint64_t aID) returns(double aValue);
|
||||
prio(high) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
|
||||
prio(high) sync MinValue(uint64_t aID) returns(double aValue);
|
||||
prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
|
||||
prio(high) sync Step(uint64_t aID) returns(double aStep);
|
||||
|
||||
prio(high) sync TakeFocus(uint64_t aID);
|
||||
prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
|
||||
returns(uint64_t aChild, bool aOk);
|
||||
prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -799,5 +799,117 @@ ProxyAccessible::UnselectAll()
|
|||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAccessible::DoAction(uint8_t aIndex)
|
||||
{
|
||||
bool success = false;
|
||||
unused << mDoc->SendDoAction(mID, aIndex, &success);
|
||||
return success;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ProxyAccessible::ActionCount()
|
||||
{
|
||||
uint8_t count = 0;
|
||||
unused << mDoc->SendActionCount(mID, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::ActionDescriptionAt(uint8_t aIndex, nsString& aDescription)
|
||||
{
|
||||
unused << mDoc->SendActionDescriptionAt(mID, aIndex, &aDescription);
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::ActionNameAt(uint8_t aIndex, nsString& aName)
|
||||
{
|
||||
unused << mDoc->SendActionNameAt(mID, aIndex, &aName);
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
ProxyAccessible::AccessKey()
|
||||
{
|
||||
uint32_t key = 0;
|
||||
uint32_t modifierMask = 0;
|
||||
unused << mDoc->SendAccessKey(mID, &key, &modifierMask);
|
||||
return KeyBinding(key, modifierMask);
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
ProxyAccessible::KeyboardShortcut()
|
||||
{
|
||||
uint32_t key = 0;
|
||||
uint32_t modifierMask = 0;
|
||||
unused << mDoc->SendKeyboardShortcut(mID, &key, &modifierMask);
|
||||
return KeyBinding(key, modifierMask);
|
||||
}
|
||||
|
||||
double
|
||||
ProxyAccessible::CurValue()
|
||||
{
|
||||
double val = UnspecifiedNaN<double>();
|
||||
unused << mDoc->SendCurValue(mID, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAccessible::SetCurValue(double aValue)
|
||||
{
|
||||
bool success = false;
|
||||
unused << mDoc->SendSetCurValue(mID, aValue, &success);
|
||||
return success;
|
||||
}
|
||||
|
||||
double
|
||||
ProxyAccessible::MinValue()
|
||||
{
|
||||
double val = UnspecifiedNaN<double>();
|
||||
unused << mDoc->SendMinValue(mID, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
double
|
||||
ProxyAccessible::MaxValue()
|
||||
{
|
||||
double val = UnspecifiedNaN<double>();
|
||||
unused << mDoc->SendMaxValue(mID, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
double
|
||||
ProxyAccessible::Step()
|
||||
{
|
||||
double step = UnspecifiedNaN<double>();
|
||||
unused << mDoc->SendStep(mID, &step);
|
||||
return step;
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::TakeFocus()
|
||||
{
|
||||
unused << mDoc->SendTakeFocus(mID);
|
||||
}
|
||||
|
||||
ProxyAccessible*
|
||||
ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
|
||||
Accessible::EWhichChildAtPoint aWhichChild)
|
||||
{
|
||||
uint64_t childID = 0;
|
||||
bool ok = false;
|
||||
unused << mDoc->SendChildAtPoint(mID, aX, aY,
|
||||
static_cast<uint32_t>(aWhichChild),
|
||||
&childID, &ok);
|
||||
return ok ? mDoc->GetAccessible(childID) : nullptr;
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
ProxyAccessible::Bounds()
|
||||
{
|
||||
nsIntRect rect;
|
||||
unused << mDoc->SendBounds(mID, &rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
|
||||
#include "mozilla/a11y/Role.h"
|
||||
#include "nsIAccessibleText.h"
|
||||
#include "Accessible.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsRect.h"
|
||||
#include "Accessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
@ -256,6 +258,24 @@ public:
|
|||
bool SelectAll();
|
||||
bool UnselectAll();
|
||||
|
||||
bool DoAction(uint8_t aIndex);
|
||||
uint8_t ActionCount();
|
||||
void ActionDescriptionAt(uint8_t aIndex, nsString& aDescription);
|
||||
void ActionNameAt(uint8_t aIndex, nsString& aName);
|
||||
KeyBinding AccessKey();
|
||||
KeyBinding KeyboardShortcut();
|
||||
|
||||
double CurValue();
|
||||
bool SetCurValue(double aValue);
|
||||
double MinValue();
|
||||
double MaxValue();
|
||||
double Step();
|
||||
|
||||
void TakeFocus();
|
||||
ProxyAccessible* ChildAtPoint(int32_t aX, int32_t aY,
|
||||
Accessible::EWhichChildAtPoint aWhichChild);
|
||||
nsIntRect Bounds();
|
||||
|
||||
/**
|
||||
* Allow the platform to store a pointers worth of data on us.
|
||||
*/
|
||||
|
|
|
@ -969,12 +969,7 @@ pref("gecko.handlerService.allowRegisterFromDifferentHost", false);
|
|||
pref("browser.safebrowsing.enabled", true);
|
||||
pref("browser.safebrowsing.malware.enabled", true);
|
||||
pref("browser.safebrowsing.downloads.enabled", true);
|
||||
// Remote lookups are only enabled for Windows in Nightly and Aurora
|
||||
#if defined(XP_WIN)
|
||||
pref("browser.safebrowsing.downloads.remote.enabled", true);
|
||||
#else
|
||||
pref("browser.safebrowsing.downloads.remote.enabled", false);
|
||||
#endif
|
||||
pref("browser.safebrowsing.debug", false);
|
||||
|
||||
pref("browser.safebrowsing.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
|
||||
|
@ -1015,7 +1010,7 @@ pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
|
|||
#ifdef XP_WIN
|
||||
// Only download the whitelist on Windows, since the whitelist is
|
||||
// only useful for suppressing remote lookups for signed binaries which we can
|
||||
// only verify on Windows (Bug 974579).
|
||||
// only verify on Windows (Bug 974579). Other platforms always do remote lookups.
|
||||
pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-digest256");
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1450,6 +1445,9 @@ pref("devtools.performance.ui.enable-framerate", true);
|
|||
// The default cache UI setting
|
||||
pref("devtools.cache.disabled", false);
|
||||
|
||||
// The default service workers UI setting
|
||||
pref("devtools.serviceWorkers.testing.enabled", false);
|
||||
|
||||
// Enable the Network Monitor
|
||||
pref("devtools.netmonitor.enabled", true);
|
||||
|
||||
|
|
|
@ -3246,8 +3246,7 @@
|
|||
};
|
||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||
let event = gContextMenuContentData.event;
|
||||
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
|
||||
popup.openPopupAtScreen(pos.x, pos.y, true);
|
||||
popup.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
break;
|
||||
}
|
||||
case "DOMWebNotificationClicked": {
|
||||
|
|
|
@ -50,6 +50,9 @@ support-files =
|
|||
file_bug906190_redirected.html
|
||||
file_bug906190.js
|
||||
file_bug906190.sjs
|
||||
file_mixedContentFromOnunload.html
|
||||
file_mixedContentFromOnunload_test1.html
|
||||
file_mixedContentFromOnunload_test2.html
|
||||
file_bug970276_popup1.html
|
||||
file_bug970276_popup2.html
|
||||
file_bug970276_favicon1.ico
|
||||
|
@ -283,6 +286,7 @@ skip-if = e10s # Bug 1126316 - New e10s windows erroneously fire initial about:b
|
|||
[browser_bug902156.js]
|
||||
[browser_bug906190.js]
|
||||
skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
|
||||
[browser_mixedContentFromOnunload.js]
|
||||
[browser_bug970746.js]
|
||||
skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
|
||||
[browser_bug1015721.js]
|
||||
|
|
|
@ -59,6 +59,7 @@ function checkPage() {
|
|||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
|
||||
"online.");
|
||||
Services.obs.removeObserver(observer, "network:offline-status-changed", false);
|
||||
finish();
|
||||
}, "network:offline-status-changed", false);
|
||||
gBrowser.contentDocument.getElementById("errorTryAgain").click();
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Tests for Bug 947079 - Fix bug in nsSecureBrowserUIImpl that sets the wrong
|
||||
* security state on a page because of a subresource load that is not on the
|
||||
* same page.
|
||||
*/
|
||||
|
||||
// We use different domains for each test and for navigation within each test
|
||||
const gHttpTestRoot1 = "http://example.com/browser/browser/base/content/test/general/";
|
||||
const gHttpsTestRoot1 = "https://test1.example.com/browser/browser/base/content/test/general/";
|
||||
const gHttpTestRoot2 = "http://example.net/browser/browser/base/content/test/general/";
|
||||
const gHttpsTestRoot2 = "https://test2.example.com/browser/browser/base/content/test/general/";
|
||||
|
||||
let gTestBrowser = null;
|
||||
|
||||
function SecStateTestsCompleted() {
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", false]]}, SecStateTests);
|
||||
}
|
||||
|
||||
function SecStateTests() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
|
||||
whenLoaded(gTestBrowser, SecStateTest1A);
|
||||
let url = gHttpTestRoot1 + "file_mixedContentFromOnunload.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Navigation from an http page to a https page with no mixed content
|
||||
// The http page loads an http image on unload
|
||||
function SecStateTest1A() {
|
||||
whenLoaded(gTestBrowser, SecStateTest1B);
|
||||
let url = gHttpsTestRoot1 + "file_mixedContentFromOnunload_test1.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
function SecStateTest1B() {
|
||||
// check security state. Since current url is https and doesn't have any
|
||||
// mixed content resources, we expect it to be secure.
|
||||
isSecurityState("secure");
|
||||
|
||||
whenLoaded(gTestBrowser, SecStateTest2A);
|
||||
|
||||
// change locations and proceed with the second test
|
||||
let url = gHttpTestRoot2 + "file_mixedContentFromOnunload.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Navigation from an http page to a https page that has mixed display content
|
||||
// The http page loads an http image on unload
|
||||
function SecStateTest2A() {
|
||||
whenLoaded(gTestBrowser, SecStateTest2B);
|
||||
let url = gHttpsTestRoot2 + "file_mixedContentFromOnunload_test2.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
function SecStateTest2B() {
|
||||
isSecurityState("broken");
|
||||
|
||||
SecStateTestsCompleted();
|
||||
}
|
||||
|
||||
// Compares the security state of the page with what is expected
|
||||
function isSecurityState(expectedState) {
|
||||
let ui = gTestBrowser.securityUI;
|
||||
if (!ui) {
|
||||
ok(false, "No security UI to get the security state");
|
||||
return;
|
||||
}
|
||||
|
||||
const wpl = Components.interfaces.nsIWebProgressListener;
|
||||
|
||||
// determine the security state
|
||||
let isSecure = ui.state & wpl.STATE_IS_SECURE;
|
||||
let isBroken = ui.state & wpl.STATE_IS_BROKEN;
|
||||
let isInsecure = ui.state & wpl.STATE_IS_INSECURE;
|
||||
|
||||
let actualState;
|
||||
if (isSecure && !(isBroken || isInsecure)) {
|
||||
actualState = "secure";
|
||||
} else if (isBroken && !(isSecure || isInsecure)) {
|
||||
actualState = "broken";
|
||||
} else if (isInsecure && !(isSecure || isBroken)) {
|
||||
actualState = "insecure";
|
||||
} else {
|
||||
actualState = "unknown";
|
||||
}
|
||||
|
||||
is(expectedState, actualState, "Expected state " + expectedState + " and the actual state is " + actualState + ".");
|
||||
}
|
||||
|
||||
function whenLoaded(aElement, aCallback) {
|
||||
aElement.addEventListener("load", function onLoad() {
|
||||
aElement.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test for https://bugzilla.mozilla.org/show_bug.cgi?id=947079
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 947079</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for Bug 947079</p>
|
||||
<script>
|
||||
window.addEventListener('unload', function() {
|
||||
new Image().src = 'http://mochi.test:8888/tests/image/test/mochitest/blue.png';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test 1 for https://bugzilla.mozilla.org/show_bug.cgi?id=947079
|
||||
Page with no insecure subresources
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 1 for Bug 947079</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>There are no insecure resource loads on this page</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test 2 for https://bugzilla.mozilla.org/show_bug.cgi?id=947079
|
||||
Page with an insecure image load
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 2 for Bug 947079</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Page with http image load</p>
|
||||
<img src="http://test2.example.com/tests/image/test/mochitest/blue.png">
|
||||
</body>
|
||||
</html>
|
|
@ -13,6 +13,7 @@ var Ci = Components.interfaces;
|
|||
var Cr = Components.results;
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
Components.utils.import('resource://gre/modules/AppConstants.jsm');
|
||||
|
||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
|
@ -73,17 +74,9 @@ const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
|
|||
// identifying the "use plugin" action, so we use this constant instead.
|
||||
const kActionUsePlugin = 5;
|
||||
|
||||
/*
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
*/
|
||||
const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
|
||||
/*
|
||||
#else
|
||||
*/
|
||||
const ICON_URL_APP = "chrome://browser/skin/preferences/application.png";
|
||||
/*
|
||||
#endif
|
||||
*/
|
||||
const ICON_URL_APP = AppConstants.platform == "linux" ?
|
||||
"moz-icon://dummy.exe?size=16" :
|
||||
"chrome://browser/skin/preferences/application.png";
|
||||
|
||||
// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
|
||||
// was set by us to a custom handler icon and CSS should not try to override it.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// Constants & Enumeration Values
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
Components.utils.import('resource://gre/modules/AppConstants.jsm');
|
||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
|
@ -67,17 +68,9 @@ const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
|
|||
// identifying the "use plugin" action, so we use this constant instead.
|
||||
const kActionUsePlugin = 5;
|
||||
|
||||
/*
|
||||
#if MOZ_WIDGET_GTK == 2
|
||||
*/
|
||||
const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
|
||||
/*
|
||||
#else
|
||||
*/
|
||||
const ICON_URL_APP = "chrome://browser/skin/preferences/application.png";
|
||||
/*
|
||||
#endif
|
||||
*/
|
||||
const ICON_URL_APP = AppConstants.platform == "linux" ?
|
||||
"moz-icon://dummy.exe?size=16" :
|
||||
"chrome://browser/skin/preferences/application.png";
|
||||
|
||||
// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
|
||||
// was set by us to a custom handler icon and CSS should not try to override it.
|
||||
|
|
|
@ -95,7 +95,9 @@ let gSyncPane = {
|
|||
"weave:service:start-over:finish",
|
||||
"weave:service:setup-complete",
|
||||
"weave:service:logout:finish",
|
||||
FxAccountsCommon.ONVERIFIED_NOTIFICATION];
|
||||
FxAccountsCommon.ONVERIFIED_NOTIFICATION,
|
||||
FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
|
||||
];
|
||||
let migrateTopic = "fxa-migration:state-changed";
|
||||
|
||||
// Add the observers now and remove them on unload
|
||||
|
@ -123,6 +125,8 @@ let gSyncPane = {
|
|||
}),
|
||||
|
||||
this.updateWeavePrefs();
|
||||
|
||||
this._initProfileImageUI();
|
||||
},
|
||||
|
||||
_setupEventListeners: function() {
|
||||
|
@ -224,6 +228,14 @@ let gSyncPane = {
|
|||
});
|
||||
},
|
||||
|
||||
_initProfileImageUI: function () {
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled")) {
|
||||
document.getElementById("fxaProfileImage").hidden = false;
|
||||
}
|
||||
} catch (e) { }
|
||||
},
|
||||
|
||||
updateWeavePrefs: function () {
|
||||
// ask the migration module to broadcast its current state (and nothing will
|
||||
// happen if it's not loaded - which is good, as that means no migration
|
||||
|
@ -244,10 +256,11 @@ let gSyncPane = {
|
|||
}
|
||||
// determine the fxa status...
|
||||
this.page = PAGE_PLEASE_WAIT;
|
||||
|
||||
fxAccounts.getSignedInUser().then(data => {
|
||||
if (!data) {
|
||||
this.page = FXA_PAGE_LOGGED_OUT;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
this.page = FXA_PAGE_LOGGED_IN;
|
||||
// We are logged in locally, but maybe we are in a state where the
|
||||
|
@ -281,7 +294,36 @@ let gSyncPane = {
|
|||
for (let checkbox of engines.querySelectorAll("checkbox")) {
|
||||
checkbox.disabled = enginesListDisabled;
|
||||
}
|
||||
|
||||
// Clear the profile image (if any) of the previously logged in account.
|
||||
document.getElementById("fxaProfileImage").style.removeProperty("background-image");
|
||||
|
||||
// If the account is verified the next promise in the chain will
|
||||
// fetch profile data.
|
||||
return data.verified;
|
||||
}).then(shouldGetProfile => {
|
||||
if (shouldGetProfile) {
|
||||
return fxAccounts.getSignedInUserProfile();
|
||||
}
|
||||
}).then(data => {
|
||||
if (data && data.avatar) {
|
||||
// Make sure the image is available before displaying it,
|
||||
// as we don't want to overwrite the default profile image
|
||||
// with a broken/unavailable image
|
||||
let img = new Image();
|
||||
img.onload = () => {
|
||||
let bgImage = "url('" + data.avatar + "')";
|
||||
document.getElementById("fxaProfileImage").style.backgroundImage = bgImage;
|
||||
};
|
||||
img.src = data.avatar;
|
||||
}
|
||||
}, err => {
|
||||
FxAccountsCommon.log.error(err);
|
||||
}).catch(err => {
|
||||
// If we get here something's really busted
|
||||
Cu.reportError(String(err));
|
||||
});
|
||||
|
||||
// If fxAccountEnabled is false and we are in a "not configured" state,
|
||||
// then fxAccounts is probably fully disabled rather than just unconfigured,
|
||||
// so handle this case. This block can be removed once we remove support
|
||||
|
@ -521,6 +563,15 @@ let gSyncPane = {
|
|||
});
|
||||
},
|
||||
|
||||
openChangeProfileImage: function() {
|
||||
fxAccounts.promiseAccountsChangeProfileURI("avatar")
|
||||
.then(url => {
|
||||
this.openContentInBrowser(url, {
|
||||
replaceQueryString: true
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
manageFirefoxAccount: function() {
|
||||
let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri");
|
||||
this.openContentInBrowser(url);
|
||||
|
|
|
@ -233,7 +233,11 @@
|
|||
<!-- logged in and verified and all is good -->
|
||||
<hbox id="fxaLoginVerified"
|
||||
align="center">
|
||||
<label id="fxaEmailAddress1"/>
|
||||
<hbox align="center">
|
||||
<image id="fxaProfileImage"
|
||||
onclick="gSyncPane.openChangeProfileImage();" hidden="true"/>
|
||||
<label id="fxaEmailAddress1"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<button id="verifiedManage"
|
||||
label="&manage.label;"/>
|
||||
|
|
|
@ -8,6 +8,8 @@ support-files =
|
|||
head.js
|
||||
helper_disable_cache.js
|
||||
doc_theme.css
|
||||
browser_toolbox_options_enable_serviceworkers_testing.html
|
||||
serviceworker.js
|
||||
|
||||
[browser_devtools_api.js]
|
||||
[browser_devtools_api_destroy.js]
|
||||
|
@ -51,6 +53,8 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
|
|||
[browser_toolbox_zoom.js]
|
||||
[browser_toolbox_custom_host.js]
|
||||
[browser_toolbox_theme_registration.js]
|
||||
[browser_toolbox_options_enable_serviceworkers_testing.js]
|
||||
skip-if = e10s # Bug 1030318
|
||||
|
||||
# We want this test to run for mochitest-dt as well, so we include it here:
|
||||
[../../../base/content/test/general/browser_parsable_css.js]
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>browser_toolbox_options_enable_serviceworkers_testing.html</title>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
div {
|
||||
width: 260px;
|
||||
height: 24px;
|
||||
border: 1px solid #000;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 20px
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
function log(msg) {
|
||||
var output = document.getElementById("output");
|
||||
|
||||
output.innerHTML = msg;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("serviceworker.js").then(
|
||||
swr => {
|
||||
var msg = "";
|
||||
var button = document.getElementById("button");
|
||||
if (swr.installing) {
|
||||
msg += "Installing worker/";
|
||||
}
|
||||
if (swr.waiting) {
|
||||
msg += "Waiting worker/";
|
||||
}
|
||||
if (swr.active) {
|
||||
msg += "Active worker/";
|
||||
}
|
||||
log(msg);
|
||||
button.click();
|
||||
},
|
||||
error => {
|
||||
var button = document.getElementById("button");
|
||||
if (error.name === "SecurityError") {
|
||||
log("SecurityError");
|
||||
}
|
||||
button.click();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test in page</h1>
|
||||
<input id="button"
|
||||
type="button"
|
||||
value="Worker clicks here"/>
|
||||
<br>
|
||||
<div id="output">No output</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,124 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that enabling Service Workers testing option enables the
|
||||
// mServiceWorkersTestingEnabled attribute added to nsPIDOMWindow.
|
||||
|
||||
const TEST_URI = URL_ROOT +
|
||||
"browser_toolbox_options_enable_serviceworkers_testing.html";
|
||||
|
||||
const ELEMENT_ID = "devtools-enable-serviceWorkersTesting";
|
||||
|
||||
let toolbox;
|
||||
let doc;
|
||||
|
||||
function test() {
|
||||
// Note: Pref dom.serviceWorkers.testing.enabled is false since we are testing
|
||||
// the same capabilities are enabled with the devtool pref.
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", false]
|
||||
]}, start);
|
||||
}
|
||||
|
||||
function start() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
gDevTools.showToolbox(target).then(testSelectTool);
|
||||
}, true);
|
||||
|
||||
content.location = TEST_URI;
|
||||
}
|
||||
|
||||
function testSelectTool(aToolbox) {
|
||||
toolbox = aToolbox;
|
||||
toolbox.once("options-selected", testRegisterFails);
|
||||
toolbox.selectTool("options");
|
||||
}
|
||||
|
||||
function testRegisterFails() {
|
||||
let output = doc.getElementById("output");
|
||||
let button = doc.getElementById("button");
|
||||
|
||||
function doTheCheck() {
|
||||
info("Testing it doesn't registers correctly until enable testing");
|
||||
is(output.textContent,
|
||||
"SecurityError",
|
||||
"SecurityError expected");
|
||||
testRegisterInstallingWorker();
|
||||
}
|
||||
|
||||
if (output.textContent !== "No output") {
|
||||
doTheCheck();
|
||||
}
|
||||
|
||||
button.addEventListener('click', function onClick() {
|
||||
button.removeEventListener('click', onClick);
|
||||
doTheCheck();
|
||||
});
|
||||
}
|
||||
|
||||
function testRegisterInstallingWorker() {
|
||||
toggleServiceWorkersTestingCheckbox().then(() => {
|
||||
let output = doc.getElementById("output");
|
||||
let button = doc.getElementById("button");
|
||||
|
||||
function doTheCheck() {
|
||||
info("Testing it registers correctly and there is an installing worker");
|
||||
is(output.textContent,
|
||||
"Installing worker/",
|
||||
"Installing worker expected");
|
||||
toggleServiceWorkersTestingCheckbox().then(finishUp);
|
||||
}
|
||||
|
||||
if (output.textContent !== "No output") {
|
||||
doTheCheck();
|
||||
}
|
||||
|
||||
button.addEventListener('click', function onClick() {
|
||||
button.removeEventListener('click', onClick);
|
||||
doTheCheck();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function toggleServiceWorkersTestingCheckbox() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let cbx = panel.panelDoc.getElementById(ELEMENT_ID);
|
||||
|
||||
cbx.scrollIntoView();
|
||||
|
||||
if (cbx.checked) {
|
||||
info("Clearing checkbox to disable service workers testing");
|
||||
} else {
|
||||
info("Checking checkbox to enable service workers testing");
|
||||
}
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
cbx.click();
|
||||
|
||||
let mm = getFrameScript();
|
||||
mm.sendAsyncMessage("devtools:test:reload");
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
toolbox.destroy().then(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
toolbox = doc = null;
|
||||
finish();
|
||||
});
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
// empty service worker, always succeed!
|
|
@ -317,7 +317,7 @@ OptionsPanel.prototype = {
|
|||
if (this.target.activeTab) {
|
||||
this.target.client.attachTab(this.target.activeTab._actor, (response) => {
|
||||
this._origJavascriptEnabled = response.javascriptEnabled;
|
||||
this.disableJSNode.checked = !this._origJavascriptEnabled
|
||||
this.disableJSNode.checked = !this._origJavascriptEnabled;
|
||||
this.disableJSNode.addEventListener("click", this._disableJSClicked, false);
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -145,6 +145,10 @@
|
|||
<checkbox id="devtools-disable-javascript"
|
||||
label="&options.disableJavaScript.label;"
|
||||
tooltiptext="&options.disableJavaScript.tooltip;"/>
|
||||
<checkbox id="devtools-enable-serviceWorkersTesting"
|
||||
label="&options.enableServiceWorkersTesting.label;"
|
||||
tooltiptext="&options.enableServiceWorkersTesting.tooltip;"
|
||||
data-pref="devtools.serviceWorkers.testing.enabled"/>
|
||||
<hbox class="hidden-labels-box">
|
||||
<checkbox label="&options.enableChrome.label5;"
|
||||
tooltiptext="&options.enableChrome.tooltip3;"
|
||||
|
|
|
@ -332,6 +332,7 @@ Toolbox.prototype = {
|
|||
this._buildOptions();
|
||||
this._buildTabs();
|
||||
this._applyCacheSettings();
|
||||
this._applyServiceWorkersTestingSettings();
|
||||
this._addKeysToWindow();
|
||||
this._addReloadKeys();
|
||||
this._addHostListeners();
|
||||
|
@ -407,8 +408,13 @@ Toolbox.prototype = {
|
|||
* }
|
||||
*/
|
||||
_prefChanged: function(event, data) {
|
||||
if (data.pref === "devtools.cache.disabled") {
|
||||
switch(data.pref) {
|
||||
case "devtools.cache.disabled":
|
||||
this._applyCacheSettings();
|
||||
break;
|
||||
case "devtools.serviceWorkers.testing.enabled":
|
||||
this._applyServiceWorkersTestingSettings();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -747,6 +753,22 @@ Toolbox.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply the current service workers testing setting from
|
||||
* devtools.serviceWorkers.testing.enabled to this toolbox's tab.
|
||||
*/
|
||||
_applyServiceWorkersTestingSettings: function() {
|
||||
let pref = "devtools.serviceWorkers.testing.enabled";
|
||||
let serviceWorkersTestingEnabled =
|
||||
Services.prefs.getBoolPref(pref) || false;
|
||||
|
||||
if (this.target.activeTab) {
|
||||
this.target.activeTab.reconfigure({
|
||||
"serviceWorkersTestingEnabled": serviceWorkersTestingEnabled
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Setter for the checked state of the picker button in the toolbar
|
||||
* @param {Boolean} isChecked
|
||||
|
@ -1694,10 +1716,13 @@ Toolbox.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// Now that we are closing the toolbox we can re-enable JavaScript for the
|
||||
// current tab.
|
||||
// Now that we are closing the toolbox we can re-enable the cache settings
|
||||
// and disable the service workers testing settings for the current tab.
|
||||
if (this.target.activeTab) {
|
||||
this.target.activeTab.reconfigure({"cacheDisabled": false});
|
||||
this.target.activeTab.reconfigure({
|
||||
"cacheDisabled": false,
|
||||
"serviceWorkersTestingEnabled": false
|
||||
});
|
||||
}
|
||||
|
||||
// Destroying the walker and inspector fronts
|
||||
|
|
|
@ -13,7 +13,11 @@ let test = Task.async(function*() {
|
|||
let firstTarget = TargetFactory.forTab(firstTab);
|
||||
yield firstTarget.makeRemote();
|
||||
|
||||
yield gDevTools.showToolbox(firstTarget, "webconsole");
|
||||
let toolboxFirstTab;
|
||||
yield gDevTools.showToolbox(firstTarget, "webconsole").then((aToolbox) => {
|
||||
toolboxFirstTab = aToolbox;
|
||||
});
|
||||
|
||||
is(gProfilerConnections, 1,
|
||||
"A shared profiler connection should have been created.");
|
||||
|
||||
|
@ -25,14 +29,21 @@ let test = Task.async(function*() {
|
|||
let secondTarget = TargetFactory.forTab(secondTab);
|
||||
yield secondTarget.makeRemote();
|
||||
|
||||
yield gDevTools.showToolbox(secondTarget, "jsprofiler");
|
||||
let toolboxSecondTab;
|
||||
yield gDevTools.showToolbox(secondTarget, "jsprofiler").then((aToolbox) => {
|
||||
toolboxSecondTab = aToolbox;
|
||||
});
|
||||
|
||||
is(gProfilerConnections, 2,
|
||||
"Only one new profiler connection should have been created.");
|
||||
|
||||
yield removeTab(firstTab);
|
||||
yield removeTab(secondTab);
|
||||
|
||||
finish();
|
||||
yield toolboxFirstTab.destroy().then(() => {
|
||||
removeTab(firstTab);
|
||||
});
|
||||
yield toolboxSecondTab.destroy().then(() => {
|
||||
removeTab(secondTab);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
|
||||
function profilerConnectionObserver(subject, topic, data) {
|
||||
|
|
|
@ -97,6 +97,12 @@
|
|||
<!ENTITY options.disableCache.label2 "Disable Cache (when toolbox is open)">
|
||||
<!ENTITY options.disableCache.tooltip2 "Turning this option on will disable the cache for all tabs that have the toolbox open.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.enableServiceWorkersTesting.label,
|
||||
- options.enableServiceWorkersTesting.tooltip): This is the options panel label and
|
||||
- tooltip for the checkbox that toggles the service workers testing features on or off. -->
|
||||
<!ENTITY options.enableServiceWorkersTesting.label "Enable Service Workers testing features (when toolbox is open)">
|
||||
<!ENTITY options.enableServiceWorkersTesting.tooltip "Turning this option on will enable the service workers testing features for all tabs that have the toolbox open.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.selectDefaultTools.label): This is the label for
|
||||
- the heading of group of checkboxes corresponding to the default developer
|
||||
- tools. -->
|
||||
|
|
|
@ -179,6 +179,7 @@ browser.jar:
|
|||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||
skin/classic/browser/preferences/in-content/default-profile-image.svg (../shared/incontentprefs/default-profile-image.svg)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||
skin/classic/browser/preferences/search.css (preferences/search.css)
|
||||
|
|
|
@ -284,6 +284,7 @@ browser.jar:
|
|||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||
skin/classic/browser/preferences/in-content/default-profile-image.svg (../shared/incontentprefs/default-profile-image.svg)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||
skin/classic/browser/preferences/search.css (preferences/search.css)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<path fill="#C3CFD8" d="M500-0.3c276.1,0,500,223.9,500,500s-223.9,500-500,500S0,775.8,0,499.7C0,223.5,223.9-0.3,500-0.3z"/>
|
||||
<circle fill="#FFFFFF" cx="500" cy="317" r="139.1"/>
|
||||
<path fill="#FFFFFF" d="M751.8,643.6L751.8,643.6c0.1-2.3,0.2-4.6,0.2-6.9c0-68-55.3-127-136.2-156.3L505.9,590.4h0
|
||||
c-0.4,29.8-1.4,58.8-2.8,86.6c-1,0.1-2,0.3-3.1,0.3s-2-0.2-3.1-0.3c-1.4-27.9-2.4-56.9-2.8-86.7h0L384.3,480.4
|
||||
C303.3,509.7,248,568.7,248,636.7c0,2.3,0.1,4.6,0.2,6.9l7.4,49.7c57.1,72,145.4,118.2,244.4,118.2c99,0,187.3-46.2,244.4-118.2
|
||||
L751.8,643.6z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 993 B |
|
@ -216,6 +216,22 @@ description > html|a {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
#fxaProfileImage {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border-width: 5px;
|
||||
border-color: red;
|
||||
background-image: url(chrome://browser/skin/preferences/in-content/default-profile-image.svg);
|
||||
background-size: contain;
|
||||
cursor: pointer;
|
||||
-moz-margin-end: 15px;
|
||||
}
|
||||
|
||||
#fxaProfileImage:hover {
|
||||
border-color: blue;
|
||||
}
|
||||
|
||||
#noFxaAccount {
|
||||
/* Overriding the margins from the base preferences.css theme file.
|
||||
These overrides can be simplified by fixing bug 1027174 */
|
||||
|
|
|
@ -207,6 +207,7 @@ browser.jar:
|
|||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||
skin/classic/browser/preferences/in-content/default-profile-image.svg (../shared/incontentprefs/default-profile-image.svg)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||
skin/classic/browser/preferences/search.css (preferences/search.css)
|
||||
|
|
|
@ -130,6 +130,7 @@ ifdef MOZ_FOLD_LIBS
|
|||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_DIR=$(ABS_DIST)/../config/external/sqlite
|
||||
endif # MOZ_FOLD_LIBS
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
|
||||
endif
|
||||
|
@ -357,6 +358,11 @@ GARBAGE += \
|
|||
endif # GCC_USE_GNU_LD
|
||||
endif # WINNT
|
||||
|
||||
IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
|
||||
IMPORT_LIB_DEST ?= $(DIST)/lib
|
||||
IMPORT_LIB_TARGET = target
|
||||
INSTALL_TARGETS += IMPORT_LIB
|
||||
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -31,11 +31,6 @@ ifdef LIBRARY
|
|||
ifdef DIST_INSTALL
|
||||
ifdef IS_COMPONENT
|
||||
$(error Shipping static component libs makes no sense.)
|
||||
else
|
||||
DIST_LIBRARY_FILES = $(LIBRARY)
|
||||
DIST_LIBRARY_DEST ?= $(DIST)/lib
|
||||
DIST_LIBRARY_TARGET = target
|
||||
INSTALL_TARGETS += DIST_LIBRARY
|
||||
endif
|
||||
endif # DIST_INSTALL
|
||||
endif # LIBRARY
|
||||
|
@ -47,21 +42,6 @@ SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
|
|||
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
|
||||
SHARED_LIBRARY_TARGET = target
|
||||
INSTALL_TARGETS += SHARED_LIBRARY
|
||||
|
||||
ifneq (,$(filter WINNT,$(OS_ARCH)))
|
||||
ifndef NO_INSTALL_IMPORT_LIBRARY
|
||||
IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
|
||||
endif # NO_INSTALL_IMPORT_LIBRARY
|
||||
else
|
||||
IMPORT_LIB_FILES = $(SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
IMPORT_LIB_DEST ?= $(DIST)/lib
|
||||
IMPORT_LIB_TARGET = target
|
||||
ifdef IMPORT_LIB_FILES
|
||||
INSTALL_TARGETS += IMPORT_LIB
|
||||
endif
|
||||
|
||||
endif # ! IS_COMPONENT
|
||||
endif # SHARED_LIBRARY
|
||||
|
||||
|
@ -72,13 +52,6 @@ HOST_PROGRAMS_TARGET = host
|
|||
INSTALL_TARGETS += HOST_PROGRAMS
|
||||
endif
|
||||
|
||||
ifdef HOST_LIBRARY
|
||||
HOST_LIBRARY_FILES = $(HOST_LIBRARY)
|
||||
HOST_LIBRARY_DEST ?= $(DIST)/host/lib
|
||||
HOST_LIBRARY_TARGET = host
|
||||
INSTALL_TARGETS += HOST_LIBRARY
|
||||
endif
|
||||
|
||||
endif # !NO_DIST_INSTALL
|
||||
|
||||
# EOF
|
||||
|
|
|
@ -2727,6 +2727,7 @@ MOZ_CHECK_HEADERS([linux/quota.h],,,[#include <sys/socket.h>])
|
|||
|
||||
dnl SCTP support - needs various network include headers
|
||||
MOZ_CHECK_HEADERS([linux/if_addr.h linux/rtnetlink.h],,,[#include <sys/socket.h>])
|
||||
MOZ_CHECK_HEADERS(sys/queue.h)
|
||||
|
||||
MOZ_CHECK_HEADERS(sys/types.h netinet/in.h byteswap.h)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
|||
[test_popup-navigates-children.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(Needs multiple window.open support, also uses docshelltreenode) b2g-debug(Needs multiple window.open support, also uses docshelltreenode) b2g-desktop(Needs multiple window.open support, also uses docshelltreenode)
|
||||
[test_reserved.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || android_version == '10' #too slow on Android 2.3 aws only; bug 1030403
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || android_version == '10' || android_version == '18' #too slow on Android 2.3 and 4.3 aws only; bug 1030403
|
||||
[test_sessionhistory.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #RANDOM # b2g-debug(Perma-orange on debug emulator builds) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
[test_sibling-matching-parent.html]
|
||||
|
|
|
@ -61,7 +61,7 @@ AnimationPlayer::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
|
|||
mHoldTime = previousCurrentTime;
|
||||
}
|
||||
|
||||
CancelPendingPlay();
|
||||
CancelPendingTasks();
|
||||
if (mReady) {
|
||||
// We may have already resolved mReady, but in that case calling
|
||||
// MaybeResolve is a no-op, so that's okay.
|
||||
|
@ -123,7 +123,12 @@ AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime)
|
|||
{
|
||||
SilentlySetCurrentTime(aSeekTime);
|
||||
|
||||
// Once pending pause tasks are supported, cancel that here.
|
||||
if (mPendingState == PendingState::PausePending) {
|
||||
CancelPendingTasks();
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSourceContent();
|
||||
PostUpdate();
|
||||
|
@ -160,7 +165,7 @@ AnimationPlayer::SilentlySetPlaybackRate(double aPlaybackRate)
|
|||
AnimationPlayState
|
||||
AnimationPlayer::PlayState() const
|
||||
{
|
||||
if (mIsPending) {
|
||||
if (mPendingState != PendingState::NotPending) {
|
||||
return AnimationPlayState::Pending;
|
||||
}
|
||||
|
||||
|
@ -267,7 +272,7 @@ AnimationPlayer::Tick()
|
|||
// it's possible that mPendingReadyTime is set to a time in the future.
|
||||
// In that case, we should wait until the next refresh driver tick before
|
||||
// resuming.
|
||||
if (mIsPending &&
|
||||
if (mPendingState != PendingState::NotPending &&
|
||||
!mPendingReadyTime.IsNull() &&
|
||||
mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
|
||||
ResumeAt(mPendingReadyTime.Value());
|
||||
|
@ -284,12 +289,11 @@ AnimationPlayer::Tick()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::StartOnNextTick(const Nullable<TimeDuration>& aReadyTime)
|
||||
AnimationPlayer::TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime)
|
||||
{
|
||||
// Normally we expect the play state to be pending but it's possible that,
|
||||
// due to the handling of possibly orphaned players in Tick() [coming
|
||||
// in a later patch in this series], this player got started whilst still
|
||||
// being in another document's pending player map.
|
||||
// due to the handling of possibly orphaned players in Tick(), this player got
|
||||
// started whilst still being in another document's pending player map.
|
||||
if (PlayState() != AnimationPlayState::Pending) {
|
||||
return;
|
||||
}
|
||||
|
@ -300,7 +304,7 @@ AnimationPlayer::StartOnNextTick(const Nullable<TimeDuration>& aReadyTime)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::StartNow()
|
||||
AnimationPlayer::TriggerNow()
|
||||
{
|
||||
MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
|
||||
"Expected to start a pending player");
|
||||
|
@ -334,8 +338,8 @@ AnimationPlayer::GetCurrentOrPendingStartTime() const
|
|||
void
|
||||
AnimationPlayer::Cancel()
|
||||
{
|
||||
if (mIsPending) {
|
||||
CancelPendingPlay();
|
||||
if (mPendingState != PendingState::NotPending) {
|
||||
CancelPendingTasks();
|
||||
if (mReady) {
|
||||
mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
}
|
||||
|
@ -350,7 +354,9 @@ AnimationPlayer::Cancel()
|
|||
bool
|
||||
AnimationPlayer::IsRunning() const
|
||||
{
|
||||
if (IsPaused() || !GetSource() || GetSource()->IsFinishedTransition()) {
|
||||
if (IsPausedOrPausing() ||
|
||||
!GetSource() ||
|
||||
GetSource()->IsFinishedTransition()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -424,6 +430,12 @@ AnimationPlayer::DoPlay()
|
|||
// need to pass a flag so that when we start playing due to a change in
|
||||
// animation-play-state we *don't* trigger finishing behavior.
|
||||
|
||||
bool reuseReadyPromise = false;
|
||||
if (mPendingState != PendingState::NotPending) {
|
||||
CancelPendingTasks();
|
||||
reuseReadyPromise = true;
|
||||
}
|
||||
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
if (mPlaybackRate > 0.0 &&
|
||||
(currentTime.IsNull())) {
|
||||
|
@ -439,17 +451,19 @@ AnimationPlayer::DoPlay()
|
|||
return;
|
||||
}
|
||||
|
||||
// Clear ready promise. We'll create a new one lazily.
|
||||
mReady = nullptr;
|
||||
|
||||
// Clear the start time until we resolve a new one
|
||||
mStartTime.SetNull();
|
||||
|
||||
mIsPending = true;
|
||||
if (!reuseReadyPromise) {
|
||||
// Clear ready promise. We'll create a new one lazily.
|
||||
mReady = nullptr;
|
||||
}
|
||||
|
||||
mPendingState = PendingState::PlayPending;
|
||||
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (!doc) {
|
||||
StartOnNextTick(Nullable<TimeDuration>());
|
||||
TriggerOnNextTick(Nullable<TimeDuration>());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -464,8 +478,8 @@ AnimationPlayer::DoPlay()
|
|||
void
|
||||
AnimationPlayer::DoPause()
|
||||
{
|
||||
if (mIsPending) {
|
||||
CancelPendingPlay();
|
||||
if (mPendingState == PendingState::PlayPending) {
|
||||
CancelPendingTasks();
|
||||
// Resolve the ready promise since we currently only use it for
|
||||
// players that are waiting to play. Later (in bug 1109390), we will
|
||||
// use this for players waiting to pause as well and then we won't
|
||||
|
@ -491,10 +505,11 @@ AnimationPlayer::ResumeAt(const TimeDuration& aResumeTime)
|
|||
// This method is only expected to be called for a player that is
|
||||
// waiting to play. We can easily adapt it to handle other states
|
||||
// but it's currently not necessary.
|
||||
MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
|
||||
"Expected to resume a pending player");
|
||||
MOZ_ASSERT(mPendingState == PendingState::PlayPending,
|
||||
"Expected to resume a play-pending player");
|
||||
MOZ_ASSERT(!mHoldTime.IsNull(),
|
||||
"A player in the pending state should have a resolved hold time");
|
||||
"A player in the play-pending state should have a resolved"
|
||||
" hold time");
|
||||
|
||||
if (mPlaybackRate != 0) {
|
||||
mStartTime.SetValue(aResumeTime - (mHoldTime.Value() / mPlaybackRate));
|
||||
|
@ -502,7 +517,7 @@ AnimationPlayer::ResumeAt(const TimeDuration& aResumeTime)
|
|||
} else {
|
||||
mStartTime.SetValue(aResumeTime);
|
||||
}
|
||||
mIsPending = false;
|
||||
mPendingState = PendingState::NotPending;
|
||||
|
||||
UpdateSourceContent();
|
||||
|
||||
|
@ -539,9 +554,9 @@ AnimationPlayer::PostUpdate()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::CancelPendingPlay()
|
||||
AnimationPlayer::CancelPendingTasks()
|
||||
{
|
||||
if (!mIsPending) {
|
||||
if (mPendingState == PendingState::NotPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -549,11 +564,15 @@ AnimationPlayer::CancelPendingPlay()
|
|||
if (doc) {
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
if (tracker) {
|
||||
tracker->RemovePlayPending(*this);
|
||||
if (mPendingState == PendingState::PlayPending) {
|
||||
tracker->RemovePlayPending(*this);
|
||||
} else {
|
||||
tracker->RemovePausePending(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mIsPending = false;
|
||||
mPendingState = PendingState::NotPending;
|
||||
mPendingReadyTime.SetNull();
|
||||
}
|
||||
|
||||
|
@ -574,11 +593,11 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
// when we have been painted.
|
||||
// * When we started playing we couldn't find a PendingPlayerTracker to
|
||||
// register with (perhaps the source content had no document) so we simply
|
||||
// set mIsPending in DoPlay and relied on this method to catch us on the
|
||||
// set mPendingState in DoPlay and relied on this method to catch us on the
|
||||
// next tick.
|
||||
|
||||
// If we're not pending we're ok.
|
||||
if (!mIsPending) {
|
||||
if (mPendingState == PendingState::NotPending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -598,12 +617,17 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
// PendingPlayerTracker then there's a good chance no one is tracking us.
|
||||
//
|
||||
// If we're wrong and another document is tracking us then, at worst, we'll
|
||||
// simply start the animation one tick too soon. That's better than never
|
||||
// starting the animation and is unlikely.
|
||||
// simply start/pause the animation one tick too soon. That's better than
|
||||
// never starting/pausing the animation and is unlikely.
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
return !doc ||
|
||||
!doc->GetPendingPlayerTracker() ||
|
||||
!doc->GetPendingPlayerTracker()->IsWaitingToPlay(*this);
|
||||
if (!doc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
return !tracker ||
|
||||
(!tracker->IsWaitingToPlay(*this) &&
|
||||
!tracker->IsWaitingToPause(*this));
|
||||
}
|
||||
|
||||
StickyTimeDuration
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
explicit AnimationPlayer(AnimationTimeline* aTimeline)
|
||||
: mTimeline(aTimeline)
|
||||
, mPlaybackRate(1.0)
|
||||
, mIsPending(false)
|
||||
, mPendingState(PendingState::NotPending)
|
||||
, mIsRunningOnCompositor(false)
|
||||
, mIsPreviousStateFinished(false)
|
||||
, mIsRelevant(false)
|
||||
|
@ -107,6 +107,8 @@ public:
|
|||
void Tick();
|
||||
|
||||
/**
|
||||
* Set the time to use for starting or pausing a pending player.
|
||||
*
|
||||
* Typically, when a player is played, it does not start immediately but is
|
||||
* added to a table of pending players on the document of its source content.
|
||||
* In the meantime it sets its hold time to the time from which playback
|
||||
|
@ -119,9 +121,9 @@ public:
|
|||
* players do start, they can be timed from the point when painting
|
||||
* completed.
|
||||
*
|
||||
* After calling StartOnNextTick, players remain in the pending state until
|
||||
* After calling TriggerOnNextTick, players remain in the pending state until
|
||||
* the next refresh driver tick. At that time they transition out of the
|
||||
* pending state using the time passed to StartOnNextTick as the effective
|
||||
* pending state using the time passed to TriggerOnNextTick as the effective
|
||||
* time at which they resumed.
|
||||
*
|
||||
* This approach means that any setup time required for performing the
|
||||
|
@ -145,20 +147,27 @@ public:
|
|||
* between triggering an animation and its effective start is unacceptably
|
||||
* long.
|
||||
*
|
||||
* For pausing, we apply the same asynchronous approach. This is so that we
|
||||
* synchronize with animations that are running on the compositor. Otherwise
|
||||
* if the main thread lags behind the compositor there will be a noticeable
|
||||
* jump backwards when the main thread takes over. Even though main thread
|
||||
* animations could be paused immediately, we do it asynchronously for
|
||||
* consistency and so that animations paused together end up in step.
|
||||
*
|
||||
* Note that the caller of this method is responsible for removing the player
|
||||
* from any PendingPlayerTracker it may have been added to.
|
||||
*/
|
||||
void StartOnNextTick(const Nullable<TimeDuration>& aReadyTime);
|
||||
void TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime);
|
||||
|
||||
// Testing only: Start a pending player using the current timeline time.
|
||||
// This is used to support existing tests that expect animations to begin
|
||||
// immediately. Ideally we would rewrite the those tests and get rid of this
|
||||
// method, but there are a lot of them.
|
||||
// Testing only: Start or pause a pending player using the current timeline
|
||||
// time. This is used to support existing tests that expect animations to
|
||||
// begin immediately. Ideally we would rewrite the those tests and get rid of
|
||||
// this method, but there are a lot of them.
|
||||
//
|
||||
// As with StartOnNextTick, the caller of this method is responsible for
|
||||
// As with TriggerOnNextTick, the caller of this method is responsible for
|
||||
// removing the player from any PendingPlayerTracker it may have been added
|
||||
// to.
|
||||
void StartNow();
|
||||
void TriggerNow();
|
||||
|
||||
/**
|
||||
* When StartOnNextTick is called, we store the ready time but we don't apply
|
||||
|
@ -182,17 +191,24 @@ public:
|
|||
|
||||
void Cancel();
|
||||
|
||||
const nsString& Name() const {
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mSource ? mSource->Name() : EmptyString();
|
||||
}
|
||||
|
||||
bool IsPaused() const { return PlayState() == AnimationPlayState::Paused; }
|
||||
bool IsPausedOrPausing() const
|
||||
{
|
||||
return PlayState() == AnimationPlayState::Paused ||
|
||||
mPendingState == PendingState::PausePending;
|
||||
}
|
||||
bool IsRunning() const;
|
||||
|
||||
bool HasCurrentSource() const {
|
||||
bool HasCurrentSource() const
|
||||
{
|
||||
return GetSource() && GetSource()->IsCurrent();
|
||||
}
|
||||
bool HasInEffectSource() const {
|
||||
bool HasInEffectSource() const
|
||||
{
|
||||
return GetSource() && GetSource()->IsInEffect();
|
||||
}
|
||||
|
||||
|
@ -226,10 +242,12 @@ protected:
|
|||
void UpdateSourceContent();
|
||||
void FlushStyle() const;
|
||||
void PostUpdate();
|
||||
// Remove this player from the pending player tracker and resets mIsPending
|
||||
// as necessary. The caller is responsible for resolving or aborting the
|
||||
// mReady promise as necessary.
|
||||
void CancelPendingPlay();
|
||||
/**
|
||||
* Remove this player from the pending player tracker and reset
|
||||
* mPendingState as necessary. The caller is responsible for resolving or
|
||||
* aborting the mReady promise as necessary.
|
||||
*/
|
||||
void CancelPendingTasks();
|
||||
|
||||
bool IsPossiblyOrphanedPendingPlayer() const;
|
||||
StickyTimeDuration SourceContentEnd() const;
|
||||
|
@ -252,12 +270,15 @@ protected:
|
|||
// This object is lazily created by GetReady.
|
||||
nsRefPtr<Promise> mReady;
|
||||
|
||||
// Indicates if the player is in the pending state. We use this rather
|
||||
// than checking if this player is tracked by a PendingPlayerTracker.
|
||||
// This is because the PendingPlayerTracker is associated with the source
|
||||
// content's document but we need to know if we're pending even if the
|
||||
// source content loses association with its document.
|
||||
bool mIsPending;
|
||||
// Indicates if the player is in the pending state (and what state it is
|
||||
// waiting to enter when it finished pending). We use this rather than
|
||||
// checking if this player is tracked by a PendingPlayerTracker because the
|
||||
// player will continue to be pending even after it has been removed from the
|
||||
// PendingPlayerTracker while it is waiting for the next tick
|
||||
// (see TriggerOnNextTick for details).
|
||||
enum class PendingState { NotPending, PlayPending, PausePending };
|
||||
PendingState mPendingState;
|
||||
|
||||
bool mIsRunningOnCompositor;
|
||||
// Indicates whether we were in the finished state during our
|
||||
// most recent unthrottled sample (our last ComposeStyle call).
|
||||
|
|
|
@ -13,15 +13,19 @@ using namespace mozilla;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PendingPlayerTracker, mPlayPendingSet, mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION(PendingPlayerTracker,
|
||||
mPlayPendingSet,
|
||||
mPausePendingSet,
|
||||
mDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PendingPlayerTracker, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingPlayerTracker, Release)
|
||||
|
||||
void
|
||||
PendingPlayerTracker::AddPlayPending(dom::AnimationPlayer& aPlayer)
|
||||
PendingPlayerTracker::AddPending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet)
|
||||
{
|
||||
mPlayPendingSet.PutEntry(&aPlayer);
|
||||
aSet.PutEntry(&aPlayer);
|
||||
|
||||
// Schedule a paint. Otherwise animations that don't trigger a paint by
|
||||
// themselves (e.g. CSS animations with an empty keyframes rule) won't
|
||||
|
@ -30,20 +34,22 @@ PendingPlayerTracker::AddPlayPending(dom::AnimationPlayer& aPlayer)
|
|||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::RemovePlayPending(dom::AnimationPlayer& aPlayer)
|
||||
PendingPlayerTracker::RemovePending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet)
|
||||
{
|
||||
mPlayPendingSet.RemoveEntry(&aPlayer);
|
||||
aSet.RemoveEntry(&aPlayer);
|
||||
}
|
||||
|
||||
bool
|
||||
PendingPlayerTracker::IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const
|
||||
PendingPlayerTracker::IsWaiting(const dom::AnimationPlayer& aPlayer,
|
||||
const AnimationPlayerSet& aSet) const
|
||||
{
|
||||
return mPlayPendingSet.Contains(const_cast<dom::AnimationPlayer*>(&aPlayer));
|
||||
return aSet.Contains(const_cast<dom::AnimationPlayer*>(&aPlayer));
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
|
||||
void* aReadyTime)
|
||||
TriggerPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
|
||||
void* aReadyTime)
|
||||
{
|
||||
dom::AnimationPlayer* player = aKey->GetKey();
|
||||
dom::AnimationTimeline* timeline = player->Timeline();
|
||||
|
@ -51,38 +57,43 @@ StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
|
|||
// When the timeline's refresh driver is under test control, its values
|
||||
// have no correspondance to wallclock times so we shouldn't try to convert
|
||||
// aReadyTime (which is a wallclock time) to a timeline value. Instead, the
|
||||
// animation player will be started when the refresh driver is next
|
||||
// advanced since this will trigger a call to StartPendingPlayersNow.
|
||||
// animation player will be started/paused when the refresh driver is next
|
||||
// advanced since this will trigger a call to TriggerPendingPlayersNow.
|
||||
if (timeline->IsUnderTestControl()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
Nullable<TimeDuration> readyTime =
|
||||
timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime));
|
||||
player->StartOnNextTick(readyTime);
|
||||
player->TriggerOnNextTick(readyTime);
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime)
|
||||
PendingPlayerTracker::TriggerPendingPlayersOnNextTick(const TimeStamp&
|
||||
aReadyTime)
|
||||
{
|
||||
mPlayPendingSet.EnumerateEntries(StartPlayerAtTime,
|
||||
mPlayPendingSet.EnumerateEntries(TriggerPlayerAtTime,
|
||||
const_cast<TimeStamp*>(&aReadyTime));
|
||||
mPausePendingSet.EnumerateEntries(TriggerPlayerAtTime,
|
||||
const_cast<TimeStamp*>(&aReadyTime));
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
StartPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
|
||||
TriggerPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
|
||||
{
|
||||
aKey->GetKey()->StartNow();
|
||||
aKey->GetKey()->TriggerNow();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::StartPendingPlayersNow()
|
||||
PendingPlayerTracker::TriggerPendingPlayersNow()
|
||||
{
|
||||
mPlayPendingSet.EnumerateEntries(StartPlayerNow, nullptr);
|
||||
mPlayPendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
|
||||
mPlayPendingSet.Clear();
|
||||
mPausePendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
|
||||
mPausePendingSet.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -25,13 +25,41 @@ public:
|
|||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker)
|
||||
|
||||
void AddPlayPending(dom::AnimationPlayer& aPlayer);
|
||||
void RemovePlayPending(dom::AnimationPlayer& aPlayer);
|
||||
bool IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const;
|
||||
void AddPlayPending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPause(aPlayer),
|
||||
"Player is already waiting to pause");
|
||||
AddPending(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
void RemovePlayPending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
RemovePending(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
bool IsWaitingToPlay(const dom::AnimationPlayer& aPlayer) const
|
||||
{
|
||||
return IsWaiting(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
|
||||
void StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime);
|
||||
void StartPendingPlayersNow();
|
||||
bool HasPendingPlayers() const { return mPlayPendingSet.Count() > 0; }
|
||||
void AddPausePending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPlay(aPlayer),
|
||||
"Player is already waiting to play");
|
||||
AddPending(aPlayer, mPausePendingSet);
|
||||
}
|
||||
void RemovePausePending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
RemovePending(aPlayer, mPausePendingSet);
|
||||
}
|
||||
bool IsWaitingToPause(const dom::AnimationPlayer& aPlayer) const
|
||||
{
|
||||
return IsWaiting(aPlayer, mPausePendingSet);
|
||||
}
|
||||
|
||||
void TriggerPendingPlayersOnNextTick(const TimeStamp& aReadyTime);
|
||||
void TriggerPendingPlayersNow();
|
||||
bool HasPendingPlayers() const {
|
||||
return mPlayPendingSet.Count() > 0 || mPausePendingSet.Count() > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
~PendingPlayerTracker() { }
|
||||
|
@ -41,7 +69,15 @@ private:
|
|||
typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>>
|
||||
AnimationPlayerSet;
|
||||
|
||||
void AddPending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet);
|
||||
void RemovePending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet);
|
||||
bool IsWaiting(const dom::AnimationPlayer& aPlayer,
|
||||
const AnimationPlayerSet& aSet) const;
|
||||
|
||||
AnimationPlayerSet mPlayPendingSet;
|
||||
AnimationPlayerSet mPausePendingSet;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,10 +31,11 @@ async_test(function(t) {
|
|||
player.ready.then(waitForFrame).then(t.step_func(function() {
|
||||
assert_true(getMarginLeft(cs) > previousAnimVal,
|
||||
'margin-left is initially increasing');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
|
||||
player.pause();
|
||||
return player.ready.then(waitForFrame);
|
||||
return player.ready;
|
||||
})).then(t.step_func(function() {
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
return waitForFrame();
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left does not increase after calling pause()');
|
||||
|
@ -102,13 +103,14 @@ async_test(function(t) {
|
|||
}).then(t.step_func(function() {
|
||||
assert_equals(cs.animationPlayState, 'running',
|
||||
'animation-play-state is running');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
div.style.animationPlayState = 'paused';
|
||||
cs.animationPlayState; // Trigger style resolution
|
||||
return waitForFrame();
|
||||
return player.ready;
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(cs.animationPlayState, 'paused',
|
||||
'animation-play-state is paused');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
return waitForFrame();
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'Animated value of margin-left does not change when'
|
||||
+ ' paused by style');
|
||||
|
@ -152,7 +154,7 @@ async_test(function(t) {
|
|||
|
||||
// Unlike the previous test for play(), since calling pause() is sticky,
|
||||
// we'll apply it even if the underlying style also says we're paused.
|
||||
//
|
||||
//
|
||||
// We would like to test that implementations flush styles before running
|
||||
// pause() but actually there's no style we can currently set that will
|
||||
// change the behavior of pause(). That may change in the future
|
||||
|
@ -164,9 +166,9 @@ async_test(function(t) {
|
|||
player.pause();
|
||||
var previousAnimVal = getMarginLeft(cs);
|
||||
|
||||
waitForFrame().then(t.step_func(function() {
|
||||
player.ready.then(waitForFrame).then(t.step_func(function() {
|
||||
assert_equals(cs.animationPlayState, 'running',
|
||||
'animation-play-state is paused');
|
||||
'animation-play-state is running');
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'Paused value of margin-left does not change');
|
||||
t.done();
|
||||
|
|
|
@ -588,28 +588,25 @@ async_test(function(t) {
|
|||
div.style.animation = 'anim 100s';
|
||||
|
||||
var player = div.getAnimationPlayers()[0];
|
||||
var pauseTime;
|
||||
|
||||
player.ready.then(t.step_func(function() {
|
||||
var savedCurrentTime = player.currentTime;
|
||||
|
||||
assert_not_equals(player.currentTime, null,
|
||||
'AnimationPlayer.currentTime not null on ready Promise resolve');
|
||||
|
||||
var prePauseCurrentTime = player.currentTime;
|
||||
|
||||
player.pause();
|
||||
// After bug 1109390 we will need to wait here for the ready promise again
|
||||
|
||||
assert_equals(player.currentTime, prePauseCurrentTime,
|
||||
'AnimationPlayer.currentTime is unchanged after AnimationPlayer.pause()');
|
||||
assert_equals(player.playState, 'paused',
|
||||
'AnimationPlayer.playState is "paused" after pause() call');
|
||||
return player.ready;
|
||||
})).then(t.step_func(function() {
|
||||
pauseTime = player.currentTime;
|
||||
return waitForFrame();
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(player.currentTime, pauseTime,
|
||||
'AnimationPlayer.currentTime is unchanged after pausing');
|
||||
})).catch(t.step_func(function(reason) {
|
||||
assert_unreached(reason);
|
||||
})).then(function() {
|
||||
t.done();
|
||||
});
|
||||
}, 'AnimationPlayer.currentTime after paused');
|
||||
}, 'AnimationPlayer.currentTime after pausing');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -24,23 +24,37 @@ async_test(function(t) {
|
|||
}));
|
||||
}, 'Player returns correct playState when running');
|
||||
|
||||
test(function(t) {
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var cs = window.getComputedStyle(div);
|
||||
div.style.animation = 'anim 1000s paused';
|
||||
|
||||
var player = div.getAnimationPlayers()[0];
|
||||
assert_equals(player.playState, 'paused');
|
||||
// FIXME: When we turn on async pausing later in this patch series, enable
|
||||
// this
|
||||
// assert_equals(player.playState, 'pending');
|
||||
|
||||
player.ready.then(t.step_func(function() {
|
||||
assert_equals(player.playState, 'paused');
|
||||
t.done();
|
||||
}));
|
||||
}, 'Player returns correct playState when paused');
|
||||
|
||||
test(function(t) {
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var cs = window.getComputedStyle(div);
|
||||
div.style.animation = 'anim 1000s';
|
||||
|
||||
var player = div.getAnimationPlayers()[0];
|
||||
player.pause();
|
||||
assert_equals(player.playState, 'paused');
|
||||
// FIXME: When we turn on async pausing later in this patch series, enable
|
||||
// this
|
||||
// assert_equals(player.playState, 'pending');
|
||||
|
||||
player.ready.then(t.step_func(function() {
|
||||
assert_equals(player.playState, 'paused');
|
||||
t.done();
|
||||
}));
|
||||
}, 'Player.playState updates when paused by script');
|
||||
|
||||
test(function(t) {
|
||||
|
|
|
@ -618,8 +618,8 @@ async_test(function(t) {
|
|||
'AnimationPlayer.startTime not null on ready Promise resolve');
|
||||
|
||||
player.pause();
|
||||
// After bug 1109390 we will need to wait here for the ready promise again
|
||||
|
||||
return player.ready;
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(player.startTime, null,
|
||||
'AnimationPlayer.startTime is null after paused');
|
||||
assert_equals(player.playState, 'paused',
|
||||
|
|
|
@ -384,8 +384,8 @@ async_test(function(t) {
|
|||
'AnimationPlayer.startTime not null on ready Promise resolve');
|
||||
|
||||
player.pause();
|
||||
// After bug 1109390 we will need to wait here for the ready promise again
|
||||
|
||||
return player.ready;
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(player.startTime, null,
|
||||
'AnimationPlayer.startTime is null after paused');
|
||||
assert_equals(player.playState, 'paused',
|
||||
|
|
|
@ -483,7 +483,7 @@ WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aR
|
|||
{
|
||||
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
nsPIDOMWindow* win = xpc::WindowGlobalOrNull(JS::CurrentGlobalOrNull(aCx));
|
||||
nsPIDOMWindow* win = xpc::CurrentWindowOrNull(aCx);
|
||||
xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
xpcReport->LogToConsole();
|
||||
|
|
|
@ -2595,7 +2595,7 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
|
|||
if (doc) {
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
if (tracker) {
|
||||
tracker->StartPendingPlayersNow();
|
||||
tracker->TriggerPendingPlayersNow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3985,6 +3985,32 @@ nsDOMWindowUtils::GetFramesReflowed(uint64_t* aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetServiceWorkersTestingEnabled(bool aEnabled)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
window->SetServiceWorkersTestingEnabled(aEnabled);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetServiceWorkersTestingEnabled(bool *aEnabled)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
*aEnabled = window->GetServiceWorkersTestingEnabled();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
|
||||
|
|
|
@ -884,8 +884,7 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
|
|||
|
||||
// Don't show remote iframe if we are waiting for the completion of reflow.
|
||||
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1383,6 +1382,12 @@ nsFrameLoader::StartDestroy()
|
|||
}
|
||||
}
|
||||
|
||||
// If the TabParent has installed any event listeners on the window, this is
|
||||
// its last chance to remove them while we're still in the document.
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->RemoveWindowListeners();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
bool dynamicSubframeRemoval = false;
|
||||
if (mOwnerContent) {
|
||||
|
@ -2058,8 +2063,7 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
|
|||
ScreenIntSize size = aIFrame->GetSubdocumentSize();
|
||||
nsIntRect dimensions;
|
||||
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
|
||||
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -229,6 +229,9 @@ public:
|
|||
void ActivateUpdateHitRegion();
|
||||
void DeactivateUpdateHitRegion();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
private:
|
||||
|
||||
void SetOwnerContent(mozilla::dom::Element* aContent);
|
||||
|
@ -284,9 +287,6 @@ private:
|
|||
nsresult MaybeCreateDocShell();
|
||||
nsresult EnsureMessageManager();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
// Updates the subdocument position and size. This gets called only
|
||||
// when we have our own in-process DocShell.
|
||||
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
|
||||
|
|
|
@ -584,7 +584,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
|
|||
mOuterWindow(aOuterWindow),
|
||||
// Make sure no actual window ends up with mWindowID == 0
|
||||
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
|
||||
mMarkedCCGeneration(0)
|
||||
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false)
|
||||
{}
|
||||
|
||||
nsPIDOMWindow::~nsPIDOMWindow() {}
|
||||
|
|
|
@ -91,6 +91,13 @@
|
|||
#endif
|
||||
#endif // XP_WIN
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// HandlePluginCrashed() and HandlePluginInstantiated() needed from here to
|
||||
// fix bug 1147521. Should later be replaced by proper interface methods,
|
||||
// maybe on nsIObjectLoadingContext.
|
||||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
static const char *kPrefJavaMIME = "plugin.java.mime";
|
||||
|
@ -867,6 +874,10 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
|
|||
NS_LITERAL_STRING("PluginInstantiated"));
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
HTMLObjectElement::HandlePluginInstantiated(thisContent->AsElement());
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2723,14 +2734,19 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
|||
LOG(("OBJLC [%p]: Plugin Crashed, queuing crash event", this));
|
||||
NS_ASSERTION(mType == eType_Plugin, "PluginCrashed at non-plugin type");
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
HTMLObjectElement::HandlePluginCrashed(thisContent->AsElement());
|
||||
#endif
|
||||
|
||||
PluginDestroyed();
|
||||
|
||||
// Switch to fallback/crashed state, notify
|
||||
LoadFallback(eFallbackCrashed, true);
|
||||
|
||||
// send nsPluginCrashedEvent
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
// Note that aPluginTag in invalidated after we're called, so copy
|
||||
// out any data we need now.
|
||||
|
|
|
@ -186,6 +186,18 @@ public:
|
|||
|
||||
float GetAudioGlobalVolume();
|
||||
|
||||
virtual void SetServiceWorkersTestingEnabled(bool aEnabled)
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
mServiceWorkersTestingEnabled = aEnabled;
|
||||
}
|
||||
|
||||
bool GetServiceWorkersTestingEnabled()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
return mServiceWorkersTestingEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Lazily instantiate an about:blank document if necessary, and if
|
||||
// we have what it takes to do so.
|
||||
|
@ -798,6 +810,10 @@ protected:
|
|||
bool mHasNotifiedGlobalCreated;
|
||||
|
||||
uint32_t mMarkedCCGeneration;
|
||||
|
||||
// Let the service workers plumbing know that some feature are enabled while
|
||||
// testing.
|
||||
bool mServiceWorkersTestingEnabled;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1147026 - CSP should ignore query string when checking a resource load</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="testdiv">blocked</div>
|
||||
<script src="http://test1.example.com/tests/dom/base/test/csp/file_csp_path_matching.js?val=foo"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -86,6 +86,7 @@ support-files =
|
|||
file_self_none_as_hostname_confusion.html
|
||||
file_self_none_as_hostname_confusion.html^headers^
|
||||
file_csp_path_matching.html
|
||||
file_csp_path_matching_incl_query.html
|
||||
file_csp_path_matching.js
|
||||
file_csp_path_matching_redirect.html
|
||||
file_csp_path_matching_redirect_server.sjs
|
||||
|
|
|
@ -79,9 +79,14 @@ function loadNextTest() {
|
|||
}
|
||||
else {
|
||||
policy = policies[counter++];
|
||||
var src = "file_csp_testserver.sjs";
|
||||
var src = "file_csp_testserver.sjs?file=";
|
||||
// append the file that should be served
|
||||
src += "?file=" + escape("tests/dom/base/test/csp/file_csp_path_matching.html");
|
||||
src += (counter % 2 == 0)
|
||||
// load url including ref: example.com#foo
|
||||
? escape("tests/dom/base/test/csp/file_csp_path_matching.html")
|
||||
// load url including query: example.com?val=foo (bug 1147026)
|
||||
: escape("tests/dom/base/test/csp/file_csp_path_matching_incl_query.html");
|
||||
|
||||
// append the CSP that should be used to serve the file
|
||||
src += "&csp=" + escape("default-src 'none'; script-src " + policy[1]);
|
||||
|
||||
|
|
|
@ -1525,7 +1525,7 @@ DOMInterfaces = {
|
|||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDebuggerGlobalScope',
|
||||
'implicitJSContext': [
|
||||
'dump', 'global',
|
||||
'dump', 'global', 'reportError',
|
||||
],
|
||||
},
|
||||
|
||||
|
|
|
@ -243,16 +243,14 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual nsresult GetLineno(int32_t* aLineNo)
|
||||
virtual int32_t GetLineno()
|
||||
{
|
||||
*aLineNo = mLineno;
|
||||
return NS_OK;
|
||||
return mLineno;
|
||||
}
|
||||
|
||||
virtual nsresult GetColNo(int32_t* aColNo)
|
||||
virtual int32_t GetColNo()
|
||||
{
|
||||
*aColNo = mColNo;
|
||||
return NS_OK;
|
||||
return mColNo;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStackFrame> mCaller;
|
||||
|
@ -318,8 +316,8 @@ protected:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual nsresult GetLineno(int32_t* aLineNo) override;
|
||||
virtual nsresult GetColNo(int32_t* aColNo) override;
|
||||
virtual int32_t GetLineno() override;
|
||||
virtual int32_t GetColNo() override;
|
||||
|
||||
private:
|
||||
virtual ~JSStackFrame();
|
||||
|
@ -437,7 +435,11 @@ GetValueIfNotCached(JSContext* aCx, JSObject* aStack,
|
|||
/* readonly attribute AString filename; */
|
||||
NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
aFilename.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSString*> filename(cx);
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -449,7 +451,9 @@ NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename)
|
|||
|
||||
nsAutoJSString str;
|
||||
if (!str.init(cx, filename)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_ClearPendingException(cx);
|
||||
aFilename.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
aFilename = str;
|
||||
|
||||
|
@ -476,7 +480,11 @@ NS_IMETHODIMP StackFrame::GetFilename(nsAString& aFilename)
|
|||
/* readonly attribute AString name; */
|
||||
NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
aFunction.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSString*> name(cx);
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -491,7 +499,9 @@ NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
|
|||
if (name) {
|
||||
nsAutoJSString str;
|
||||
if (!str.init(cx, name)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_ClearPendingException(cx);
|
||||
aFunction.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
aFunction = str;
|
||||
} else {
|
||||
|
@ -519,10 +529,13 @@ NS_IMETHODIMP StackFrame::GetName(nsAString& aFunction)
|
|||
}
|
||||
|
||||
// virtual
|
||||
nsresult
|
||||
JSStackFrame::GetLineno(int32_t* aLineNo)
|
||||
int32_t
|
||||
JSStackFrame::GetLineno()
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
uint32_t line;
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -530,30 +543,32 @@ JSStackFrame::GetLineno(int32_t* aLineNo)
|
|||
&canCache, &useCachedValue, &line);
|
||||
|
||||
if (useCachedValue) {
|
||||
return StackFrame::GetLineno(aLineNo);
|
||||
return StackFrame::GetLineno();
|
||||
}
|
||||
|
||||
*aLineNo = line;
|
||||
|
||||
if (canCache) {
|
||||
mLineno = line;
|
||||
mLinenoInitialized = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return line;
|
||||
}
|
||||
|
||||
/* readonly attribute int32_t lineNumber; */
|
||||
NS_IMETHODIMP StackFrame::GetLineNumber(int32_t* aLineNumber)
|
||||
{
|
||||
return GetLineno(aLineNumber);
|
||||
*aLineNumber = GetLineno();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// virtual
|
||||
nsresult
|
||||
JSStackFrame::GetColNo(int32_t* aColNo)
|
||||
int32_t
|
||||
JSStackFrame::GetColNo()
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
uint32_t col;
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -561,23 +576,22 @@ JSStackFrame::GetColNo(int32_t* aColNo)
|
|||
&canCache, &useCachedValue, &col);
|
||||
|
||||
if (useCachedValue) {
|
||||
return StackFrame::GetColNo(aColNo);
|
||||
return StackFrame::GetColNo();
|
||||
}
|
||||
|
||||
*aColNo = col;
|
||||
|
||||
if (canCache) {
|
||||
mColNo = col;
|
||||
mColNoInitialized = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return col;
|
||||
}
|
||||
|
||||
/* readonly attribute int32_t columnNumber; */
|
||||
NS_IMETHODIMP StackFrame::GetColumnNumber(int32_t* aColumnNumber)
|
||||
{
|
||||
return GetColNo(aColumnNumber);
|
||||
*aColumnNumber = GetColNo();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute AUTF8String sourceLine; */
|
||||
|
@ -590,7 +604,11 @@ NS_IMETHODIMP StackFrame::GetSourceLine(nsACString& aSourceLine)
|
|||
/* readonly attribute AString asyncCause; */
|
||||
NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
aAsyncCause.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSString*> asyncCause(cx);
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -605,7 +623,9 @@ NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause)
|
|||
if (asyncCause) {
|
||||
nsAutoJSString str;
|
||||
if (!str.init(cx, asyncCause)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_ClearPendingException(cx);
|
||||
aAsyncCause.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
aAsyncCause = str;
|
||||
} else {
|
||||
|
@ -635,7 +655,11 @@ NS_IMETHODIMP StackFrame::GetAsyncCause(nsAString& aAsyncCause)
|
|||
/* readonly attribute nsIStackFrame asyncCaller; */
|
||||
NS_IMETHODIMP JSStackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
*aAsyncCaller = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> asyncCallerObj(cx);
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -668,7 +692,11 @@ NS_IMETHODIMP StackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
|
|||
/* readonly attribute nsIStackFrame caller; */
|
||||
NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
*aCaller = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> callerObj(cx);
|
||||
bool canCache = false, useCachedValue = false;
|
||||
|
@ -706,7 +734,11 @@ NS_IMETHODIMP StackFrame::GetCaller(nsIStackFrame** aCaller)
|
|||
|
||||
NS_IMETHODIMP JSStackFrame::GetFormattedStack(nsAString& aStack)
|
||||
{
|
||||
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
|
||||
if (!mStack) {
|
||||
aStack.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Sadly we can't use GetValueIfNotCached here, because our getter
|
||||
// returns bool, not JS::SavedFrameResult. Maybe it's possible to
|
||||
// make the templates more complicated to deal, but in the meantime
|
||||
|
@ -727,12 +759,16 @@ NS_IMETHODIMP JSStackFrame::GetFormattedStack(nsAString& aStack)
|
|||
|
||||
JS::Rooted<JSString*> formattedStack(cx);
|
||||
if (!JS::StringifySavedFrameStack(cx, stack, &formattedStack)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
JS_ClearPendingException(cx);
|
||||
aStack.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoJSString str;
|
||||
if (!str.init(cx, formattedStack)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_ClearPendingException(cx);
|
||||
aStack.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aStack = str;
|
||||
|
@ -787,9 +823,7 @@ NS_IMETHODIMP StackFrame::ToString(nsACString& _retval)
|
|||
funname.AssignLiteral("<TOP_LEVEL>");
|
||||
}
|
||||
|
||||
int32_t lineno;
|
||||
rv = GetLineno(&lineno);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
int32_t lineno = GetLineno();
|
||||
|
||||
static const char format[] = "%s frame :: %s :: %s :: line %d";
|
||||
_retval.AppendPrintf(format, frametype,
|
||||
|
|
|
@ -17,7 +17,7 @@ skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in
|
|||
[webgl-mochitest/test_implicit_color_buffer_float.html]
|
||||
[webgl-mochitest/test_highp_fs.html]
|
||||
[webgl-mochitest/test_no_arr_points.html]
|
||||
skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942
|
||||
skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
|
||||
[webgl-mochitest/test_noprog_draw.html]
|
||||
[webgl-mochitest/test_privileged_exts.html]
|
||||
[webgl-mochitest/test_texsubimage_float.html]
|
||||
|
|
|
@ -1176,7 +1176,7 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
nsPoint ptInTarget = ptInRoot + rootFrame->GetOffsetToCrossDoc(targetFrame);
|
||||
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
int32_t targetAPD = targetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
ptInTarget = ptInTarget.ConvertAppUnits(rootAPD, targetAPD);
|
||||
ptInTarget = ptInTarget.ScaleToOtherAppUnits(rootAPD, targetAPD);
|
||||
|
||||
nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame);
|
||||
nsIFrame::ContentOffsets contentOffsets =
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifdef XP_MACOSX
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "nsFocusManager.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -151,6 +152,22 @@ private:
|
|||
void
|
||||
HTMLObjectElement::OnFocusBlurPlugin(Element* aElement, bool aFocus)
|
||||
{
|
||||
// In general we don't want to call nsIWidget::SetPluginFocused() for any
|
||||
// Element that doesn't have a plugin running. But if SetPluginFocused(true)
|
||||
// was just called for aElement while it had a plugin running, we want to
|
||||
// make sure nsIWidget::SetPluginFocused(false) gets called for it now, even
|
||||
// if aFocus is true.
|
||||
if (aFocus) {
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aElement);
|
||||
bool hasRunningPlugin = false;
|
||||
if (olc) {
|
||||
olc->GetHasRunningPlugin(&hasRunningPlugin);
|
||||
}
|
||||
if (!hasRunningPlugin) {
|
||||
aFocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFocus || aElement == sLastFocused) {
|
||||
if (!aFocus) {
|
||||
sLastFocused = nullptr;
|
||||
|
@ -163,6 +180,29 @@ HTMLObjectElement::OnFocusBlurPlugin(Element* aElement, bool aFocus)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLObjectElement::HandlePluginCrashed(Element* aElement)
|
||||
{
|
||||
OnFocusBlurPlugin(aElement, false);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLObjectElement::HandlePluginInstantiated(Element* aElement)
|
||||
{
|
||||
// If aElement is already focused when a plugin is instantiated, we need
|
||||
// to initiate a call to nsIWidget::SetPluginFocused(true). Otherwise
|
||||
// keyboard input won't work in a click-to-play plugin until aElement
|
||||
// loses focus and regains it.
|
||||
nsIContent* focusedContent = nullptr;
|
||||
nsFocusManager *fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
focusedContent = fm->GetFocusedContent();
|
||||
}
|
||||
if (SameCOMIdentity(focusedContent, aElement)) {
|
||||
OnFocusBlurPlugin(aElement, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLObjectElement::HandleFocusBlurPlugin(Element* aElement,
|
||||
WidgetEvent* aEvent)
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
// Helper methods
|
||||
static void OnFocusBlurPlugin(Element* aElement, bool aFocus);
|
||||
static void HandleFocusBlurPlugin(Element* aElement, WidgetEvent* aEvent);
|
||||
static void HandlePluginCrashed(Element* aElement);
|
||||
static void HandlePluginInstantiated(Element* aElement);
|
||||
// Weak pointer. Null if last action was blur.
|
||||
static Element* sLastFocused;
|
||||
#endif
|
||||
|
|
|
@ -28,13 +28,13 @@ skip-if = buildapp == 'mulet'
|
|||
[test_input_color_picker_initial.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_input_color_picker_popup.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet' || android_version == '18' # Android, bug 1147974
|
||||
[test_input_color_picker_update.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet' || android_version == '18' # Android, bug 1147974
|
||||
[test_input_defaultValue.html]
|
||||
[test_input_email.html]
|
||||
[test_input_event.html]
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop and mulet specific, initial triage
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') || android_version == '18' #Bug 931116, b2g desktop and mulet specific, initial triage; on Android, bug 1147974
|
||||
[test_input_file_picker.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(5 failures out of 139 and timing out, bug 901581) b2g-debug(5 failures out of 139 and timing out, bug 901581) b2g-desktop(5 failures out of 139 and timing out, bug 901581)
|
||||
[test_input_list_attribute.html]
|
||||
|
|
|
@ -50,7 +50,7 @@ interface nsITranslationNodeList;
|
|||
interface nsIJSRAIIHelper;
|
||||
interface nsIContentPermissionRequest;
|
||||
|
||||
[scriptable, uuid(400db885-c2b8-4bf1-bc12-1dadcb08ad12)]
|
||||
[scriptable, uuid(7f2f44ab-2857-4cc2-8c9d-3d9816f5a4d6)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -1757,6 +1757,11 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
in int32_t aRight,
|
||||
in int32_t aBottom,
|
||||
in int32_t aLeft);
|
||||
|
||||
/**
|
||||
* Enable some service workers testing features.
|
||||
*/
|
||||
attribute boolean serviceWorkersTestingEnabled;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
|
||||
|
|
|
@ -55,10 +55,10 @@ FilePickerParent::~FilePickerParent()
|
|||
// the same runnable on the main thread.
|
||||
// 3. The main thread sends the results over IPC.
|
||||
FilePickerParent::FileSizeAndDateRunnable::FileSizeAndDateRunnable(FilePickerParent *aFPParent,
|
||||
nsCOMArray<nsIDOMFile>& aDomfiles)
|
||||
nsTArray<nsRefPtr<FileImpl>>& aFiles)
|
||||
: mFilePickerParent(aFPParent)
|
||||
{
|
||||
mDomfiles.SwapElements(aDomfiles);
|
||||
mFiles.SwapElements(aFiles);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -82,16 +82,16 @@ FilePickerParent::FileSizeAndDateRunnable::Run()
|
|||
// results.
|
||||
if (NS_IsMainThread()) {
|
||||
if (mFilePickerParent) {
|
||||
mFilePickerParent->SendFiles(mDomfiles);
|
||||
mFilePickerParent->SendFiles(mFiles);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We're not on the main thread, so do the stat().
|
||||
for (unsigned i = 0; i < mDomfiles.Length(); i++) {
|
||||
uint64_t size, lastModified;
|
||||
mDomfiles[i]->GetSize(&size);
|
||||
mDomfiles[i]->GetMozLastModifiedDate(&lastModified);
|
||||
for (unsigned i = 0; i < mFiles.Length(); i++) {
|
||||
ErrorResult rv;
|
||||
mFiles[i]->GetSize(rv);
|
||||
mFiles[i]->GetLastModified(rv);
|
||||
}
|
||||
|
||||
// Dispatch ourselves back on the main thread.
|
||||
|
@ -111,14 +111,14 @@ FilePickerParent::FileSizeAndDateRunnable::Destroy()
|
|||
}
|
||||
|
||||
void
|
||||
FilePickerParent::SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles)
|
||||
FilePickerParent::SendFiles(const nsTArray<nsRefPtr<FileImpl>>& aFiles)
|
||||
{
|
||||
nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager();
|
||||
InfallibleTArray<PBlobParent*> files;
|
||||
|
||||
for (unsigned i = 0; i < aDomfiles.Length(); i++) {
|
||||
BlobParent* blob = parent->GetOrCreateActorForBlob(
|
||||
static_cast<File*>(aDomfiles[i]));
|
||||
for (unsigned i = 0; i < aFiles.Length(); i++) {
|
||||
nsRefPtr<File> file = new File(nullptr, aFiles[i]);
|
||||
BlobParent* blob = parent->GetOrCreateActorForBlob(file);
|
||||
if (blob) {
|
||||
files.AppendElement(blob);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ FilePickerParent::Done(int16_t aResult)
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIDOMFile> domfiles;
|
||||
nsTArray<nsRefPtr<FileImpl>> files;
|
||||
if (mMode == nsIFilePicker::modeOpenMultiple) {
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));
|
||||
|
@ -151,25 +151,21 @@ FilePickerParent::Done(int16_t aResult)
|
|||
if (supports) {
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
|
||||
|
||||
// A null parent is fine because File are not used in this process
|
||||
// but only in the child.
|
||||
nsCOMPtr<nsIDOMFile> domfile = File::CreateFromFile(nullptr, file);
|
||||
domfiles.AppendElement(domfile);
|
||||
nsRefPtr<FileImpl> fileimpl = new FileImplFile(file);
|
||||
files.AppendElement(fileimpl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
mFilePicker->GetFile(getter_AddRefs(file));
|
||||
if (file) {
|
||||
// A null parent is fine because File are not used in this process
|
||||
// but only in the child.
|
||||
nsCOMPtr<nsIDOMFile> domfile = File::CreateFromFile(nullptr, file);
|
||||
domfiles.AppendElement(domfile);
|
||||
nsRefPtr<FileImpl> fileimpl = new FileImplFile(file);
|
||||
files.AppendElement(fileimpl);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRunnable);
|
||||
mRunnable = new FileSizeAndDateRunnable(this, domfiles);
|
||||
mRunnable = new FileSizeAndDateRunnable(this, files);
|
||||
if (!mRunnable->Dispatch()) {
|
||||
unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIFilePicker.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/PFilePickerParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -29,7 +30,7 @@ class FilePickerParent : public PFilePickerParent
|
|||
virtual ~FilePickerParent();
|
||||
|
||||
void Done(int16_t aResult);
|
||||
void SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles);
|
||||
void SendFiles(const nsTArray<nsRefPtr<FileImpl>>& aDomfiles);
|
||||
|
||||
virtual bool RecvOpen(const int16_t& aSelectedType,
|
||||
const bool& aAddToRecentDocs,
|
||||
|
@ -64,11 +65,11 @@ class FilePickerParent : public PFilePickerParent
|
|||
class FileSizeAndDateRunnable : public nsRunnable
|
||||
{
|
||||
FilePickerParent* mFilePickerParent;
|
||||
nsCOMArray<nsIDOMFile> mDomfiles;
|
||||
nsTArray<nsRefPtr<FileImpl>> mFiles;
|
||||
nsCOMPtr<nsIEventTarget> mEventTarget;
|
||||
|
||||
public:
|
||||
FileSizeAndDateRunnable(FilePickerParent *aFPParent, nsCOMArray<nsIDOMFile>& aDomfiles);
|
||||
FileSizeAndDateRunnable(FilePickerParent *aFPParent, nsTArray<nsRefPtr<FileImpl>>& aFiles);
|
||||
bool Dispatch();
|
||||
NS_IMETHOD Run();
|
||||
void Destroy();
|
||||
|
|
|
@ -55,7 +55,7 @@ using mozilla::CSSToScreenScale from "Units.h";
|
|||
using mozilla::CommandInt from "mozilla/EventForwards.h";
|
||||
using mozilla::Modifiers from "mozilla/EventForwards.h";
|
||||
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
|
||||
using mozilla::WritingMode from "WritingModes.h";
|
||||
using mozilla::WritingMode from "mozilla/WritingModes.h";
|
||||
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -2026,8 +2026,8 @@ TabChild::RecvUpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
|||
mOrientation = orientation;
|
||||
ScreenIntSize oldScreenSize = mInnerSize;
|
||||
mInnerSize = size;
|
||||
mWidget->Resize(0, 0, size.width, size.height,
|
||||
true);
|
||||
mWidget->Resize(rect.x + chromeDisp.x, rect.y + chromeDisp.y, size.width, size.height,
|
||||
true);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
||||
baseWin->SetPositionAndSize(0, 0, size.width, size.height,
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include "nsICancelable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsILoginManagerPrompter.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
@ -324,10 +325,36 @@ TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
|
|||
void
|
||||
TabParent::SetOwnerElement(Element* aElement)
|
||||
{
|
||||
// If we held previous content then unregister for its events.
|
||||
RemoveWindowListeners();
|
||||
|
||||
// Update to the new content, and register to listen for events from it.
|
||||
mFrameElement = aElement;
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
TryCacheDPIAndScale();
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::RemoveWindowListeners()
|
||||
{
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::GetAppType(nsAString& aOut)
|
||||
{
|
||||
|
@ -879,8 +906,7 @@ TabParent::RecvSetDimensions(const uint32_t& aFlags,
|
|||
}
|
||||
|
||||
void
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
const nsIntPoint& aChromeDisp)
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
|
@ -891,12 +917,20 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
|||
|
||||
if (!mUpdatedDimensions || mOrientation != orientation ||
|
||||
mDimensions != size || !mRect.IsEqualEdges(rect)) {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
nsIntRect contentRect = rect;
|
||||
if (widget) {
|
||||
contentRect.x += widget->GetClientOffset().x;
|
||||
contentRect.y += widget->GetClientOffset().y;
|
||||
}
|
||||
|
||||
mUpdatedDimensions = true;
|
||||
mRect = rect;
|
||||
mRect = contentRect;
|
||||
mDimensions = size;
|
||||
mOrientation = orientation;
|
||||
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
|
||||
nsIntPoint chromeOffset = -LayoutDevicePixel::ToUntyped(GetChildProcessOffset());
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, chromeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2733,6 +2767,27 @@ TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aAc
|
|||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabParent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
if (eventType.EqualsLiteral("MozUpdateWindowPos") && !mIsDestroyed) {
|
||||
// This event is sent when the widget moved. Therefore we only update
|
||||
// the position.
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsIntRect windowDims;
|
||||
NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims), NS_ERROR_FAILURE);
|
||||
UpdateDimensions(windowDims, mDimensions);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class FakeChannel final : public nsIChannel,
|
||||
public nsIAuthPromptCallback,
|
||||
public nsIInterfaceRequestor,
|
||||
|
|
|
@ -7,21 +7,22 @@
|
|||
#ifndef mozilla_tabs_TabParent_h
|
||||
#define mozilla_tabs_TabParent_h
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/dom/PFilePickerParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/WritingModes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsITabParent.h"
|
||||
#include "nsIXULBrowserWindow.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "Units.h"
|
||||
#include "WritingModes.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
class nsFrameLoader;
|
||||
class nsIFrameLoader;
|
||||
|
@ -59,6 +60,7 @@ class Element;
|
|||
struct StructuredCloneData;
|
||||
|
||||
class TabParent final : public PBrowserParent
|
||||
, public nsIDOMEventListener
|
||||
, public nsITabParent
|
||||
, public nsIAuthPromptProvider
|
||||
, public nsISecureBrowserUI
|
||||
|
@ -72,6 +74,8 @@ class TabParent final : public PBrowserParent
|
|||
public:
|
||||
// nsITabParent
|
||||
NS_DECL_NSITABPARENT
|
||||
// nsIDOMEventListener interfaces
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
TabParent(nsIContentParent* aManager,
|
||||
const TabId& aTabId,
|
||||
|
@ -106,6 +110,8 @@ public:
|
|||
|
||||
void Destroy();
|
||||
|
||||
void RemoveWindowListeners();
|
||||
|
||||
virtual bool RecvMoveFocus(const bool& aForward) override;
|
||||
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) override;
|
||||
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override;
|
||||
|
@ -224,8 +230,7 @@ public:
|
|||
// message-sending functions under a layer of indirection and
|
||||
// eating the return values
|
||||
void Show(const ScreenIntSize& size, bool aParentIsActive);
|
||||
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
const nsIntPoint& chromeDisp);
|
||||
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size);
|
||||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void UIResolutionChanged();
|
||||
void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
|
||||
|
|
|
@ -161,3 +161,5 @@ XMLDocumentLoadPrincipalMismatch=Use of document.load forbidden on Documents tha
|
|||
IndexedDBTransactionAbortNavigation=An IndexedDB transaction that was not yet complete has been aborted due to page navigation.
|
||||
# LOCALIZATION NOTE (WillChangeBudgetWarning): Do not translate Will-change, %1$S,%2$S,%3$S are numbers.
|
||||
WillChangeBudgetWarning=Will-change memory consumption is too high. Surface area covers %1$S pixels, budget is the document surface area multiplied by %2$S (%3$S pixels). All occurences of will-change in the document are ignored when over budget.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker".
|
||||
HittingMaxWorkersPerDomain=A ServiceWorker could not be started immediately because other documents in the same origin are already using the maximum number of workers. The ServiceWorker is now queued and will be started after some of the other workers have completed.
|
||||
|
|
|
@ -1006,6 +1006,8 @@ MediaCodecReader::DecodeVideoFrameSync(int64_t aTimeThreshold)
|
|||
}
|
||||
|
||||
if (v) {
|
||||
// Notify mDecoder that we have decoded a video frame.
|
||||
mDecoder->NotifyDecodedFrames(0, 1, 0);
|
||||
VideoQueue().Push(v);
|
||||
} else {
|
||||
NS_WARNING("Unable to create VideoData");
|
||||
|
@ -1817,6 +1819,10 @@ MediaCodecReader::GetCodecOutputData(Track& aTrack,
|
|||
}
|
||||
|
||||
if (status == OK) {
|
||||
// Notify mDecoder that we have parsed a video frame.
|
||||
if (&aTrack == &mVideoTrack) {
|
||||
mDecoder->NotifyDecodedFrames(1, 0, 0);
|
||||
}
|
||||
if (!IsValidTimestampUs(aThreshold) || info.mTimeUs >= aThreshold) {
|
||||
// Get a valid output buffer.
|
||||
break;
|
||||
|
|
|
@ -101,7 +101,13 @@ MediaOmxCommonDecoder::PauseStateMachine()
|
|||
if (!mDecoderStateMachine) {
|
||||
return;
|
||||
}
|
||||
mDecoderStateMachine->SetDormant(true);
|
||||
// enter dormant state
|
||||
RefPtr<nsRunnable> event =
|
||||
NS_NewRunnableMethodWithArg<bool>(
|
||||
mDecoderStateMachine,
|
||||
&MediaDecoderStateMachine::SetDormant,
|
||||
true);
|
||||
mDecoderStateMachine->TaskQueue()->Dispatch(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -124,7 +130,13 @@ MediaOmxCommonDecoder::ResumeStateMachine()
|
|||
|
||||
mNextState = mPlayState;
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
mDecoderStateMachine->SetDormant(false);
|
||||
// exit dormant state
|
||||
RefPtr<nsRunnable> event =
|
||||
NS_NewRunnableMethodWithArg<bool>(
|
||||
mDecoderStateMachine,
|
||||
&MediaDecoderStateMachine::SetDormant,
|
||||
false);
|
||||
mDecoderStateMachine->TaskQueue()->Dispatch(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# do ok(true, "Type not supported") and stop the test.
|
||||
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet' || (os == 'win' && strictContentSandbox) # strictContentSandbox (Bug 1042735)
|
||||
skip-if = buildapp == 'mulet' || (os == 'win' && strictContentSandbox) || android_version == '18' # strictContentSandbox (Bug 1042735)
|
||||
support-files =
|
||||
320x240.ogv
|
||||
320x240.ogv^headers^
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881
|
||||
# won't run on b2g desktop tests - bug 1119993
|
||||
# broken HTTPS on b2g emulator - bug 1135339
|
||||
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10' || (buildapp == 'b2g' && toolkit != 'gonk') || (buildapp == 'b2g' && toolkit == 'gonk')
|
||||
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10' || android_version == '18' || (buildapp == 'b2g' && toolkit != 'gonk') || (buildapp == 'b2g' && toolkit == 'gonk')
|
||||
support-files =
|
||||
/.well-known/idp-proxy/idp.js
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[DEFAULT]
|
||||
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881
|
||||
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10'
|
||||
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10' || android_version == '18'
|
||||
support-files =
|
||||
head.js
|
||||
dataChannel.js
|
||||
|
|
|
@ -189,7 +189,7 @@ void Reverb::process(const AudioChunk* sourceBus, AudioChunk* destinationBus, si
|
|||
|
||||
// simply copy L -> R
|
||||
float* destinationChannelR = static_cast<float*>(const_cast<void*>(destinationBus->mChannelData[1]));
|
||||
bool isCopySafe = destinationChannelL && destinationChannelR && size_t(destinationBus->mDuration) >= framesToProcess && size_t(destinationBus->mDuration) >= framesToProcess;
|
||||
bool isCopySafe = destinationChannelL && destinationChannelR && size_t(destinationBus->mDuration) >= framesToProcess;
|
||||
MOZ_ASSERT(isCopySafe);
|
||||
if (!isCopySafe)
|
||||
return;
|
||||
|
|
|
@ -120,9 +120,9 @@ skip-if = toolkit == 'android' # bug 1145816
|
|||
[test_mediaStreamAudioSourceNodePassThrough.html]
|
||||
[test_mediaStreamAudioSourceNodeResampling.html]
|
||||
[test_mixingRules.html]
|
||||
skip-if = android_version == '10' # bug 1091965
|
||||
skip-if = android_version == '10' || android_version == '18' # bug 1091965
|
||||
[test_mozaudiochannel.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' # Android: bug 1061675
|
||||
skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' || android_version == '18' # Android: bug 1061675
|
||||
[test_nodeToParamConnection.html]
|
||||
[test_OfflineAudioContext.html]
|
||||
[test_offlineDestinationChannelCountLess.html]
|
||||
|
|
|
@ -334,7 +334,8 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsPluginStreamListenerPeer* streamPe
|
|||
|
||||
if (streamType == nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN) {
|
||||
SuspendRequest();
|
||||
} else if (!SetStreamType(streamType, false)) {
|
||||
}
|
||||
if (!SetStreamType(streamType, false)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -364,6 +365,12 @@ nsNPAPIPluginStreamListener::SetStreamType(uint16_t aType, bool aNeedsResume)
|
|||
// instance is destroyed.
|
||||
NS_ADDREF_THIS();
|
||||
break;
|
||||
case nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN:
|
||||
MOZ_ASSERT(!aNeedsResume);
|
||||
mStreamType = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
|
||||
// In this case we just want to set mStreamType but we do not want to
|
||||
// execute anything else in this function.
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -790,7 +790,6 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
|||
tabContentBounds.ScaleInverseRoundOut(scaleFactor);
|
||||
int32_t windowH = tabContentBounds.height + int(chromeSize.y);
|
||||
|
||||
// This is actually relative to window-chrome.
|
||||
nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft());
|
||||
|
||||
// Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space.
|
||||
|
@ -800,8 +799,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
|||
nsPoint screenPoint;
|
||||
switch (sourceSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() +
|
||||
chromeSize + pluginPosition + windowPosition;
|
||||
screenPoint = sourcePoint + pluginPosition +
|
||||
pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) +
|
||||
|
@ -824,8 +823,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
|||
nsPoint destPoint;
|
||||
switch (destSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() -
|
||||
chromeSize - pluginPosition - windowPosition;
|
||||
destPoint = screenPoint - pluginPosition -
|
||||
pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
destPoint = screenPoint - windowPosition;
|
||||
|
@ -1308,7 +1307,7 @@ GetOffsetRootContent(nsIFrame* aFrame)
|
|||
int32_t newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0;
|
||||
if (!f || newAPD != currAPD) {
|
||||
// Convert docOffset to the right APD and add it to offset.
|
||||
offset += docOffset.ConvertAppUnits(currAPD, apd);
|
||||
offset += docOffset.ScaleToOtherAppUnits(currAPD, apd);
|
||||
docOffset.x = docOffset.y = 0;
|
||||
}
|
||||
currAPD = newAPD;
|
||||
|
@ -1316,7 +1315,7 @@ GetOffsetRootContent(nsIFrame* aFrame)
|
|||
}
|
||||
}
|
||||
|
||||
offset += docOffset.ConvertAppUnits(currAPD, apd);
|
||||
offset += docOffset.ScaleToOtherAppUnits(currAPD, apd);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
|
|
@ -1185,6 +1185,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
|
|||
void
|
||||
nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType)
|
||||
{
|
||||
MOZ_ASSERT(aStreamType != STREAM_TYPE_UNKNOWN);
|
||||
MOZ_ASSERT(mRequest);
|
||||
mStreamType = aStreamType;
|
||||
if (!mUseLocalCache && mStreamType >= NP_ASFILE) {
|
||||
|
@ -1201,8 +1202,6 @@ nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType)
|
|||
}
|
||||
}
|
||||
|
||||
const int32_t nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN = UINT16_MAX;
|
||||
|
||||
nsresult
|
||||
nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile)
|
||||
{
|
||||
|
|
|
@ -131,7 +131,9 @@ public:
|
|||
// Called by nsNPAPIPluginStreamListener
|
||||
void OnStreamTypeSet(const int32_t aStreamType);
|
||||
|
||||
static const int32_t STREAM_TYPE_UNKNOWN;
|
||||
enum {
|
||||
STREAM_TYPE_UNKNOWN = UINT16_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
|
||||
|
|
|
@ -1395,7 +1395,7 @@ PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
|
|||
MOZ_ASSERT(mSurrogate);
|
||||
mSurrogate->AsyncCallDeparting();
|
||||
if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) {
|
||||
*stype = UINT16_MAX;
|
||||
*stype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
|
||||
} else {
|
||||
err = NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
|
|
@ -537,6 +537,13 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
|
|||
OnInitFailure();
|
||||
return;
|
||||
}
|
||||
CrashReporterParent* crashReporter = CrashReporter();
|
||||
if (crashReporter) {
|
||||
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
|
||||
mIsStartingAsync ?
|
||||
NS_LITERAL_CSTRING("1") :
|
||||
NS_LITERAL_CSTRING("0"));
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
{ // Scope for lock
|
||||
mozilla::MutexAutoLock lock(mCrashReporterMutex);
|
||||
|
@ -607,6 +614,12 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome)
|
|||
{
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
|
||||
mIsStartingAsync = Preferences::GetBool(kAsyncInitPref, false);
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
|
||||
mIsStartingAsync ?
|
||||
NS_LITERAL_CSTRING("1") :
|
||||
NS_LITERAL_CSTRING("0"));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -408,12 +408,16 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
|
|||
// path-level matching, unless the channel got redirected, see:
|
||||
// http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
|
||||
if (!aWasRedirected && !mPath.IsEmpty()) {
|
||||
// cloning uri so we can ignore the ref
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aUri->CloneIgnoringRef(getter_AddRefs(uri));
|
||||
|
||||
// converting aUri into nsIURL so we can strip query and ref
|
||||
// example.com/test#foo -> example.com/test
|
||||
// example.com/test?val=foo -> example.com/test
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aUri);
|
||||
if (!url) {
|
||||
NS_ASSERTION(false, "can't QI into nsIURI");
|
||||
return false;
|
||||
}
|
||||
nsAutoCString uriPath;
|
||||
rv = uri->GetPath(uriPath);
|
||||
rv = url->GetFilePath(uriPath);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
// check if the last character of mPath is '/'; if so
|
||||
// we just have to check loading resource is within
|
||||
|
|
|
@ -61,6 +61,7 @@ skip-if = true
|
|||
[test_pointer-events-1b.xhtml]
|
||||
[test_pointer-events-2.xhtml]
|
||||
[test_pointer-events-3.xhtml]
|
||||
skip-if = android_version == '18' # bug 1147994
|
||||
[test_pointer-events-4.xhtml]
|
||||
[test_pointer-events-5.xhtml]
|
||||
[test_pointer-events-6.xhtml]
|
||||
|
|
|
@ -7,9 +7,15 @@
|
|||
interface WorkerDebuggerGlobalScope : EventTarget {
|
||||
readonly attribute object global;
|
||||
|
||||
void enterEventLoop();
|
||||
|
||||
void leaveEventLoop();
|
||||
|
||||
void postMessage(DOMString message);
|
||||
|
||||
attribute EventHandler onmessage;
|
||||
|
||||
void reportError(DOMString message);
|
||||
};
|
||||
|
||||
// So you can debug while you debug
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/asmjscache/AsmJSCache.h"
|
||||
#include "mozilla/dom/AtomList.h"
|
||||
|
@ -1414,6 +1416,12 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
|
||||
nsCString sharedWorkerScriptSpec;
|
||||
|
||||
const bool isServiceWorker = aWorkerPrivate->IsServiceWorker();
|
||||
if (isServiceWorker) {
|
||||
AssertIsOnMainThread();
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_SPAWN_ATTEMPTS, 1);
|
||||
}
|
||||
|
||||
bool isSharedOrServiceWorker = aWorkerPrivate->IsSharedWorker() ||
|
||||
aWorkerPrivate->IsServiceWorker();
|
||||
if (isSharedOrServiceWorker) {
|
||||
|
@ -1461,6 +1469,19 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
|
||||
if (queued) {
|
||||
domainInfo->mQueuedWorkers.AppendElement(aWorkerPrivate);
|
||||
if (isServiceWorker) {
|
||||
AssertIsOnMainThread();
|
||||
// ServiceWorker spawn gets queued due to hitting max workers per domain
|
||||
// limit so let's log a warning.
|
||||
// Note: aWorkerPrivate->GetDocument() call might result nullptr due to
|
||||
// no window so the message warning will show up in the browser console.
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"),
|
||||
aWorkerPrivate->GetDocument(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"HittingMaxWorkersPerDomain");
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_SPAWN_GETS_QUEUED, 1);
|
||||
}
|
||||
}
|
||||
else if (parent) {
|
||||
domainInfo->mChildWorkerCount++;
|
||||
|
@ -1529,6 +1550,10 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (isServiceWorker) {
|
||||
AssertIsOnMainThread();
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_WAS_SPAWNED, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -885,6 +885,10 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
|
|||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> outerWindow = window->GetOuterWindow();
|
||||
bool serviceWorkersTestingEnabled =
|
||||
outerWindow->GetServiceWorkersTestingEnabled();
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -893,8 +897,8 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
|
|||
nsCOMPtr<nsIURI> documentURI = doc->GetBaseURI();
|
||||
|
||||
bool authenticatedOrigin = false;
|
||||
// FIXME(nsm): Bug 1003991. Disable check when devtools are open.
|
||||
if (Preferences::GetBool("dom.serviceWorkers.testing.enabled")) {
|
||||
if (Preferences::GetBool("dom.serviceWorkers.testing.enabled") ||
|
||||
serviceWorkersTestingEnabled) {
|
||||
authenticatedOrigin = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1505,20 +1505,23 @@ public:
|
|||
nsIScriptGlobalObject* sgo;
|
||||
|
||||
if (aWorkerPrivate) {
|
||||
nsIDOMEventTarget* target = nullptr;
|
||||
WorkerGlobalScope* globalScope = nullptr;
|
||||
UNWRAP_WORKER_OBJECT(WorkerGlobalScope, global, globalScope);
|
||||
if (globalScope) {
|
||||
MOZ_ASSERT(global == globalScope->GetWrapperPreserveColor());
|
||||
target = static_cast<nsIDOMEventTarget*>(globalScope);
|
||||
} else {
|
||||
|
||||
if (!globalScope) {
|
||||
WorkerDebuggerGlobalScope* globalScope = nullptr;
|
||||
UNWRAP_OBJECT(WorkerDebuggerGlobalScope, global, globalScope);
|
||||
MOZ_ASSERT(globalScope);
|
||||
MOZ_ASSERT(global == globalScope->GetWrapperPreserveColor());
|
||||
target = static_cast<nsIDOMEventTarget*>(globalScope);
|
||||
|
||||
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
|
||||
aMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(global == globalScope->GetWrapperPreserveColor());
|
||||
nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(globalScope);
|
||||
|
||||
nsRefPtr<ErrorEvent> event =
|
||||
ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
|
||||
event->SetTrusted(true);
|
||||
|
@ -4214,6 +4217,41 @@ WorkerPrivateParent<Derived>::AssertInnerWindowIsCorrect() const
|
|||
|
||||
#endif
|
||||
|
||||
class ReportDebuggerErrorRunnable final : public nsIRunnable
|
||||
{
|
||||
nsRefPtr<WorkerDebugger> mDebugger;
|
||||
nsString mFilename;
|
||||
uint32_t mLineno;
|
||||
nsString mMessage;
|
||||
|
||||
public:
|
||||
ReportDebuggerErrorRunnable(WorkerDebugger* aDebugger,
|
||||
const nsAString& aFilename, uint32_t aLineno,
|
||||
const nsAString& aMessage)
|
||||
: mDebugger(aDebugger),
|
||||
mFilename(aFilename),
|
||||
mLineno(aLineno),
|
||||
mMessage(aMessage)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
~ReportDebuggerErrorRunnable()
|
||||
{ }
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
mDebugger->ReportErrorToDebuggerOnMainThread(mFilename, mLineno, mMessage);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ReportDebuggerErrorRunnable, nsIRunnable)
|
||||
|
||||
WorkerDebugger::WorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
||||
: mMutex("WorkerDebugger::mMutex"),
|
||||
mCondVar(mMutex, "WorkerDebugger::mCondVar"),
|
||||
|
@ -4499,6 +4537,41 @@ WorkerDebugger::PostMessageToDebuggerOnMainThread(const nsAString& aMessage)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::ReportErrorToDebugger(const nsAString& aFilename,
|
||||
uint32_t aLineno,
|
||||
const nsAString& aMessage)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new ReportDebuggerErrorRunnable(this, aFilename, aLineno, aMessage);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to report error to debugger on main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
||||
uint32_t aLineno,
|
||||
const nsAString& aMessage)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIWorkerDebuggerListener>> listeners;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
listeners.AppendElements(mListeners);
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < listeners.Length(); ++index) {
|
||||
listeners[index]->OnError(aFilename, aLineno, aMessage);
|
||||
}
|
||||
|
||||
LogErrorToConsole(aMessage, aFilename, nsString(), aLineno, 0, 0, 0);
|
||||
}
|
||||
|
||||
WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
||||
WorkerPrivate* aParent,
|
||||
const nsAString& aScriptURL,
|
||||
|
@ -4510,6 +4583,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
|||
aSharedWorkerName, aLoadInfo)
|
||||
, mJSContext(nullptr)
|
||||
, mPRThread(nullptr)
|
||||
, mDebuggerEventLoopLevel(0)
|
||||
, mErrorHandlerRecursionCount(0)
|
||||
, mNextTimeoutId(1)
|
||||
, mStatus(Pending)
|
||||
|
@ -6113,12 +6187,90 @@ WorkerPrivate::PostMessageToParentMessagePort(
|
|||
aMessagePortSerial, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::EnterDebuggerEventLoop()
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
JSContext* cx = GetJSContext();
|
||||
MOZ_ASSERT(cx);
|
||||
|
||||
uint32_t currentEventLoopLevel = ++mDebuggerEventLoopLevel;
|
||||
|
||||
while (currentEventLoopLevel <= mDebuggerEventLoopLevel) {
|
||||
bool debuggerRunnablesPending = false;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
debuggerRunnablesPending = !mDebuggerQueue.IsEmpty();
|
||||
}
|
||||
|
||||
// Don't block with the periodic GC timer running.
|
||||
if (!debuggerRunnablesPending) {
|
||||
SetGCTimerMode(IdleTimer);
|
||||
}
|
||||
|
||||
// Wait for something to do
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
while (mControlQueue.IsEmpty() &&
|
||||
!(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty())) {
|
||||
WaitForWorkerEvents();
|
||||
}
|
||||
|
||||
ProcessAllControlRunnablesLocked();
|
||||
}
|
||||
|
||||
if (debuggerRunnablesPending) {
|
||||
// Start the periodic GC timer if it is not already running.
|
||||
SetGCTimerMode(PeriodicTimer);
|
||||
|
||||
WorkerRunnable* runnable;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mDebuggerQueue.Pop(runnable);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(runnable);
|
||||
static_cast<nsIRunnable*>(runnable)->Run();
|
||||
runnable->Release();
|
||||
|
||||
// Now *might* be a good time to GC. Let the JS engine make the decision.
|
||||
JS_MaybeGC(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::LeaveDebuggerEventLoop()
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mDebuggerEventLoopLevel > 0) {
|
||||
--mDebuggerEventLoopLevel;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::PostMessageToDebugger(const nsAString& aMessage)
|
||||
{
|
||||
mDebugger->PostMessageToDebugger(aMessage);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::ReportErrorToDebugger(const nsAString& aFilename,
|
||||
uint32_t aLineno,
|
||||
const nsAString& aMessage)
|
||||
{
|
||||
mDebugger->ReportErrorToDebugger(aFilename, aLineno, aMessage);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
||||
{
|
||||
|
|
|
@ -56,6 +56,8 @@ class PrincipalInfo;
|
|||
|
||||
struct PRThread;
|
||||
|
||||
class ReportDebuggerErrorRunnable;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class AutoSyncLoopHolder;
|
||||
|
@ -721,6 +723,8 @@ public:
|
|||
};
|
||||
|
||||
class WorkerDebugger : public nsIWorkerDebugger {
|
||||
friend class ::ReportDebuggerErrorRunnable;
|
||||
|
||||
mozilla::Mutex mMutex;
|
||||
mozilla::CondVar mCondVar;
|
||||
|
||||
|
@ -753,6 +757,10 @@ public:
|
|||
void
|
||||
PostMessageToDebugger(const nsAString& aMessage);
|
||||
|
||||
void
|
||||
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
|
||||
const nsAString& aMessage);
|
||||
|
||||
private:
|
||||
virtual
|
||||
~WorkerDebugger();
|
||||
|
@ -762,6 +770,11 @@ private:
|
|||
|
||||
void
|
||||
PostMessageToDebuggerOnMainThread(const nsAString& aMessage);
|
||||
|
||||
void
|
||||
ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
||||
uint32_t aLineno,
|
||||
const nsAString& aMessage);
|
||||
};
|
||||
|
||||
class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||
|
@ -802,6 +815,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
nsTArray<ParentType*> mChildWorkers;
|
||||
nsTArray<WorkerFeature*> mFeatures;
|
||||
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
|
||||
uint32_t mDebuggerEventLoopLevel;
|
||||
|
||||
struct SyncLoopInfo
|
||||
{
|
||||
|
@ -962,9 +976,19 @@ public:
|
|||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
EnterDebuggerEventLoop();
|
||||
|
||||
void
|
||||
LeaveDebuggerEventLoop();
|
||||
|
||||
void
|
||||
PostMessageToDebugger(const nsAString& aMessage);
|
||||
|
||||
void
|
||||
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
|
||||
const nsAString& aMessage);
|
||||
|
||||
bool
|
||||
NotifyInternal(JSContext* aCx, Status aStatus);
|
||||
|
||||
|
|
|
@ -513,12 +513,35 @@ WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
|
|||
aGlobal.set(mWorkerPrivate->GetOrCreateGlobalScope(aCx)->GetWrapper());
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerGlobalScope::EnterEventLoop()
|
||||
{
|
||||
mWorkerPrivate->EnterDebuggerEventLoop();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerGlobalScope::LeaveEventLoop()
|
||||
{
|
||||
mWorkerPrivate->LeaveDebuggerEventLoop();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage)
|
||||
{
|
||||
mWorkerPrivate->PostMessageToDebugger(aMessage);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
|
||||
const nsAString& aMessage)
|
||||
{
|
||||
JS::AutoFilename afn;
|
||||
uint32_t lineno = 0;
|
||||
JS::DescribeScriptedCaller(aCx, &afn, &lineno);
|
||||
nsString filename(NS_ConvertUTF8toUTF16(afn.get()));
|
||||
mWorkerPrivate->ReportErrorToDebugger(filename, lineno, aMessage);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
|
||||
const Optional<nsAString>& aString) const
|
||||
|
|
|
@ -264,11 +264,20 @@ public:
|
|||
void
|
||||
GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal);
|
||||
|
||||
void
|
||||
EnterEventLoop();
|
||||
|
||||
void
|
||||
LeaveEventLoop();
|
||||
|
||||
void
|
||||
PostMessage(const nsAString& aMessage);
|
||||
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
|
||||
void
|
||||
ReportError(JSContext* aCx, const nsAString& aMessage);
|
||||
|
||||
void
|
||||
Dump(JSContext* aCx, const Optional<nsAString>& aString) const;
|
||||
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(ead45621-22a7-48ef-b7db-c4252ae3e6cb)]
|
||||
[scriptable, uuid(55d54034-1573-4889-b1d9-93ba12fc33c7)]
|
||||
interface nsIWorkerDebuggerListener : nsISupports
|
||||
{
|
||||
void onClose();
|
||||
|
||||
void onError(in DOMString filename, in unsigned long lineno,
|
||||
in DOMString message);
|
||||
|
||||
void onMessage(in DOMString message);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict"
|
||||
|
||||
onmessage = function (event) {
|
||||
this.onmessage = function (event) {
|
||||
switch (event.data) {
|
||||
case "ping":
|
||||
postMessage("pong");
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
debugger;
|
||||
}
|
||||
|
||||
self.onmessage = function (event) {
|
||||
switch (event.data) {
|
||||
case "ping":
|
||||
debugger;
|
||||
postMessage("pong");
|
||||
break;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
|
||||
let frames = [];
|
||||
|
||||
var dbg = new Debugger(global);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frames.push(frame);
|
||||
postMessage("paused");
|
||||
enterEventLoop();
|
||||
frames.pop();
|
||||
postMessage("resumed");
|
||||
};
|
||||
|
||||
this.onmessage = function (event) {
|
||||
switch (event.data) {
|
||||
case "eval":
|
||||
frames[frames.length - 1].eval("f()");
|
||||
postMessage("evalled");
|
||||
break;
|
||||
|
||||
case "ping":
|
||||
postMessage("pong");
|
||||
break;
|
||||
|
||||
case "resume":
|
||||
leaveEventLoop();
|
||||
break;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
debugger;
|
||||
}
|
||||
|
||||
var worker = new Worker("WorkerDebuggerGlobalScope.enterEventLoop_childWorker.js");
|
||||
|
||||
worker.onmessage = function (event) {
|
||||
postMessage("child:" + event.data);
|
||||
};
|
||||
|
||||
self.onmessage = function (event) {
|
||||
var message = event.data;
|
||||
if (message.indexOf(":") >= 0) {
|
||||
worker.postMessage(message.split(":")[1]);
|
||||
return;
|
||||
}
|
||||
switch (message) {
|
||||
case "ping":
|
||||
debugger;
|
||||
postMessage("pong");
|
||||
break;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
self.onerror = function () {
|
||||
postMessage("error");
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
"use strict";
|
||||
|
||||
this.onmessage = function (event) {
|
||||
switch (event.data) {
|
||||
case "report":
|
||||
reportError("reported");
|
||||
break;
|
||||
case "throw":
|
||||
throw new Error("thrown");
|
||||
break;
|
||||
}
|
||||
};
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче