Merge m-c to b2g-inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-03-27 12:20:00 -04:00
commit 6558bd81c3
414 changed files with 13340 additions and 6629 deletions

View File

@ -8,7 +8,7 @@
#include "AccessibleWrap.h" #include "AccessibleWrap.h"
#include "nsMai.h" #include "nsMai.h"
#include "ProxyAccessible.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
@ -20,12 +20,17 @@ extern "C" {
static void static void
getCurrentValueCB(AtkValue *obj, GValue *value) getCurrentValueCB(AtkValue *obj, GValue *value)
{ {
ProxyAccessible* proxy = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj)); AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
if (!accWrap) if (!accWrap) {
proxy = GetProxy(ATK_OBJECT(obj));
if (!proxy) {
return; return;
}
}
memset (value, 0, sizeof (GValue)); memset (value, 0, sizeof (GValue));
double accValue = accWrap->CurValue(); double accValue = accWrap ? accWrap->CurValue() : proxy->CurValue();
if (IsNaN(accValue)) if (IsNaN(accValue))
return; return;
@ -36,12 +41,17 @@ getCurrentValueCB(AtkValue *obj, GValue *value)
static void static void
getMaximumValueCB(AtkValue *obj, GValue *value) getMaximumValueCB(AtkValue *obj, GValue *value)
{ {
ProxyAccessible* proxy = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj)); AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
if (!accWrap) if (!accWrap) {
proxy = GetProxy(ATK_OBJECT(obj));
if (!proxy) {
return; return;
}
}
memset(value, 0, sizeof (GValue)); memset(value, 0, sizeof (GValue));
double accValue = accWrap->MaxValue(); double accValue = accWrap ? accWrap->MaxValue() : proxy->MaxValue();
if (IsNaN(accValue)) if (IsNaN(accValue))
return; return;
@ -52,12 +62,17 @@ getMaximumValueCB(AtkValue *obj, GValue *value)
static void static void
getMinimumValueCB(AtkValue *obj, GValue *value) getMinimumValueCB(AtkValue *obj, GValue *value)
{ {
ProxyAccessible* proxy = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj)); AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
if (!accWrap) if (!accWrap) {
proxy = GetProxy(ATK_OBJECT(obj));
if (!proxy) {
return; return;
}
}
memset(value, 0, sizeof (GValue)); memset(value, 0, sizeof (GValue));
double accValue = accWrap->MinValue(); double accValue = accWrap ? accWrap->MinValue() : proxy->MinValue();
if (IsNaN(accValue)) if (IsNaN(accValue))
return; return;
@ -68,12 +83,17 @@ getMinimumValueCB(AtkValue *obj, GValue *value)
static void static void
getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement) getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
{ {
ProxyAccessible* proxy = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj)); AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
if (!accWrap) if (!accWrap) {
proxy = GetProxy(ATK_OBJECT(obj));
if (!proxy) {
return; return;
}
}
memset(minimumIncrement, 0, sizeof (GValue)); memset(minimumIncrement, 0, sizeof (GValue));
double accValue = accWrap->Step(); double accValue = accWrap ? accWrap->Step() : proxy->Step();
if (IsNaN(accValue)) if (IsNaN(accValue))
accValue = 0; // zero if the minimum increment is undefined accValue = 0; // zero if the minimum increment is undefined
@ -84,12 +104,17 @@ getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
static gboolean static gboolean
setCurrentValueCB(AtkValue *obj, const GValue *value) setCurrentValueCB(AtkValue *obj, const GValue *value)
{ {
ProxyAccessible* proxy = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj)); AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
if (!accWrap) if (!accWrap) {
proxy = GetProxy(ATK_OBJECT(obj));
if (!proxy) {
return FALSE; return FALSE;
}
}
double accValue =g_value_get_double(value); double accValue =g_value_get_double(value);
return accWrap->SetCurValue(accValue); return accWrap ? accWrap->SetCurValue(accValue) : proxy->SetCurValue(accValue);
} }
} }

View File

@ -533,8 +533,9 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
// accessibles in subtree then we don't care about the change. // accessibles in subtree then we don't care about the change.
Accessible* child = document->GetAccessible(aChildNode); Accessible* child = document->GetAccessible(aChildNode);
if (!child) { if (!child) {
a11y::TreeWalker walker(document->GetContainerAccessible(aChildNode), Accessible* container = document->GetContainerAccessible(aChildNode);
aChildNode, a11y::TreeWalker::eWalkCache); a11y::TreeWalker walker(container ? container : document, aChildNode,
a11y::TreeWalker::eWalkCache);
child = walker.NextChild(); child = walker.NextChild();
} }

View File

@ -15,6 +15,7 @@
#include "TableCellAccessible.h" #include "TableCellAccessible.h"
#include "nsIPersistentProperties2.h" #include "nsIPersistentProperties2.h"
#include "nsISimpleEnumerator.h" #include "nsISimpleEnumerator.h"
#include "nsAccUtils.h"
namespace mozilla { namespace mozilla {
namespace a11y { namespace a11y {
@ -1430,5 +1431,205 @@ DocAccessibleChild::RecvUnselectAll(const uint64_t& aID,
return true; 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;
}
} }
} }

View File

@ -351,6 +351,56 @@ public:
virtual bool RecvUnselectAll(const uint64_t& aID, virtual bool RecvUnselectAll(const uint64_t& aID,
bool* aSuccess) override; 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: private:
Accessible* IdToAccessible(const uint64_t& aID) const; Accessible* IdToAccessible(const uint64_t& aID) const;

View File

@ -192,6 +192,23 @@ child:
prio(high) sync SelectAll(uint64_t aID) 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 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);
}; };
} }

View File

@ -799,5 +799,117 @@ ProxyAccessible::UnselectAll()
return success; 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;
}
} }
} }

View File

@ -9,9 +9,11 @@
#include "mozilla/a11y/Role.h" #include "mozilla/a11y/Role.h"
#include "nsIAccessibleText.h" #include "nsIAccessibleText.h"
#include "Accessible.h"
#include "nsString.h" #include "nsString.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsRect.h" #include "nsRect.h"
#include "Accessible.h"
namespace mozilla { namespace mozilla {
namespace a11y { namespace a11y {
@ -256,6 +258,24 @@ public:
bool SelectAll(); bool SelectAll();
bool UnselectAll(); 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. * Allow the platform to store a pointers worth of data on us.
*/ */

View File

@ -969,12 +969,7 @@ pref("gecko.handlerService.allowRegisterFromDifferentHost", false);
pref("browser.safebrowsing.enabled", true); pref("browser.safebrowsing.enabled", true);
pref("browser.safebrowsing.malware.enabled", true); pref("browser.safebrowsing.malware.enabled", true);
pref("browser.safebrowsing.downloads.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); pref("browser.safebrowsing.downloads.remote.enabled", true);
#else
pref("browser.safebrowsing.downloads.remote.enabled", false);
#endif
pref("browser.safebrowsing.debug", false); 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%"); 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 #ifdef XP_WIN
// Only download the whitelist on Windows, since the whitelist is // Only download the whitelist on Windows, since the whitelist is
// only useful for suppressing remote lookups for signed binaries which we can // 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"); pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-digest256");
#endif #endif
#endif #endif
@ -1450,6 +1445,9 @@ pref("devtools.performance.ui.enable-framerate", true);
// The default cache UI setting // The default cache UI setting
pref("devtools.cache.disabled", false); pref("devtools.cache.disabled", false);
// The default service workers UI setting
pref("devtools.serviceWorkers.testing.enabled", false);
// Enable the Network Monitor // Enable the Network Monitor
pref("devtools.netmonitor.enabled", true); pref("devtools.netmonitor.enabled", true);

View File

@ -3246,8 +3246,7 @@
}; };
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu"); let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
let event = gContextMenuContentData.event; let event = gContextMenuContentData.event;
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY); popup.openPopupAtScreen(event.screenX, event.screenY, true);
popup.openPopupAtScreen(pos.x, pos.y, true);
break; break;
} }
case "DOMWebNotificationClicked": { case "DOMWebNotificationClicked": {

View File

@ -50,6 +50,9 @@ support-files =
file_bug906190_redirected.html file_bug906190_redirected.html
file_bug906190.js file_bug906190.js
file_bug906190.sjs file_bug906190.sjs
file_mixedContentFromOnunload.html
file_mixedContentFromOnunload_test1.html
file_mixedContentFromOnunload_test2.html
file_bug970276_popup1.html file_bug970276_popup1.html
file_bug970276_popup2.html file_bug970276_popup2.html
file_bug970276_favicon1.ico 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_bug902156.js]
[browser_bug906190.js] [browser_bug906190.js]
skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
[browser_mixedContentFromOnunload.js]
[browser_bug970746.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 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] [browser_bug1015721.js]

View File

@ -59,6 +59,7 @@ function checkPage() {
Services.obs.addObserver(function observer(aSubject, aTopic) { Services.obs.addObserver(function observer(aSubject, aTopic) {
ok(!Services.io.offline, "After clicking the Try Again button, we're back " + ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
"online."); "online.");
Services.obs.removeObserver(observer, "network:offline-status-changed", false);
finish(); finish();
}, "network:offline-status-changed", false); }, "network:offline-status-changed", false);
gBrowser.contentDocument.getElementById("errorTryAgain").click(); gBrowser.contentDocument.getElementById("errorTryAgain").click();

View File

@ -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);
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -13,6 +13,7 @@ var Ci = Components.interfaces;
var Cr = Components.results; var Cr = Components.results;
Components.utils.import('resource://gre/modules/Services.jsm'); 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_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.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. // identifying the "use plugin" action, so we use this constant instead.
const kActionUsePlugin = 5; const kActionUsePlugin = 5;
/* const ICON_URL_APP = AppConstants.platform == "linux" ?
#ifdef MOZ_WIDGET_GTK "moz-icon://dummy.exe?size=16" :
*/ "chrome://browser/skin/preferences/application.png";
const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
/*
#else
*/
const ICON_URL_APP = "chrome://browser/skin/preferences/application.png";
/*
#endif
*/
// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL // 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. // was set by us to a custom handler icon and CSS should not try to override it.

View File

@ -8,6 +8,7 @@
// Constants & Enumeration Values // Constants & Enumeration Values
Components.utils.import('resource://gre/modules/Services.jsm'); 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_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed"; const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.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. // identifying the "use plugin" action, so we use this constant instead.
const kActionUsePlugin = 5; const kActionUsePlugin = 5;
/* const ICON_URL_APP = AppConstants.platform == "linux" ?
#if MOZ_WIDGET_GTK == 2 "moz-icon://dummy.exe?size=16" :
*/ "chrome://browser/skin/preferences/application.png";
const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
/*
#else
*/
const ICON_URL_APP = "chrome://browser/skin/preferences/application.png";
/*
#endif
*/
// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL // 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. // was set by us to a custom handler icon and CSS should not try to override it.

View File

@ -95,7 +95,9 @@ let gSyncPane = {
"weave:service:start-over:finish", "weave:service:start-over:finish",
"weave:service:setup-complete", "weave:service:setup-complete",
"weave:service:logout:finish", "weave:service:logout:finish",
FxAccountsCommon.ONVERIFIED_NOTIFICATION]; FxAccountsCommon.ONVERIFIED_NOTIFICATION,
FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
];
let migrateTopic = "fxa-migration:state-changed"; let migrateTopic = "fxa-migration:state-changed";
// Add the observers now and remove them on unload // Add the observers now and remove them on unload
@ -123,6 +125,8 @@ let gSyncPane = {
}), }),
this.updateWeavePrefs(); this.updateWeavePrefs();
this._initProfileImageUI();
}, },
_setupEventListeners: function() { _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 () { updateWeavePrefs: function () {
// ask the migration module to broadcast its current state (and nothing will // 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 // happen if it's not loaded - which is good, as that means no migration
@ -244,10 +256,11 @@ let gSyncPane = {
} }
// determine the fxa status... // determine the fxa status...
this.page = PAGE_PLEASE_WAIT; this.page = PAGE_PLEASE_WAIT;
fxAccounts.getSignedInUser().then(data => { fxAccounts.getSignedInUser().then(data => {
if (!data) { if (!data) {
this.page = FXA_PAGE_LOGGED_OUT; this.page = FXA_PAGE_LOGGED_OUT;
return; return false;
} }
this.page = FXA_PAGE_LOGGED_IN; this.page = FXA_PAGE_LOGGED_IN;
// We are logged in locally, but maybe we are in a state where the // 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")) { for (let checkbox of engines.querySelectorAll("checkbox")) {
checkbox.disabled = enginesListDisabled; 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, // If fxAccountEnabled is false and we are in a "not configured" state,
// then fxAccounts is probably fully disabled rather than just unconfigured, // then fxAccounts is probably fully disabled rather than just unconfigured,
// so handle this case. This block can be removed once we remove support // 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() { manageFirefoxAccount: function() {
let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri"); let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri");
this.openContentInBrowser(url); this.openContentInBrowser(url);

View File

@ -233,7 +233,11 @@
<!-- logged in and verified and all is good --> <!-- logged in and verified and all is good -->
<hbox id="fxaLoginVerified" <hbox id="fxaLoginVerified"
align="center"> align="center">
<hbox align="center">
<image id="fxaProfileImage"
onclick="gSyncPane.openChangeProfileImage();" hidden="true"/>
<label id="fxaEmailAddress1"/> <label id="fxaEmailAddress1"/>
</hbox>
<spacer flex="1"/> <spacer flex="1"/>
<button id="verifiedManage" <button id="verifiedManage"
label="&manage.label;"/> label="&manage.label;"/>

View File

@ -8,6 +8,8 @@ support-files =
head.js head.js
helper_disable_cache.js helper_disable_cache.js
doc_theme.css doc_theme.css
browser_toolbox_options_enable_serviceworkers_testing.html
serviceworker.js
[browser_devtools_api.js] [browser_devtools_api.js]
[browser_devtools_api_destroy.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_zoom.js]
[browser_toolbox_custom_host.js] [browser_toolbox_custom_host.js]
[browser_toolbox_theme_registration.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: # We want this test to run for mochitest-dt as well, so we include it here:
[../../../base/content/test/general/browser_parsable_css.js] [../../../base/content/test/general/browser_parsable_css.js]

View File

@ -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>

View File

@ -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();
});
}

View File

@ -0,0 +1 @@
// empty service worker, always succeed!

View File

@ -317,7 +317,7 @@ OptionsPanel.prototype = {
if (this.target.activeTab) { if (this.target.activeTab) {
this.target.client.attachTab(this.target.activeTab._actor, (response) => { this.target.client.attachTab(this.target.activeTab._actor, (response) => {
this._origJavascriptEnabled = response.javascriptEnabled; this._origJavascriptEnabled = response.javascriptEnabled;
this.disableJSNode.checked = !this._origJavascriptEnabled this.disableJSNode.checked = !this._origJavascriptEnabled;
this.disableJSNode.addEventListener("click", this._disableJSClicked, false); this.disableJSNode.addEventListener("click", this._disableJSClicked, false);
}); });
} else { } else {

View File

@ -145,6 +145,10 @@
<checkbox id="devtools-disable-javascript" <checkbox id="devtools-disable-javascript"
label="&options.disableJavaScript.label;" label="&options.disableJavaScript.label;"
tooltiptext="&options.disableJavaScript.tooltip;"/> 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"> <hbox class="hidden-labels-box">
<checkbox label="&options.enableChrome.label5;" <checkbox label="&options.enableChrome.label5;"
tooltiptext="&options.enableChrome.tooltip3;" tooltiptext="&options.enableChrome.tooltip3;"

View File

@ -332,6 +332,7 @@ Toolbox.prototype = {
this._buildOptions(); this._buildOptions();
this._buildTabs(); this._buildTabs();
this._applyCacheSettings(); this._applyCacheSettings();
this._applyServiceWorkersTestingSettings();
this._addKeysToWindow(); this._addKeysToWindow();
this._addReloadKeys(); this._addReloadKeys();
this._addHostListeners(); this._addHostListeners();
@ -407,8 +408,13 @@ Toolbox.prototype = {
* } * }
*/ */
_prefChanged: function(event, data) { _prefChanged: function(event, data) {
if (data.pref === "devtools.cache.disabled") { switch(data.pref) {
case "devtools.cache.disabled":
this._applyCacheSettings(); 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 * Setter for the checked state of the picker button in the toolbar
* @param {Boolean} isChecked * @param {Boolean} isChecked
@ -1694,10 +1716,13 @@ Toolbox.prototype = {
} }
} }
// Now that we are closing the toolbox we can re-enable JavaScript for the // Now that we are closing the toolbox we can re-enable the cache settings
// current tab. // and disable the service workers testing settings for the current tab.
if (this.target.activeTab) { if (this.target.activeTab) {
this.target.activeTab.reconfigure({"cacheDisabled": false}); this.target.activeTab.reconfigure({
"cacheDisabled": false,
"serviceWorkersTestingEnabled": false
});
} }
// Destroying the walker and inspector fronts // Destroying the walker and inspector fronts

View File

@ -13,7 +13,11 @@ let test = Task.async(function*() {
let firstTarget = TargetFactory.forTab(firstTab); let firstTarget = TargetFactory.forTab(firstTab);
yield firstTarget.makeRemote(); yield firstTarget.makeRemote();
yield gDevTools.showToolbox(firstTarget, "webconsole"); let toolboxFirstTab;
yield gDevTools.showToolbox(firstTarget, "webconsole").then((aToolbox) => {
toolboxFirstTab = aToolbox;
});
is(gProfilerConnections, 1, is(gProfilerConnections, 1,
"A shared profiler connection should have been created."); "A shared profiler connection should have been created.");
@ -25,15 +29,22 @@ let test = Task.async(function*() {
let secondTarget = TargetFactory.forTab(secondTab); let secondTarget = TargetFactory.forTab(secondTab);
yield secondTarget.makeRemote(); yield secondTarget.makeRemote();
yield gDevTools.showToolbox(secondTarget, "jsprofiler"); let toolboxSecondTab;
yield gDevTools.showToolbox(secondTarget, "jsprofiler").then((aToolbox) => {
toolboxSecondTab = aToolbox;
});
is(gProfilerConnections, 2, is(gProfilerConnections, 2,
"Only one new profiler connection should have been created."); "Only one new profiler connection should have been created.");
yield removeTab(firstTab); yield toolboxFirstTab.destroy().then(() => {
yield removeTab(secondTab); removeTab(firstTab);
});
yield toolboxSecondTab.destroy().then(() => {
removeTab(secondTab);
finish(); finish();
}); });
});
function profilerConnectionObserver(subject, topic, data) { function profilerConnectionObserver(subject, topic, data) {
is(topic, "profiler-connection-created", "The correct topic was observed."); is(topic, "profiler-connection-created", "The correct topic was observed.");

View File

@ -97,6 +97,12 @@
<!ENTITY options.disableCache.label2 "Disable Cache (when toolbox is open)"> <!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."> <!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 <!-- LOCALIZATION NOTE (options.selectDefaultTools.label): This is the label for
- the heading of group of checkboxes corresponding to the default developer - the heading of group of checkboxes corresponding to the default developer
- tools. --> - tools. -->

View File

@ -179,6 +179,7 @@ browser.jar:
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico) 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/icons.svg (../shared/incontentprefs/icons.svg)
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css) 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/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/preferences/search.css (preferences/search.css) skin/classic/browser/preferences/search.css (preferences/search.css)

View File

@ -284,6 +284,7 @@ browser.jar:
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico) 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/icons.svg (../shared/incontentprefs/icons.svg)
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css) 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/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/preferences/search.css (preferences/search.css) skin/classic/browser/preferences/search.css (preferences/search.css)

View File

@ -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>

After

Width:  |  Height:  |  Size: 993 B

View File

@ -216,6 +216,22 @@ description > html|a {
cursor: pointer; 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 { #noFxaAccount {
/* Overriding the margins from the base preferences.css theme file. /* Overriding the margins from the base preferences.css theme file.
These overrides can be simplified by fixing bug 1027174 */ These overrides can be simplified by fixing bug 1027174 */

View File

@ -207,6 +207,7 @@ browser.jar:
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico) 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/icons.svg (../shared/incontentprefs/icons.svg)
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css) 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/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/preferences/search.css (preferences/search.css) skin/classic/browser/preferences/search.css (preferences/search.css)

View File

@ -130,6 +130,7 @@ ifdef MOZ_FOLD_LIBS
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3 DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3
else else
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3 DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_DIR=$(ABS_DIST)/../config/external/sqlite
endif # MOZ_FOLD_LIBS endif # MOZ_FOLD_LIBS
DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
endif endif
@ -357,6 +358,11 @@ GARBAGE += \
endif # GCC_USE_GNU_LD endif # GCC_USE_GNU_LD
endif # WINNT endif # WINNT
IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
IMPORT_LIB_DEST ?= $(DIST)/lib
IMPORT_LIB_TARGET = target
INSTALL_TARGETS += IMPORT_LIB
endif # MOZ_FOLD_LIBS endif # MOZ_FOLD_LIBS
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

View File

@ -31,11 +31,6 @@ ifdef LIBRARY
ifdef DIST_INSTALL ifdef DIST_INSTALL
ifdef IS_COMPONENT ifdef IS_COMPONENT
$(error Shipping static component libs makes no sense.) $(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
endif # DIST_INSTALL endif # DIST_INSTALL
endif # LIBRARY endif # LIBRARY
@ -47,21 +42,6 @@ SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET) SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
SHARED_LIBRARY_TARGET = target SHARED_LIBRARY_TARGET = target
INSTALL_TARGETS += SHARED_LIBRARY 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 # ! IS_COMPONENT
endif # SHARED_LIBRARY endif # SHARED_LIBRARY
@ -72,13 +52,6 @@ HOST_PROGRAMS_TARGET = host
INSTALL_TARGETS += HOST_PROGRAMS INSTALL_TARGETS += HOST_PROGRAMS
endif 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 endif # !NO_DIST_INSTALL
# EOF # EOF

View File

@ -2727,6 +2727,7 @@ MOZ_CHECK_HEADERS([linux/quota.h],,,[#include <sys/socket.h>])
dnl SCTP support - needs various network include headers 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([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) MOZ_CHECK_HEADERS(sys/types.h netinet/in.h byteswap.h)

View File

@ -45,7 +45,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
[test_popup-navigates-children.html] [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) 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] [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] [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) 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] [test_sibling-matching-parent.html]

View File

@ -61,7 +61,7 @@ AnimationPlayer::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
mHoldTime = previousCurrentTime; mHoldTime = previousCurrentTime;
} }
CancelPendingPlay(); CancelPendingTasks();
if (mReady) { if (mReady) {
// We may have already resolved mReady, but in that case calling // We may have already resolved mReady, but in that case calling
// MaybeResolve is a no-op, so that's okay. // MaybeResolve is a no-op, so that's okay.
@ -123,7 +123,12 @@ AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime)
{ {
SilentlySetCurrentTime(aSeekTime); SilentlySetCurrentTime(aSeekTime);
// Once pending pause tasks are supported, cancel that here. if (mPendingState == PendingState::PausePending) {
CancelPendingTasks();
if (mReady) {
mReady->MaybeResolve(this);
}
}
UpdateSourceContent(); UpdateSourceContent();
PostUpdate(); PostUpdate();
@ -160,7 +165,7 @@ AnimationPlayer::SilentlySetPlaybackRate(double aPlaybackRate)
AnimationPlayState AnimationPlayState
AnimationPlayer::PlayState() const AnimationPlayer::PlayState() const
{ {
if (mIsPending) { if (mPendingState != PendingState::NotPending) {
return AnimationPlayState::Pending; return AnimationPlayState::Pending;
} }
@ -267,7 +272,7 @@ AnimationPlayer::Tick()
// it's possible that mPendingReadyTime is set to a time in the future. // 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 // In that case, we should wait until the next refresh driver tick before
// resuming. // resuming.
if (mIsPending && if (mPendingState != PendingState::NotPending &&
!mPendingReadyTime.IsNull() && !mPendingReadyTime.IsNull() &&
mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) { mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
ResumeAt(mPendingReadyTime.Value()); ResumeAt(mPendingReadyTime.Value());
@ -284,12 +289,11 @@ AnimationPlayer::Tick()
} }
void 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, // 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 // due to the handling of possibly orphaned players in Tick(), this player got
// in a later patch in this series], this player got started whilst still // started whilst still being in another document's pending player map.
// being in another document's pending player map.
if (PlayState() != AnimationPlayState::Pending) { if (PlayState() != AnimationPlayState::Pending) {
return; return;
} }
@ -300,7 +304,7 @@ AnimationPlayer::StartOnNextTick(const Nullable<TimeDuration>& aReadyTime)
} }
void void
AnimationPlayer::StartNow() AnimationPlayer::TriggerNow()
{ {
MOZ_ASSERT(PlayState() == AnimationPlayState::Pending, MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
"Expected to start a pending player"); "Expected to start a pending player");
@ -334,8 +338,8 @@ AnimationPlayer::GetCurrentOrPendingStartTime() const
void void
AnimationPlayer::Cancel() AnimationPlayer::Cancel()
{ {
if (mIsPending) { if (mPendingState != PendingState::NotPending) {
CancelPendingPlay(); CancelPendingTasks();
if (mReady) { if (mReady) {
mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR); mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
} }
@ -350,7 +354,9 @@ AnimationPlayer::Cancel()
bool bool
AnimationPlayer::IsRunning() const AnimationPlayer::IsRunning() const
{ {
if (IsPaused() || !GetSource() || GetSource()->IsFinishedTransition()) { if (IsPausedOrPausing() ||
!GetSource() ||
GetSource()->IsFinishedTransition()) {
return false; return false;
} }
@ -424,6 +430,12 @@ AnimationPlayer::DoPlay()
// need to pass a flag so that when we start playing due to a change in // 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. // animation-play-state we *don't* trigger finishing behavior.
bool reuseReadyPromise = false;
if (mPendingState != PendingState::NotPending) {
CancelPendingTasks();
reuseReadyPromise = true;
}
Nullable<TimeDuration> currentTime = GetCurrentTime(); Nullable<TimeDuration> currentTime = GetCurrentTime();
if (mPlaybackRate > 0.0 && if (mPlaybackRate > 0.0 &&
(currentTime.IsNull())) { (currentTime.IsNull())) {
@ -439,17 +451,19 @@ AnimationPlayer::DoPlay()
return; return;
} }
// Clear ready promise. We'll create a new one lazily.
mReady = nullptr;
// Clear the start time until we resolve a new one // Clear the start time until we resolve a new one
mStartTime.SetNull(); mStartTime.SetNull();
mIsPending = true; if (!reuseReadyPromise) {
// Clear ready promise. We'll create a new one lazily.
mReady = nullptr;
}
mPendingState = PendingState::PlayPending;
nsIDocument* doc = GetRenderedDocument(); nsIDocument* doc = GetRenderedDocument();
if (!doc) { if (!doc) {
StartOnNextTick(Nullable<TimeDuration>()); TriggerOnNextTick(Nullable<TimeDuration>());
return; return;
} }
@ -464,8 +478,8 @@ AnimationPlayer::DoPlay()
void void
AnimationPlayer::DoPause() AnimationPlayer::DoPause()
{ {
if (mIsPending) { if (mPendingState == PendingState::PlayPending) {
CancelPendingPlay(); CancelPendingTasks();
// Resolve the ready promise since we currently only use it for // Resolve the ready promise since we currently only use it for
// players that are waiting to play. Later (in bug 1109390), we will // 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 // 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 // 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 // waiting to play. We can easily adapt it to handle other states
// but it's currently not necessary. // but it's currently not necessary.
MOZ_ASSERT(PlayState() == AnimationPlayState::Pending, MOZ_ASSERT(mPendingState == PendingState::PlayPending,
"Expected to resume a pending player"); "Expected to resume a play-pending player");
MOZ_ASSERT(!mHoldTime.IsNull(), 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) { if (mPlaybackRate != 0) {
mStartTime.SetValue(aResumeTime - (mHoldTime.Value() / mPlaybackRate)); mStartTime.SetValue(aResumeTime - (mHoldTime.Value() / mPlaybackRate));
@ -502,7 +517,7 @@ AnimationPlayer::ResumeAt(const TimeDuration& aResumeTime)
} else { } else {
mStartTime.SetValue(aResumeTime); mStartTime.SetValue(aResumeTime);
} }
mIsPending = false; mPendingState = PendingState::NotPending;
UpdateSourceContent(); UpdateSourceContent();
@ -539,9 +554,9 @@ AnimationPlayer::PostUpdate()
} }
void void
AnimationPlayer::CancelPendingPlay() AnimationPlayer::CancelPendingTasks()
{ {
if (!mIsPending) { if (mPendingState == PendingState::NotPending) {
return; return;
} }
@ -549,11 +564,15 @@ AnimationPlayer::CancelPendingPlay()
if (doc) { if (doc) {
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker(); PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
if (tracker) { if (tracker) {
if (mPendingState == PendingState::PlayPending) {
tracker->RemovePlayPending(*this); tracker->RemovePlayPending(*this);
} else {
tracker->RemovePausePending(*this);
}
} }
} }
mIsPending = false; mPendingState = PendingState::NotPending;
mPendingReadyTime.SetNull(); mPendingReadyTime.SetNull();
} }
@ -574,11 +593,11 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
// when we have been painted. // when we have been painted.
// * When we started playing we couldn't find a PendingPlayerTracker to // * When we started playing we couldn't find a PendingPlayerTracker to
// register with (perhaps the source content had no document) so we simply // 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. // next tick.
// If we're not pending we're ok. // If we're not pending we're ok.
if (!mIsPending) { if (mPendingState == PendingState::NotPending) {
return false; return false;
} }
@ -598,12 +617,17 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
// PendingPlayerTracker then there's a good chance no one is tracking us. // 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 // 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 // simply start/pause the animation one tick too soon. That's better than
// starting the animation and is unlikely. // never starting/pausing the animation and is unlikely.
nsIDocument* doc = GetRenderedDocument(); nsIDocument* doc = GetRenderedDocument();
return !doc || if (!doc) {
!doc->GetPendingPlayerTracker() || return false;
!doc->GetPendingPlayerTracker()->IsWaitingToPlay(*this); }
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
return !tracker ||
(!tracker->IsWaitingToPlay(*this) &&
!tracker->IsWaitingToPause(*this));
} }
StickyTimeDuration StickyTimeDuration

View File

@ -54,7 +54,7 @@ public:
explicit AnimationPlayer(AnimationTimeline* aTimeline) explicit AnimationPlayer(AnimationTimeline* aTimeline)
: mTimeline(aTimeline) : mTimeline(aTimeline)
, mPlaybackRate(1.0) , mPlaybackRate(1.0)
, mIsPending(false) , mPendingState(PendingState::NotPending)
, mIsRunningOnCompositor(false) , mIsRunningOnCompositor(false)
, mIsPreviousStateFinished(false) , mIsPreviousStateFinished(false)
, mIsRelevant(false) , mIsRelevant(false)
@ -107,6 +107,8 @@ public:
void Tick(); 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 * 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. * 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 * 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 * players do start, they can be timed from the point when painting
* completed. * 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 * 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. * time at which they resumed.
* *
* This approach means that any setup time required for performing the * 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 * between triggering an animation and its effective start is unacceptably
* long. * 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 * Note that the caller of this method is responsible for removing the player
* from any PendingPlayerTracker it may have been added to. * 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. // Testing only: Start or pause a pending player using the current timeline
// This is used to support existing tests that expect animations to begin // time. This is used to support existing tests that expect animations to
// immediately. Ideally we would rewrite the those tests and get rid of this // begin immediately. Ideally we would rewrite the those tests and get rid of
// method, but there are a lot of them. // 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 // removing the player from any PendingPlayerTracker it may have been added
// to. // to.
void StartNow(); void TriggerNow();
/** /**
* When StartOnNextTick is called, we store the ready time but we don't apply * When StartOnNextTick is called, we store the ready time but we don't apply
@ -182,17 +191,24 @@ public:
void Cancel(); void Cancel();
const nsString& Name() const { const nsString& Name() const
{
return mSource ? mSource->Name() : EmptyString(); 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 IsRunning() const;
bool HasCurrentSource() const { bool HasCurrentSource() const
{
return GetSource() && GetSource()->IsCurrent(); return GetSource() && GetSource()->IsCurrent();
} }
bool HasInEffectSource() const { bool HasInEffectSource() const
{
return GetSource() && GetSource()->IsInEffect(); return GetSource() && GetSource()->IsInEffect();
} }
@ -226,10 +242,12 @@ protected:
void UpdateSourceContent(); void UpdateSourceContent();
void FlushStyle() const; void FlushStyle() const;
void PostUpdate(); void PostUpdate();
// Remove this player from the pending player tracker and resets mIsPending /**
// as necessary. The caller is responsible for resolving or aborting the * Remove this player from the pending player tracker and reset
// mReady promise as necessary. * mPendingState as necessary. The caller is responsible for resolving or
void CancelPendingPlay(); * aborting the mReady promise as necessary.
*/
void CancelPendingTasks();
bool IsPossiblyOrphanedPendingPlayer() const; bool IsPossiblyOrphanedPendingPlayer() const;
StickyTimeDuration SourceContentEnd() const; StickyTimeDuration SourceContentEnd() const;
@ -252,12 +270,15 @@ protected:
// This object is lazily created by GetReady. // This object is lazily created by GetReady.
nsRefPtr<Promise> mReady; nsRefPtr<Promise> mReady;
// Indicates if the player is in the pending state. We use this rather // Indicates if the player is in the pending state (and what state it is
// than checking if this player is tracked by a PendingPlayerTracker. // waiting to enter when it finished pending). We use this rather than
// This is because the PendingPlayerTracker is associated with the source // checking if this player is tracked by a PendingPlayerTracker because the
// content's document but we need to know if we're pending even if the // player will continue to be pending even after it has been removed from the
// source content loses association with its document. // PendingPlayerTracker while it is waiting for the next tick
bool mIsPending; // (see TriggerOnNextTick for details).
enum class PendingState { NotPending, PlayPending, PausePending };
PendingState mPendingState;
bool mIsRunningOnCompositor; bool mIsRunningOnCompositor;
// Indicates whether we were in the finished state during our // Indicates whether we were in the finished state during our
// most recent unthrottled sample (our last ComposeStyle call). // most recent unthrottled sample (our last ComposeStyle call).

View File

@ -13,15 +13,19 @@ using namespace mozilla;
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_ROOT_NATIVE(PendingPlayerTracker, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingPlayerTracker, Release) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingPlayerTracker, Release)
void 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 // Schedule a paint. Otherwise animations that don't trigger a paint by
// themselves (e.g. CSS animations with an empty keyframes rule) won't // themselves (e.g. CSS animations with an empty keyframes rule) won't
@ -30,19 +34,21 @@ PendingPlayerTracker::AddPlayPending(dom::AnimationPlayer& aPlayer)
} }
void void
PendingPlayerTracker::RemovePlayPending(dom::AnimationPlayer& aPlayer) PendingPlayerTracker::RemovePending(dom::AnimationPlayer& aPlayer,
AnimationPlayerSet& aSet)
{ {
mPlayPendingSet.RemoveEntry(&aPlayer); aSet.RemoveEntry(&aPlayer);
} }
bool 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 PLDHashOperator
StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, TriggerPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
void* aReadyTime) void* aReadyTime)
{ {
dom::AnimationPlayer* player = aKey->GetKey(); dom::AnimationPlayer* player = aKey->GetKey();
@ -51,38 +57,43 @@ StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
// When the timeline's refresh driver is under test control, its values // 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 // 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 // aReadyTime (which is a wallclock time) to a timeline value. Instead, the
// animation player will be started when the refresh driver is next // animation player will be started/paused when the refresh driver is next
// advanced since this will trigger a call to StartPendingPlayersNow. // advanced since this will trigger a call to TriggerPendingPlayersNow.
if (timeline->IsUnderTestControl()) { if (timeline->IsUnderTestControl()) {
return PL_DHASH_NEXT; return PL_DHASH_NEXT;
} }
Nullable<TimeDuration> readyTime = Nullable<TimeDuration> readyTime =
timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime)); timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime));
player->StartOnNextTick(readyTime); player->TriggerOnNextTick(readyTime);
return PL_DHASH_REMOVE; return PL_DHASH_REMOVE;
} }
void 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)); const_cast<TimeStamp*>(&aReadyTime));
} }
PLDHashOperator PLDHashOperator
StartPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*) TriggerPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
{ {
aKey->GetKey()->StartNow(); aKey->GetKey()->TriggerNow();
return PL_DHASH_NEXT; return PL_DHASH_NEXT;
} }
void void
PendingPlayerTracker::StartPendingPlayersNow() PendingPlayerTracker::TriggerPendingPlayersNow()
{ {
mPlayPendingSet.EnumerateEntries(StartPlayerNow, nullptr); mPlayPendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
mPlayPendingSet.Clear(); mPlayPendingSet.Clear();
mPausePendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
mPausePendingSet.Clear();
} }
void void

View File

@ -25,13 +25,41 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker) NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker)
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker)
void AddPlayPending(dom::AnimationPlayer& aPlayer); void AddPlayPending(dom::AnimationPlayer& aPlayer)
void RemovePlayPending(dom::AnimationPlayer& aPlayer); {
bool IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const; 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 AddPausePending(dom::AnimationPlayer& aPlayer)
void StartPendingPlayersNow(); {
bool HasPendingPlayers() const { return mPlayPendingSet.Count() > 0; } 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: private:
~PendingPlayerTracker() { } ~PendingPlayerTracker() { }
@ -41,7 +69,15 @@ private:
typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>> typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>>
AnimationPlayerSet; 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 mPlayPendingSet;
AnimationPlayerSet mPausePendingSet;
nsCOMPtr<nsIDocument> mDocument; nsCOMPtr<nsIDocument> mDocument;
}; };

View File

@ -31,10 +31,11 @@ async_test(function(t) {
player.ready.then(waitForFrame).then(t.step_func(function() { player.ready.then(waitForFrame).then(t.step_func(function() {
assert_true(getMarginLeft(cs) > previousAnimVal, assert_true(getMarginLeft(cs) > previousAnimVal,
'margin-left is initially increasing'); 'margin-left is initially increasing');
previousAnimVal = getMarginLeft(cs);
player.pause(); 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() { })).then(t.step_func(function() {
assert_equals(getMarginLeft(cs), previousAnimVal, assert_equals(getMarginLeft(cs), previousAnimVal,
'margin-left does not increase after calling pause()'); 'margin-left does not increase after calling pause()');
@ -102,13 +103,14 @@ async_test(function(t) {
}).then(t.step_func(function() { }).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'running', assert_equals(cs.animationPlayState, 'running',
'animation-play-state is running'); 'animation-play-state is running');
previousAnimVal = getMarginLeft(cs);
div.style.animationPlayState = 'paused'; div.style.animationPlayState = 'paused';
cs.animationPlayState; // Trigger style resolution return player.ready;
return waitForFrame();
})).then(t.step_func(function() { })).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'paused', assert_equals(cs.animationPlayState, 'paused',
'animation-play-state is paused'); 'animation-play-state is paused');
previousAnimVal = getMarginLeft(cs);
return waitForFrame();
})).then(t.step_func(function() {
assert_equals(getMarginLeft(cs), previousAnimVal, assert_equals(getMarginLeft(cs), previousAnimVal,
'Animated value of margin-left does not change when' 'Animated value of margin-left does not change when'
+ ' paused by style'); + ' paused by style');
@ -164,9 +166,9 @@ async_test(function(t) {
player.pause(); player.pause();
var previousAnimVal = getMarginLeft(cs); var previousAnimVal = getMarginLeft(cs);
waitForFrame().then(t.step_func(function() { player.ready.then(waitForFrame).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'running', assert_equals(cs.animationPlayState, 'running',
'animation-play-state is paused'); 'animation-play-state is running');
assert_equals(getMarginLeft(cs), previousAnimVal, assert_equals(getMarginLeft(cs), previousAnimVal,
'Paused value of margin-left does not change'); 'Paused value of margin-left does not change');
t.done(); t.done();

View File

@ -588,28 +588,25 @@ async_test(function(t) {
div.style.animation = 'anim 100s'; div.style.animation = 'anim 100s';
var player = div.getAnimationPlayers()[0]; var player = div.getAnimationPlayers()[0];
var pauseTime;
player.ready.then(t.step_func(function() { player.ready.then(t.step_func(function() {
var savedCurrentTime = player.currentTime;
assert_not_equals(player.currentTime, null, assert_not_equals(player.currentTime, null,
'AnimationPlayer.currentTime not null on ready Promise resolve'); 'AnimationPlayer.currentTime not null on ready Promise resolve');
var prePauseCurrentTime = player.currentTime;
player.pause(); 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.currentTime, prePauseCurrentTime, pauseTime = player.currentTime;
'AnimationPlayer.currentTime is unchanged after AnimationPlayer.pause()'); return waitForFrame();
assert_equals(player.playState, 'paused', })).then(t.step_func(function() {
'AnimationPlayer.playState is "paused" after pause() call'); assert_equals(player.currentTime, pauseTime,
'AnimationPlayer.currentTime is unchanged after pausing');
})).catch(t.step_func(function(reason) { })).catch(t.step_func(function(reason) {
assert_unreached(reason); assert_unreached(reason);
})).then(function() { })).then(function() {
t.done(); t.done();
}); });
}, 'AnimationPlayer.currentTime after paused'); }, 'AnimationPlayer.currentTime after pausing');
</script> </script>
</body> </body>

View File

@ -24,23 +24,37 @@ async_test(function(t) {
})); }));
}, 'Player returns correct playState when running'); }, 'Player returns correct playState when running');
test(function(t) { async_test(function(t) {
var div = addDiv(t); var div = addDiv(t);
var cs = window.getComputedStyle(div); var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused'; div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0]; var player = div.getAnimationPlayers()[0];
// 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'); assert_equals(player.playState, 'paused');
t.done();
}));
}, 'Player returns correct playState when paused'); }, 'Player returns correct playState when paused');
test(function(t) { async_test(function(t) {
var div = addDiv(t); var div = addDiv(t);
var cs = window.getComputedStyle(div); var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s'; div.style.animation = 'anim 1000s';
var player = div.getAnimationPlayers()[0]; var player = div.getAnimationPlayers()[0];
player.pause(); player.pause();
// 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'); assert_equals(player.playState, 'paused');
t.done();
}));
}, 'Player.playState updates when paused by script'); }, 'Player.playState updates when paused by script');
test(function(t) { test(function(t) {

View File

@ -618,8 +618,8 @@ async_test(function(t) {
'AnimationPlayer.startTime not null on ready Promise resolve'); 'AnimationPlayer.startTime not null on ready Promise resolve');
player.pause(); 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, assert_equals(player.startTime, null,
'AnimationPlayer.startTime is null after paused'); 'AnimationPlayer.startTime is null after paused');
assert_equals(player.playState, 'paused', assert_equals(player.playState, 'paused',

View File

@ -384,8 +384,8 @@ async_test(function(t) {
'AnimationPlayer.startTime not null on ready Promise resolve'); 'AnimationPlayer.startTime not null on ready Promise resolve');
player.pause(); 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, assert_equals(player.startTime, null,
'AnimationPlayer.startTime is null after paused'); 'AnimationPlayer.startTime is null after paused');
assert_equals(player.playState, 'paused', assert_equals(player.playState, 'paused',

View File

@ -483,7 +483,7 @@ WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aR
{ {
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags)); MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); 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(), xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
win ? win->WindowID() : 0); win ? win->WindowID() : 0);
xpcReport->LogToConsole(); xpcReport->LogToConsole();

View File

@ -2595,7 +2595,7 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
if (doc) { if (doc) {
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker(); PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
if (tracker) { if (tracker) {
tracker->StartPendingPlayersNow(); tracker->TriggerPendingPlayersNow();
} }
} }
@ -3985,6 +3985,32 @@ nsDOMWindowUtils::GetFramesReflowed(uint64_t* aResult)
return NS_OK; 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_BEGIN(nsTranslationNodeList)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList) NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)

View File

@ -884,8 +884,7 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
// Don't show remote iframe if we are waiting for the completion of reflow. // Don't show remote iframe if we are waiting for the completion of reflow.
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement(); mRemoteBrowser->UpdateDimensions(dimensions, size);
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
} }
} }
@ -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; nsCOMPtr<nsIDocument> doc;
bool dynamicSubframeRemoval = false; bool dynamicSubframeRemoval = false;
if (mOwnerContent) { if (mOwnerContent) {
@ -2058,8 +2063,7 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
ScreenIntSize size = aIFrame->GetSubdocumentSize(); ScreenIntSize size = aIFrame->GetSubdocumentSize();
nsIntRect dimensions; nsIntRect dimensions;
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement(); mRemoteBrowser->UpdateDimensions(dimensions, size);
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
} }
return NS_OK; return NS_OK;
} }

View File

@ -229,6 +229,9 @@ public:
void ActivateUpdateHitRegion(); void ActivateUpdateHitRegion();
void DeactivateUpdateHitRegion(); void DeactivateUpdateHitRegion();
// Properly retrieves documentSize of any subdocument type.
nsresult GetWindowDimensions(nsIntRect& aRect);
private: private:
void SetOwnerContent(mozilla::dom::Element* aContent); void SetOwnerContent(mozilla::dom::Element* aContent);
@ -284,9 +287,6 @@ private:
nsresult MaybeCreateDocShell(); nsresult MaybeCreateDocShell();
nsresult EnsureMessageManager(); nsresult EnsureMessageManager();
// Properly retrieves documentSize of any subdocument type.
nsresult GetWindowDimensions(nsIntRect& aRect);
// Updates the subdocument position and size. This gets called only // Updates the subdocument position and size. This gets called only
// when we have our own in-process DocShell. // when we have our own in-process DocShell.
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame); void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);

View File

@ -584,7 +584,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
mOuterWindow(aOuterWindow), mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0 // Make sure no actual window ends up with mWindowID == 0
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false), mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
mMarkedCCGeneration(0) mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false)
{} {}
nsPIDOMWindow::~nsPIDOMWindow() {} nsPIDOMWindow::~nsPIDOMWindow() {}

View File

@ -91,6 +91,13 @@
#endif #endif
#endif // XP_WIN #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 NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static const char *kPrefJavaMIME = "plugin.java.mime"; static const char *kPrefJavaMIME = "plugin.java.mime";
@ -867,6 +874,10 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
NS_LITERAL_STRING("PluginInstantiated")); NS_LITERAL_STRING("PluginInstantiated"));
NS_DispatchToCurrentThread(ev); NS_DispatchToCurrentThread(ev);
#ifdef XP_MACOSX
HTMLObjectElement::HandlePluginInstantiated(thisContent->AsElement());
#endif
return NS_OK; return NS_OK;
} }
@ -2723,14 +2734,19 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
LOG(("OBJLC [%p]: Plugin Crashed, queuing crash event", this)); LOG(("OBJLC [%p]: Plugin Crashed, queuing crash event", this));
NS_ASSERTION(mType == eType_Plugin, "PluginCrashed at non-plugin type"); 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(); PluginDestroyed();
// Switch to fallback/crashed state, notify // Switch to fallback/crashed state, notify
LoadFallback(eFallbackCrashed, true); LoadFallback(eFallbackCrashed, true);
// send nsPluginCrashedEvent // send nsPluginCrashedEvent
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
// Note that aPluginTag in invalidated after we're called, so copy // Note that aPluginTag in invalidated after we're called, so copy
// out any data we need now. // out any data we need now.

View File

@ -186,6 +186,18 @@ public:
float GetAudioGlobalVolume(); float GetAudioGlobalVolume();
virtual void SetServiceWorkersTestingEnabled(bool aEnabled)
{
MOZ_ASSERT(IsOuterWindow());
mServiceWorkersTestingEnabled = aEnabled;
}
bool GetServiceWorkersTestingEnabled()
{
MOZ_ASSERT(IsOuterWindow());
return mServiceWorkersTestingEnabled;
}
protected: protected:
// Lazily instantiate an about:blank document if necessary, and if // Lazily instantiate an about:blank document if necessary, and if
// we have what it takes to do so. // we have what it takes to do so.
@ -798,6 +810,10 @@ protected:
bool mHasNotifiedGlobalCreated; bool mHasNotifiedGlobalCreated;
uint32_t mMarkedCCGeneration; uint32_t mMarkedCCGeneration;
// Let the service workers plumbing know that some feature are enabled while
// testing.
bool mServiceWorkersTestingEnabled;
}; };

View File

@ -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>

View File

@ -86,6 +86,7 @@ support-files =
file_self_none_as_hostname_confusion.html file_self_none_as_hostname_confusion.html
file_self_none_as_hostname_confusion.html^headers^ file_self_none_as_hostname_confusion.html^headers^
file_csp_path_matching.html file_csp_path_matching.html
file_csp_path_matching_incl_query.html
file_csp_path_matching.js file_csp_path_matching.js
file_csp_path_matching_redirect.html file_csp_path_matching_redirect.html
file_csp_path_matching_redirect_server.sjs file_csp_path_matching_redirect_server.sjs

View File

@ -79,9 +79,14 @@ function loadNextTest() {
} }
else { else {
policy = policies[counter++]; policy = policies[counter++];
var src = "file_csp_testserver.sjs"; var src = "file_csp_testserver.sjs?file=";
// append the file that should be served // 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 // append the CSP that should be used to serve the file
src += "&csp=" + escape("default-src 'none'; script-src " + policy[1]); src += "&csp=" + escape("default-src 'none'; script-src " + policy[1]);

View File

@ -1525,7 +1525,7 @@ DOMInterfaces = {
'headerFile': 'mozilla/dom/WorkerScope.h', 'headerFile': 'mozilla/dom/WorkerScope.h',
'nativeType': 'mozilla::dom::workers::WorkerDebuggerGlobalScope', 'nativeType': 'mozilla::dom::workers::WorkerDebuggerGlobalScope',
'implicitJSContext': [ 'implicitJSContext': [
'dump', 'global', 'dump', 'global', 'reportError',
], ],
}, },

View File

@ -243,16 +243,14 @@ protected:
return false; return false;
} }
virtual nsresult GetLineno(int32_t* aLineNo) virtual int32_t GetLineno()
{ {
*aLineNo = mLineno; return mLineno;
return NS_OK;
} }
virtual nsresult GetColNo(int32_t* aColNo) virtual int32_t GetColNo()
{ {
*aColNo = mColNo; return mColNo;
return NS_OK;
} }
nsCOMPtr<nsIStackFrame> mCaller; nsCOMPtr<nsIStackFrame> mCaller;
@ -318,8 +316,8 @@ protected:
return true; return true;
} }
virtual nsresult GetLineno(int32_t* aLineNo) override; virtual int32_t GetLineno() override;
virtual nsresult GetColNo(int32_t* aColNo) override; virtual int32_t GetColNo() override;
private: private:
virtual ~JSStackFrame(); virtual ~JSStackFrame();
@ -437,7 +435,11 @@ GetValueIfNotCached(JSContext* aCx, JSObject* aStack,
/* readonly attribute AString filename; */ /* readonly attribute AString filename; */
NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename) NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename)
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
aFilename.Truncate();
return NS_OK;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
JS::Rooted<JSString*> filename(cx); JS::Rooted<JSString*> filename(cx);
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -449,7 +451,9 @@ NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename)
nsAutoJSString str; nsAutoJSString str;
if (!str.init(cx, filename)) { if (!str.init(cx, filename)) {
return NS_ERROR_OUT_OF_MEMORY; JS_ClearPendingException(cx);
aFilename.Truncate();
return NS_OK;
} }
aFilename = str; aFilename = str;
@ -476,7 +480,11 @@ NS_IMETHODIMP StackFrame::GetFilename(nsAString& aFilename)
/* readonly attribute AString name; */ /* readonly attribute AString name; */
NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction) NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
aFunction.Truncate();
return NS_OK;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
JS::Rooted<JSString*> name(cx); JS::Rooted<JSString*> name(cx);
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -491,7 +499,9 @@ NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
if (name) { if (name) {
nsAutoJSString str; nsAutoJSString str;
if (!str.init(cx, name)) { if (!str.init(cx, name)) {
return NS_ERROR_OUT_OF_MEMORY; JS_ClearPendingException(cx);
aFunction.Truncate();
return NS_OK;
} }
aFunction = str; aFunction = str;
} else { } else {
@ -519,10 +529,13 @@ NS_IMETHODIMP StackFrame::GetName(nsAString& aFunction)
} }
// virtual // virtual
nsresult int32_t
JSStackFrame::GetLineno(int32_t* aLineNo) JSStackFrame::GetLineno()
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
return 0;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
uint32_t line; uint32_t line;
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -530,30 +543,32 @@ JSStackFrame::GetLineno(int32_t* aLineNo)
&canCache, &useCachedValue, &line); &canCache, &useCachedValue, &line);
if (useCachedValue) { if (useCachedValue) {
return StackFrame::GetLineno(aLineNo); return StackFrame::GetLineno();
} }
*aLineNo = line;
if (canCache) { if (canCache) {
mLineno = line; mLineno = line;
mLinenoInitialized = true; mLinenoInitialized = true;
} }
return NS_OK; return line;
} }
/* readonly attribute int32_t lineNumber; */ /* readonly attribute int32_t lineNumber; */
NS_IMETHODIMP StackFrame::GetLineNumber(int32_t* aLineNumber) NS_IMETHODIMP StackFrame::GetLineNumber(int32_t* aLineNumber)
{ {
return GetLineno(aLineNumber); *aLineNumber = GetLineno();
return NS_OK;
} }
// virtual // virtual
nsresult int32_t
JSStackFrame::GetColNo(int32_t* aColNo) JSStackFrame::GetColNo()
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
return 0;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
uint32_t col; uint32_t col;
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -561,23 +576,22 @@ JSStackFrame::GetColNo(int32_t* aColNo)
&canCache, &useCachedValue, &col); &canCache, &useCachedValue, &col);
if (useCachedValue) { if (useCachedValue) {
return StackFrame::GetColNo(aColNo); return StackFrame::GetColNo();
} }
*aColNo = col;
if (canCache) { if (canCache) {
mColNo = col; mColNo = col;
mColNoInitialized = true; mColNoInitialized = true;
} }
return NS_OK; return col;
} }
/* readonly attribute int32_t columnNumber; */ /* readonly attribute int32_t columnNumber; */
NS_IMETHODIMP StackFrame::GetColumnNumber(int32_t* aColumnNumber) NS_IMETHODIMP StackFrame::GetColumnNumber(int32_t* aColumnNumber)
{ {
return GetColNo(aColumnNumber); *aColumnNumber = GetColNo();
return NS_OK;
} }
/* readonly attribute AUTF8String sourceLine; */ /* readonly attribute AUTF8String sourceLine; */
@ -590,7 +604,11 @@ NS_IMETHODIMP StackFrame::GetSourceLine(nsACString& aSourceLine)
/* readonly attribute AString asyncCause; */ /* readonly attribute AString asyncCause; */
NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause) NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause)
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
aAsyncCause.Truncate();
return NS_OK;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
JS::Rooted<JSString*> asyncCause(cx); JS::Rooted<JSString*> asyncCause(cx);
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -605,7 +623,9 @@ NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause)
if (asyncCause) { if (asyncCause) {
nsAutoJSString str; nsAutoJSString str;
if (!str.init(cx, asyncCause)) { if (!str.init(cx, asyncCause)) {
return NS_ERROR_OUT_OF_MEMORY; JS_ClearPendingException(cx);
aAsyncCause.Truncate();
return NS_OK;
} }
aAsyncCause = str; aAsyncCause = str;
} else { } else {
@ -635,7 +655,11 @@ NS_IMETHODIMP StackFrame::GetAsyncCause(nsAString& aAsyncCause)
/* readonly attribute nsIStackFrame asyncCaller; */ /* readonly attribute nsIStackFrame asyncCaller; */
NS_IMETHODIMP JSStackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller) NS_IMETHODIMP JSStackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
*aAsyncCaller = nullptr;
return NS_OK;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
JS::Rooted<JSObject*> asyncCallerObj(cx); JS::Rooted<JSObject*> asyncCallerObj(cx);
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -668,7 +692,11 @@ NS_IMETHODIMP StackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
/* readonly attribute nsIStackFrame caller; */ /* readonly attribute nsIStackFrame caller; */
NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller) NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
{ {
NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE); if (!mStack) {
*aCaller = nullptr;
return NS_OK;
}
ThreadsafeAutoJSContext cx; ThreadsafeAutoJSContext cx;
JS::Rooted<JSObject*> callerObj(cx); JS::Rooted<JSObject*> callerObj(cx);
bool canCache = false, useCachedValue = false; bool canCache = false, useCachedValue = false;
@ -706,7 +734,11 @@ NS_IMETHODIMP StackFrame::GetCaller(nsIStackFrame** aCaller)
NS_IMETHODIMP JSStackFrame::GetFormattedStack(nsAString& aStack) 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 // Sadly we can't use GetValueIfNotCached here, because our getter
// returns bool, not JS::SavedFrameResult. Maybe it's possible to // returns bool, not JS::SavedFrameResult. Maybe it's possible to
// make the templates more complicated to deal, but in the meantime // 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); JS::Rooted<JSString*> formattedStack(cx);
if (!JS::StringifySavedFrameStack(cx, stack, &formattedStack)) { if (!JS::StringifySavedFrameStack(cx, stack, &formattedStack)) {
return NS_ERROR_UNEXPECTED; JS_ClearPendingException(cx);
aStack.Truncate();
return NS_OK;
} }
nsAutoJSString str; nsAutoJSString str;
if (!str.init(cx, formattedStack)) { if (!str.init(cx, formattedStack)) {
return NS_ERROR_OUT_OF_MEMORY; JS_ClearPendingException(cx);
aStack.Truncate();
return NS_OK;
} }
aStack = str; aStack = str;
@ -787,9 +823,7 @@ NS_IMETHODIMP StackFrame::ToString(nsACString& _retval)
funname.AssignLiteral("<TOP_LEVEL>"); funname.AssignLiteral("<TOP_LEVEL>");
} }
int32_t lineno; int32_t lineno = GetLineno();
rv = GetLineno(&lineno);
NS_ENSURE_SUCCESS(rv, rv);
static const char format[] = "%s frame :: %s :: %s :: line %d"; static const char format[] = "%s frame :: %s :: %s :: line %d";
_retval.AppendPrintf(format, frametype, _retval.AppendPrintf(format, frametype,

View File

@ -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_implicit_color_buffer_float.html]
[webgl-mochitest/test_highp_fs.html] [webgl-mochitest/test_highp_fs.html]
[webgl-mochitest/test_no_arr_points.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_noprog_draw.html]
[webgl-mochitest/test_privileged_exts.html] [webgl-mochitest/test_privileged_exts.html]
[webgl-mochitest/test_texsubimage_float.html] [webgl-mochitest/test_texsubimage_float.html]

View File

@ -1176,7 +1176,7 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
nsPoint ptInTarget = ptInRoot + rootFrame->GetOffsetToCrossDoc(targetFrame); nsPoint ptInTarget = ptInRoot + rootFrame->GetOffsetToCrossDoc(targetFrame);
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel(); int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
int32_t targetAPD = targetFrame->PresContext()->AppUnitsPerDevPixel(); int32_t targetAPD = targetFrame->PresContext()->AppUnitsPerDevPixel();
ptInTarget = ptInTarget.ConvertAppUnits(rootAPD, targetAPD); ptInTarget = ptInTarget.ScaleToOtherAppUnits(rootAPD, targetAPD);
nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame); nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame);
nsIFrame::ContentOffsets contentOffsets = nsIFrame::ContentOffsets contentOffsets =

View File

@ -23,6 +23,7 @@
#ifdef XP_MACOSX #ifdef XP_MACOSX
#include "mozilla/EventDispatcher.h" #include "mozilla/EventDispatcher.h"
#include "mozilla/dom/Event.h" #include "mozilla/dom/Event.h"
#include "nsFocusManager.h"
#endif #endif
namespace mozilla { namespace mozilla {
@ -151,6 +152,22 @@ private:
void void
HTMLObjectElement::OnFocusBlurPlugin(Element* aElement, bool aFocus) 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 || aElement == sLastFocused) {
if (!aFocus) { if (!aFocus) {
sLastFocused = nullptr; 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 void
HTMLObjectElement::HandleFocusBlurPlugin(Element* aElement, HTMLObjectElement::HandleFocusBlurPlugin(Element* aElement,
WidgetEvent* aEvent) WidgetEvent* aEvent)

View File

@ -36,6 +36,8 @@ public:
// Helper methods // Helper methods
static void OnFocusBlurPlugin(Element* aElement, bool aFocus); static void OnFocusBlurPlugin(Element* aElement, bool aFocus);
static void HandleFocusBlurPlugin(Element* aElement, WidgetEvent* aEvent); 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. // Weak pointer. Null if last action was blur.
static Element* sLastFocused; static Element* sLastFocused;
#endif #endif

View File

@ -28,13 +28,13 @@ skip-if = buildapp == 'mulet'
[test_input_color_picker_initial.html] [test_input_color_picker_initial.html]
skip-if = buildapp == 'mulet' skip-if = buildapp == 'mulet'
[test_input_color_picker_popup.html] [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] [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_defaultValue.html]
[test_input_email.html] [test_input_email.html]
[test_input_event.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] [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) 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] [test_input_list_attribute.html]

View File

@ -50,7 +50,7 @@ interface nsITranslationNodeList;
interface nsIJSRAIIHelper; interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest; interface nsIContentPermissionRequest;
[scriptable, uuid(400db885-c2b8-4bf1-bc12-1dadcb08ad12)] [scriptable, uuid(7f2f44ab-2857-4cc2-8c9d-3d9816f5a4d6)]
interface nsIDOMWindowUtils : nsISupports { interface nsIDOMWindowUtils : nsISupports {
/** /**
@ -1757,6 +1757,11 @@ interface nsIDOMWindowUtils : nsISupports {
in int32_t aRight, in int32_t aRight,
in int32_t aBottom, in int32_t aBottom,
in int32_t aLeft); in int32_t aLeft);
/**
* Enable some service workers testing features.
*/
attribute boolean serviceWorkersTestingEnabled;
}; };
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)] [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]

View File

@ -55,10 +55,10 @@ FilePickerParent::~FilePickerParent()
// the same runnable on the main thread. // the same runnable on the main thread.
// 3. The main thread sends the results over IPC. // 3. The main thread sends the results over IPC.
FilePickerParent::FileSizeAndDateRunnable::FileSizeAndDateRunnable(FilePickerParent *aFPParent, FilePickerParent::FileSizeAndDateRunnable::FileSizeAndDateRunnable(FilePickerParent *aFPParent,
nsCOMArray<nsIDOMFile>& aDomfiles) nsTArray<nsRefPtr<FileImpl>>& aFiles)
: mFilePickerParent(aFPParent) : mFilePickerParent(aFPParent)
{ {
mDomfiles.SwapElements(aDomfiles); mFiles.SwapElements(aFiles);
} }
bool bool
@ -82,16 +82,16 @@ FilePickerParent::FileSizeAndDateRunnable::Run()
// results. // results.
if (NS_IsMainThread()) { if (NS_IsMainThread()) {
if (mFilePickerParent) { if (mFilePickerParent) {
mFilePickerParent->SendFiles(mDomfiles); mFilePickerParent->SendFiles(mFiles);
} }
return NS_OK; return NS_OK;
} }
// We're not on the main thread, so do the stat(). // We're not on the main thread, so do the stat().
for (unsigned i = 0; i < mDomfiles.Length(); i++) { for (unsigned i = 0; i < mFiles.Length(); i++) {
uint64_t size, lastModified; ErrorResult rv;
mDomfiles[i]->GetSize(&size); mFiles[i]->GetSize(rv);
mDomfiles[i]->GetMozLastModifiedDate(&lastModified); mFiles[i]->GetLastModified(rv);
} }
// Dispatch ourselves back on the main thread. // Dispatch ourselves back on the main thread.
@ -111,14 +111,14 @@ FilePickerParent::FileSizeAndDateRunnable::Destroy()
} }
void void
FilePickerParent::SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles) FilePickerParent::SendFiles(const nsTArray<nsRefPtr<FileImpl>>& aFiles)
{ {
nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager(); nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager();
InfallibleTArray<PBlobParent*> files; InfallibleTArray<PBlobParent*> files;
for (unsigned i = 0; i < aDomfiles.Length(); i++) { for (unsigned i = 0; i < aFiles.Length(); i++) {
BlobParent* blob = parent->GetOrCreateActorForBlob( nsRefPtr<File> file = new File(nullptr, aFiles[i]);
static_cast<File*>(aDomfiles[i])); BlobParent* blob = parent->GetOrCreateActorForBlob(file);
if (blob) { if (blob) {
files.AppendElement(blob); files.AppendElement(blob);
} }
@ -139,7 +139,7 @@ FilePickerParent::Done(int16_t aResult)
return; return;
} }
nsCOMArray<nsIDOMFile> domfiles; nsTArray<nsRefPtr<FileImpl>> files;
if (mMode == nsIFilePicker::modeOpenMultiple) { if (mMode == nsIFilePicker::modeOpenMultiple) {
nsCOMPtr<nsISimpleEnumerator> iter; nsCOMPtr<nsISimpleEnumerator> iter;
NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter))); NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));
@ -151,25 +151,21 @@ FilePickerParent::Done(int16_t aResult)
if (supports) { if (supports) {
nsCOMPtr<nsIFile> file = do_QueryInterface(supports); nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
// A null parent is fine because File are not used in this process nsRefPtr<FileImpl> fileimpl = new FileImplFile(file);
// but only in the child. files.AppendElement(fileimpl);
nsCOMPtr<nsIDOMFile> domfile = File::CreateFromFile(nullptr, file);
domfiles.AppendElement(domfile);
} }
} }
} else { } else {
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
mFilePicker->GetFile(getter_AddRefs(file)); mFilePicker->GetFile(getter_AddRefs(file));
if (file) { if (file) {
// A null parent is fine because File are not used in this process nsRefPtr<FileImpl> fileimpl = new FileImplFile(file);
// but only in the child. files.AppendElement(fileimpl);
nsCOMPtr<nsIDOMFile> domfile = File::CreateFromFile(nullptr, file);
domfiles.AppendElement(domfile);
} }
} }
MOZ_ASSERT(!mRunnable); MOZ_ASSERT(!mRunnable);
mRunnable = new FileSizeAndDateRunnable(this, domfiles); mRunnable = new FileSizeAndDateRunnable(this, files);
if (!mRunnable->Dispatch()) { if (!mRunnable->Dispatch()) {
unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel); unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
} }

View File

@ -12,6 +12,7 @@
#include "nsIFilePicker.h" #include "nsIFilePicker.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/PFilePickerParent.h" #include "mozilla/dom/PFilePickerParent.h"
namespace mozilla { namespace mozilla {
@ -29,7 +30,7 @@ class FilePickerParent : public PFilePickerParent
virtual ~FilePickerParent(); virtual ~FilePickerParent();
void Done(int16_t aResult); 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, virtual bool RecvOpen(const int16_t& aSelectedType,
const bool& aAddToRecentDocs, const bool& aAddToRecentDocs,
@ -64,11 +65,11 @@ class FilePickerParent : public PFilePickerParent
class FileSizeAndDateRunnable : public nsRunnable class FileSizeAndDateRunnable : public nsRunnable
{ {
FilePickerParent* mFilePickerParent; FilePickerParent* mFilePickerParent;
nsCOMArray<nsIDOMFile> mDomfiles; nsTArray<nsRefPtr<FileImpl>> mFiles;
nsCOMPtr<nsIEventTarget> mEventTarget; nsCOMPtr<nsIEventTarget> mEventTarget;
public: public:
FileSizeAndDateRunnable(FilePickerParent *aFPParent, nsCOMArray<nsIDOMFile>& aDomfiles); FileSizeAndDateRunnable(FilePickerParent *aFPParent, nsTArray<nsRefPtr<FileImpl>>& aFiles);
bool Dispatch(); bool Dispatch();
NS_IMETHOD Run(); NS_IMETHOD Run();
void Destroy(); void Destroy();

View File

@ -55,7 +55,7 @@ using mozilla::CSSToScreenScale from "Units.h";
using mozilla::CommandInt from "mozilla/EventForwards.h"; using mozilla::CommandInt from "mozilla/EventForwards.h";
using mozilla::Modifiers from "mozilla/EventForwards.h"; using mozilla::Modifiers from "mozilla/EventForwards.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.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"; using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
namespace mozilla { namespace mozilla {

View File

@ -2026,7 +2026,7 @@ TabChild::RecvUpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
mOrientation = orientation; mOrientation = orientation;
ScreenIntSize oldScreenSize = mInnerSize; ScreenIntSize oldScreenSize = mInnerSize;
mInnerSize = size; mInnerSize = size;
mWidget->Resize(0, 0, size.width, size.height, mWidget->Resize(rect.x + chromeDisp.x, rect.y + chromeDisp.y, size.width, size.height,
true); true);
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation()); nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());

View File

@ -80,6 +80,7 @@
#include "nsICancelable.h" #include "nsICancelable.h"
#include "gfxPrefs.h" #include "gfxPrefs.h"
#include "nsILoginManagerPrompter.h" #include "nsILoginManagerPrompter.h"
#include "nsPIWindowRoot.h"
#include <algorithm> #include <algorithm>
using namespace mozilla::dom; using namespace mozilla::dom;
@ -324,10 +325,36 @@ TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
void void
TabParent::SetOwnerElement(Element* aElement) 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; 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(); 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 void
TabParent::GetAppType(nsAString& aOut) TabParent::GetAppType(nsAString& aOut)
{ {
@ -879,8 +906,7 @@ TabParent::RecvSetDimensions(const uint32_t& aFlags,
} }
void void
TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size, TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
const nsIntPoint& aChromeDisp)
{ {
if (mIsDestroyed) { if (mIsDestroyed) {
return; return;
@ -891,12 +917,20 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
if (!mUpdatedDimensions || mOrientation != orientation || if (!mUpdatedDimensions || mOrientation != orientation ||
mDimensions != size || !mRect.IsEqualEdges(rect)) { 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; mUpdatedDimensions = true;
mRect = rect; mRect = contentRect;
mDimensions = size; mDimensions = size;
mOrientation = orientation; 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; 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, class FakeChannel final : public nsIChannel,
public nsIAuthPromptCallback, public nsIAuthPromptCallback,
public nsIInterfaceRequestor, public nsIInterfaceRequestor,

View File

@ -7,21 +7,22 @@
#ifndef mozilla_tabs_TabParent_h #ifndef mozilla_tabs_TabParent_h
#define 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/PBrowserParent.h"
#include "mozilla/dom/PFilePickerParent.h" #include "mozilla/dom/PFilePickerParent.h"
#include "mozilla/dom/TabContext.h" #include "mozilla/dom/TabContext.h"
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/EventForwards.h"
#include "mozilla/WritingModes.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIAuthPromptProvider.h" #include "nsIAuthPromptProvider.h"
#include "nsIBrowserDOMWindow.h" #include "nsIBrowserDOMWindow.h"
#include "nsIDOMEventListener.h"
#include "nsISecureBrowserUI.h" #include "nsISecureBrowserUI.h"
#include "nsITabParent.h" #include "nsITabParent.h"
#include "nsIXULBrowserWindow.h" #include "nsIXULBrowserWindow.h"
#include "nsWeakReference.h" #include "nsWeakReference.h"
#include "Units.h" #include "Units.h"
#include "WritingModes.h"
#include "js/TypeDecls.h"
class nsFrameLoader; class nsFrameLoader;
class nsIFrameLoader; class nsIFrameLoader;
@ -59,6 +60,7 @@ class Element;
struct StructuredCloneData; struct StructuredCloneData;
class TabParent final : public PBrowserParent class TabParent final : public PBrowserParent
, public nsIDOMEventListener
, public nsITabParent , public nsITabParent
, public nsIAuthPromptProvider , public nsIAuthPromptProvider
, public nsISecureBrowserUI , public nsISecureBrowserUI
@ -72,6 +74,8 @@ class TabParent final : public PBrowserParent
public: public:
// nsITabParent // nsITabParent
NS_DECL_NSITABPARENT NS_DECL_NSITABPARENT
// nsIDOMEventListener interfaces
NS_DECL_NSIDOMEVENTLISTENER
TabParent(nsIContentParent* aManager, TabParent(nsIContentParent* aManager,
const TabId& aTabId, const TabId& aTabId,
@ -106,6 +110,8 @@ public:
void Destroy(); void Destroy();
void RemoveWindowListeners();
virtual bool RecvMoveFocus(const bool& aForward) override; virtual bool RecvMoveFocus(const bool& aForward) override;
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) override; virtual bool RecvEvent(const RemoteDOMEvent& aEvent) override;
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override; virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override;
@ -224,8 +230,7 @@ public:
// message-sending functions under a layer of indirection and // message-sending functions under a layer of indirection and
// eating the return values // eating the return values
void Show(const ScreenIntSize& size, bool aParentIsActive); void Show(const ScreenIntSize& size, bool aParentIsActive);
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size, void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size);
const nsIntPoint& chromeDisp);
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics); void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
void UIResolutionChanged(); void UIResolutionChanged();
void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,

View File

@ -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. 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. # 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. 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.

View File

@ -1006,6 +1006,8 @@ MediaCodecReader::DecodeVideoFrameSync(int64_t aTimeThreshold)
} }
if (v) { if (v) {
// Notify mDecoder that we have decoded a video frame.
mDecoder->NotifyDecodedFrames(0, 1, 0);
VideoQueue().Push(v); VideoQueue().Push(v);
} else { } else {
NS_WARNING("Unable to create VideoData"); NS_WARNING("Unable to create VideoData");
@ -1817,6 +1819,10 @@ MediaCodecReader::GetCodecOutputData(Track& aTrack,
} }
if (status == OK) { 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) { if (!IsValidTimestampUs(aThreshold) || info.mTimeUs >= aThreshold) {
// Get a valid output buffer. // Get a valid output buffer.
break; break;

View File

@ -101,7 +101,13 @@ MediaOmxCommonDecoder::PauseStateMachine()
if (!mDecoderStateMachine) { if (!mDecoderStateMachine) {
return; return;
} }
mDecoderStateMachine->SetDormant(true); // enter dormant state
RefPtr<nsRunnable> event =
NS_NewRunnableMethodWithArg<bool>(
mDecoderStateMachine,
&MediaDecoderStateMachine::SetDormant,
true);
mDecoderStateMachine->TaskQueue()->Dispatch(event);
} }
void void
@ -124,7 +130,13 @@ MediaOmxCommonDecoder::ResumeStateMachine()
mNextState = mPlayState; mNextState = mPlayState;
ChangeState(PLAY_STATE_LOADING); 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 void

View File

@ -22,7 +22,7 @@
# do ok(true, "Type not supported") and stop the test. # do ok(true, "Type not supported") and stop the test.
[DEFAULT] [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 = support-files =
320x240.ogv 320x240.ogv
320x240.ogv^headers^ 320x240.ogv^headers^

View File

@ -2,7 +2,7 @@
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881 # strictContentSandbox - bug 1042735, Android 2.3 - bug 981881
# won't run on b2g desktop tests - bug 1119993 # won't run on b2g desktop tests - bug 1119993
# broken HTTPS on b2g emulator - bug 1135339 # 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 = support-files =
/.well-known/idp-proxy/idp.js /.well-known/idp-proxy/idp.js

View File

@ -1,6 +1,6 @@
[DEFAULT] [DEFAULT]
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881 # 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 = support-files =
head.js head.js
dataChannel.js dataChannel.js

View File

@ -189,7 +189,7 @@ void Reverb::process(const AudioChunk* sourceBus, AudioChunk* destinationBus, si
// simply copy L -> R // simply copy L -> R
float* destinationChannelR = static_cast<float*>(const_cast<void*>(destinationBus->mChannelData[1])); 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); MOZ_ASSERT(isCopySafe);
if (!isCopySafe) if (!isCopySafe)
return; return;

View File

@ -120,9 +120,9 @@ skip-if = toolkit == 'android' # bug 1145816
[test_mediaStreamAudioSourceNodePassThrough.html] [test_mediaStreamAudioSourceNodePassThrough.html]
[test_mediaStreamAudioSourceNodeResampling.html] [test_mediaStreamAudioSourceNodeResampling.html]
[test_mixingRules.html] [test_mixingRules.html]
skip-if = android_version == '10' # bug 1091965 skip-if = android_version == '10' || android_version == '18' # bug 1091965
[test_mozaudiochannel.html] [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_nodeToParamConnection.html]
[test_OfflineAudioContext.html] [test_OfflineAudioContext.html]
[test_offlineDestinationChannelCountLess.html] [test_offlineDestinationChannelCountLess.html]

View File

@ -334,7 +334,8 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsPluginStreamListenerPeer* streamPe
if (streamType == nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN) { if (streamType == nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN) {
SuspendRequest(); SuspendRequest();
} else if (!SetStreamType(streamType, false)) { }
if (!SetStreamType(streamType, false)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -364,6 +365,12 @@ nsNPAPIPluginStreamListener::SetStreamType(uint16_t aType, bool aNeedsResume)
// instance is destroyed. // instance is destroyed.
NS_ADDREF_THIS(); NS_ADDREF_THIS();
break; 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: default:
return false; return false;
} }

View File

@ -790,7 +790,6 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
tabContentBounds.ScaleInverseRoundOut(scaleFactor); tabContentBounds.ScaleInverseRoundOut(scaleFactor);
int32_t windowH = tabContentBounds.height + int(chromeSize.y); int32_t windowH = tabContentBounds.height + int(chromeSize.y);
// This is actually relative to window-chrome.
nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft()); nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft());
// Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space. // Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space.
@ -800,8 +799,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
nsPoint screenPoint; nsPoint screenPoint;
switch (sourceSpace) { switch (sourceSpace) {
case NPCoordinateSpacePlugin: case NPCoordinateSpacePlugin:
screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() + screenPoint = sourcePoint + pluginPosition +
chromeSize + pluginPosition + windowPosition; pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
break; break;
case NPCoordinateSpaceWindow: case NPCoordinateSpaceWindow:
screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) + screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) +
@ -824,8 +823,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
nsPoint destPoint; nsPoint destPoint;
switch (destSpace) { switch (destSpace) {
case NPCoordinateSpacePlugin: case NPCoordinateSpacePlugin:
destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() - destPoint = screenPoint - pluginPosition -
chromeSize - pluginPosition - windowPosition; pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
break; break;
case NPCoordinateSpaceWindow: case NPCoordinateSpaceWindow:
destPoint = screenPoint - windowPosition; destPoint = screenPoint - windowPosition;
@ -1308,7 +1307,7 @@ GetOffsetRootContent(nsIFrame* aFrame)
int32_t newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0; int32_t newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0;
if (!f || newAPD != currAPD) { if (!f || newAPD != currAPD) {
// Convert docOffset to the right APD and add it to offset. // 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; docOffset.x = docOffset.y = 0;
} }
currAPD = newAPD; currAPD = newAPD;
@ -1316,7 +1315,7 @@ GetOffsetRootContent(nsIFrame* aFrame)
} }
} }
offset += docOffset.ConvertAppUnits(currAPD, apd); offset += docOffset.ScaleToOtherAppUnits(currAPD, apd);
return offset; return offset;
} }

View File

@ -1185,6 +1185,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
void void
nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType) nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType)
{ {
MOZ_ASSERT(aStreamType != STREAM_TYPE_UNKNOWN);
MOZ_ASSERT(mRequest); MOZ_ASSERT(mRequest);
mStreamType = aStreamType; mStreamType = aStreamType;
if (!mUseLocalCache && mStreamType >= NP_ASFILE) { 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 nsresult
nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile) nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile)
{ {

View File

@ -131,7 +131,9 @@ public:
// Called by nsNPAPIPluginStreamListener // Called by nsNPAPIPluginStreamListener
void OnStreamTypeSet(const int32_t aStreamType); void OnStreamTypeSet(const int32_t aStreamType);
static const int32_t STREAM_TYPE_UNKNOWN; enum {
STREAM_TYPE_UNKNOWN = UINT16_MAX
};
private: private:
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL); nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);

View File

@ -1395,7 +1395,7 @@ PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
MOZ_ASSERT(mSurrogate); MOZ_ASSERT(mSurrogate);
mSurrogate->AsyncCallDeparting(); mSurrogate->AsyncCallDeparting();
if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) { if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) {
*stype = UINT16_MAX; *stype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
} else { } else {
err = NPERR_GENERIC_ERROR; err = NPERR_GENERIC_ERROR;
} }

View File

@ -537,6 +537,13 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
OnInitFailure(); OnInitFailure();
return; return;
} }
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter) {
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
mIsStartingAsync ?
NS_LITERAL_CSTRING("1") :
NS_LITERAL_CSTRING("0"));
}
#ifdef XP_WIN #ifdef XP_WIN
{ // Scope for lock { // Scope for lock
mozilla::MutexAutoLock lock(mCrashReporterMutex); mozilla::MutexAutoLock lock(mCrashReporterMutex);
@ -607,6 +614,12 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome)
{ {
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
mIsStartingAsync = Preferences::GetBool(kAsyncInitPref, false); 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 #endif
} }

View File

@ -408,12 +408,16 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
// path-level matching, unless the channel got redirected, see: // path-level matching, unless the channel got redirected, see:
// http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects // http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
if (!aWasRedirected && !mPath.IsEmpty()) { if (!aWasRedirected && !mPath.IsEmpty()) {
// cloning uri so we can ignore the ref // converting aUri into nsIURL so we can strip query and ref
nsCOMPtr<nsIURI> uri; // example.com/test#foo -> example.com/test
aUri->CloneIgnoringRef(getter_AddRefs(uri)); // 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; nsAutoCString uriPath;
rv = uri->GetPath(uriPath); rv = url->GetFilePath(uriPath);
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);
// check if the last character of mPath is '/'; if so // check if the last character of mPath is '/'; if so
// we just have to check loading resource is within // we just have to check loading resource is within

View File

@ -61,6 +61,7 @@ skip-if = true
[test_pointer-events-1b.xhtml] [test_pointer-events-1b.xhtml]
[test_pointer-events-2.xhtml] [test_pointer-events-2.xhtml]
[test_pointer-events-3.xhtml] [test_pointer-events-3.xhtml]
skip-if = android_version == '18' # bug 1147994
[test_pointer-events-4.xhtml] [test_pointer-events-4.xhtml]
[test_pointer-events-5.xhtml] [test_pointer-events-5.xhtml]
[test_pointer-events-6.xhtml] [test_pointer-events-6.xhtml]

View File

@ -7,9 +7,15 @@
interface WorkerDebuggerGlobalScope : EventTarget { interface WorkerDebuggerGlobalScope : EventTarget {
readonly attribute object global; readonly attribute object global;
void enterEventLoop();
void leaveEventLoop();
void postMessage(DOMString message); void postMessage(DOMString message);
attribute EventHandler onmessage; attribute EventHandler onmessage;
void reportError(DOMString message);
}; };
// So you can debug while you debug // So you can debug while you debug

View File

@ -14,6 +14,7 @@
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsIScriptContext.h" #include "nsIScriptContext.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsISupportsPriority.h" #include "nsISupportsPriority.h"
#include "nsITimer.h" #include "nsITimer.h"
@ -26,6 +27,7 @@
#include "jsfriendapi.h" #include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/CycleCollectedJSRuntime.h" #include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h" #include "mozilla/dom/asmjscache/AsmJSCache.h"
#include "mozilla/dom/AtomList.h" #include "mozilla/dom/AtomList.h"
@ -1414,6 +1416,12 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
nsCString sharedWorkerScriptSpec; nsCString sharedWorkerScriptSpec;
const bool isServiceWorker = aWorkerPrivate->IsServiceWorker();
if (isServiceWorker) {
AssertIsOnMainThread();
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_SPAWN_ATTEMPTS, 1);
}
bool isSharedOrServiceWorker = aWorkerPrivate->IsSharedWorker() || bool isSharedOrServiceWorker = aWorkerPrivate->IsSharedWorker() ||
aWorkerPrivate->IsServiceWorker(); aWorkerPrivate->IsServiceWorker();
if (isSharedOrServiceWorker) { if (isSharedOrServiceWorker) {
@ -1461,6 +1469,19 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
if (queued) { if (queued) {
domainInfo->mQueuedWorkers.AppendElement(aWorkerPrivate); 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) { else if (parent) {
domainInfo->mChildWorkerCount++; domainInfo->mChildWorkerCount++;
@ -1529,6 +1550,10 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
return false; return false;
} }
if (isServiceWorker) {
AssertIsOnMainThread();
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_WAS_SPAWNED, 1);
}
return true; return true;
} }

View File

@ -885,6 +885,10 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow); nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
nsCOMPtr<nsPIDOMWindow> outerWindow = window->GetOuterWindow();
bool serviceWorkersTestingEnabled =
outerWindow->GetServiceWorkersTestingEnabled();
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
if (!doc) { if (!doc) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -893,8 +897,8 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
nsCOMPtr<nsIURI> documentURI = doc->GetBaseURI(); nsCOMPtr<nsIURI> documentURI = doc->GetBaseURI();
bool authenticatedOrigin = false; 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; authenticatedOrigin = true;
} }

View File

@ -1505,20 +1505,23 @@ public:
nsIScriptGlobalObject* sgo; nsIScriptGlobalObject* sgo;
if (aWorkerPrivate) { if (aWorkerPrivate) {
nsIDOMEventTarget* target = nullptr;
WorkerGlobalScope* globalScope = nullptr; WorkerGlobalScope* globalScope = nullptr;
UNWRAP_WORKER_OBJECT(WorkerGlobalScope, global, globalScope); UNWRAP_WORKER_OBJECT(WorkerGlobalScope, global, globalScope);
if (globalScope) {
MOZ_ASSERT(global == globalScope->GetWrapperPreserveColor()); if (!globalScope) {
target = static_cast<nsIDOMEventTarget*>(globalScope);
} else {
WorkerDebuggerGlobalScope* globalScope = nullptr; WorkerDebuggerGlobalScope* globalScope = nullptr;
UNWRAP_OBJECT(WorkerDebuggerGlobalScope, global, globalScope); UNWRAP_OBJECT(WorkerDebuggerGlobalScope, global, globalScope);
MOZ_ASSERT(globalScope); MOZ_ASSERT(globalScope);
MOZ_ASSERT(global == globalScope->GetWrapperPreserveColor()); 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 = nsRefPtr<ErrorEvent> event =
ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init); ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
event->SetTrusted(true); event->SetTrusted(true);
@ -4214,6 +4217,41 @@ WorkerPrivateParent<Derived>::AssertInnerWindowIsCorrect() const
#endif #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) WorkerDebugger::WorkerDebugger(WorkerPrivate* aWorkerPrivate)
: mMutex("WorkerDebugger::mMutex"), : mMutex("WorkerDebugger::mMutex"),
mCondVar(mMutex, "WorkerDebugger::mCondVar"), 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::WorkerPrivate(JSContext* aCx,
WorkerPrivate* aParent, WorkerPrivate* aParent,
const nsAString& aScriptURL, const nsAString& aScriptURL,
@ -4510,6 +4583,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
aSharedWorkerName, aLoadInfo) aSharedWorkerName, aLoadInfo)
, mJSContext(nullptr) , mJSContext(nullptr)
, mPRThread(nullptr) , mPRThread(nullptr)
, mDebuggerEventLoopLevel(0)
, mErrorHandlerRecursionCount(0) , mErrorHandlerRecursionCount(0)
, mNextTimeoutId(1) , mNextTimeoutId(1)
, mStatus(Pending) , mStatus(Pending)
@ -6113,12 +6187,90 @@ WorkerPrivate::PostMessageToParentMessagePort(
aMessagePortSerial, aRv); 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 void
WorkerPrivate::PostMessageToDebugger(const nsAString& aMessage) WorkerPrivate::PostMessageToDebugger(const nsAString& aMessage)
{ {
mDebugger->PostMessageToDebugger(aMessage); mDebugger->PostMessageToDebugger(aMessage);
} }
void
WorkerPrivate::ReportErrorToDebugger(const nsAString& aFilename,
uint32_t aLineno,
const nsAString& aMessage)
{
mDebugger->ReportErrorToDebugger(aFilename, aLineno, aMessage);
}
bool bool
WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus) WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
{ {

View File

@ -56,6 +56,8 @@ class PrincipalInfo;
struct PRThread; struct PRThread;
class ReportDebuggerErrorRunnable;
BEGIN_WORKERS_NAMESPACE BEGIN_WORKERS_NAMESPACE
class AutoSyncLoopHolder; class AutoSyncLoopHolder;
@ -721,6 +723,8 @@ public:
}; };
class WorkerDebugger : public nsIWorkerDebugger { class WorkerDebugger : public nsIWorkerDebugger {
friend class ::ReportDebuggerErrorRunnable;
mozilla::Mutex mMutex; mozilla::Mutex mMutex;
mozilla::CondVar mCondVar; mozilla::CondVar mCondVar;
@ -753,6 +757,10 @@ public:
void void
PostMessageToDebugger(const nsAString& aMessage); PostMessageToDebugger(const nsAString& aMessage);
void
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
const nsAString& aMessage);
private: private:
virtual virtual
~WorkerDebugger(); ~WorkerDebugger();
@ -762,6 +770,11 @@ private:
void void
PostMessageToDebuggerOnMainThread(const nsAString& aMessage); PostMessageToDebuggerOnMainThread(const nsAString& aMessage);
void
ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
uint32_t aLineno,
const nsAString& aMessage);
}; };
class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate> class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
@ -802,6 +815,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
nsTArray<ParentType*> mChildWorkers; nsTArray<ParentType*> mChildWorkers;
nsTArray<WorkerFeature*> mFeatures; nsTArray<WorkerFeature*> mFeatures;
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts; nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
uint32_t mDebuggerEventLoopLevel;
struct SyncLoopInfo struct SyncLoopInfo
{ {
@ -962,9 +976,19 @@ public:
const Optional<Sequence<JS::Value>>& aTransferable, const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv); ErrorResult& aRv);
void
EnterDebuggerEventLoop();
void
LeaveDebuggerEventLoop();
void void
PostMessageToDebugger(const nsAString& aMessage); PostMessageToDebugger(const nsAString& aMessage);
void
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
const nsAString& aMessage);
bool bool
NotifyInternal(JSContext* aCx, Status aStatus); NotifyInternal(JSContext* aCx, Status aStatus);

View File

@ -513,12 +513,35 @@ WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
aGlobal.set(mWorkerPrivate->GetOrCreateGlobalScope(aCx)->GetWrapper()); aGlobal.set(mWorkerPrivate->GetOrCreateGlobalScope(aCx)->GetWrapper());
} }
void
WorkerDebuggerGlobalScope::EnterEventLoop()
{
mWorkerPrivate->EnterDebuggerEventLoop();
}
void
WorkerDebuggerGlobalScope::LeaveEventLoop()
{
mWorkerPrivate->LeaveDebuggerEventLoop();
}
void void
WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage) WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage)
{ {
mWorkerPrivate->PostMessageToDebugger(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 void
WorkerDebuggerGlobalScope::Dump(JSContext* aCx, WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
const Optional<nsAString>& aString) const const Optional<nsAString>& aString) const

View File

@ -264,11 +264,20 @@ public:
void void
GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal); GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal);
void
EnterEventLoop();
void
LeaveEventLoop();
void void
PostMessage(const nsAString& aMessage); PostMessage(const nsAString& aMessage);
IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(message)
void
ReportError(JSContext* aCx, const nsAString& aMessage);
void void
Dump(JSContext* aCx, const Optional<nsAString>& aString) const; Dump(JSContext* aCx, const Optional<nsAString>& aString) const;

View File

@ -2,11 +2,14 @@
interface nsIDOMWindow; interface nsIDOMWindow;
[scriptable, uuid(ead45621-22a7-48ef-b7db-c4252ae3e6cb)] [scriptable, uuid(55d54034-1573-4889-b1d9-93ba12fc33c7)]
interface nsIWorkerDebuggerListener : nsISupports interface nsIWorkerDebuggerListener : nsISupports
{ {
void onClose(); void onClose();
void onError(in DOMString filename, in unsigned long lineno,
in DOMString message);
void onMessage(in DOMString message); void onMessage(in DOMString message);
}; };

View File

@ -1,6 +1,6 @@
"use strict" "use strict"
onmessage = function (event) { this.onmessage = function (event) {
switch (event.data) { switch (event.data) {
case "ping": case "ping":
postMessage("pong"); postMessage("pong");

View File

@ -0,0 +1,14 @@
"use strict";
function f() {
debugger;
}
self.onmessage = function (event) {
switch (event.data) {
case "ping":
debugger;
postMessage("pong");
break;
};
};

View File

@ -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;
};
};

View File

@ -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;
};
};

View File

@ -0,0 +1,5 @@
"use strict";
self.onerror = function () {
postMessage("error");
}

View File

@ -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;
}
};

Some files were not shown because too many files have changed in this diff Show More