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

This commit is contained in:
Ryan VanderMeulen 2015-07-02 15:59:46 -04:00
commit e5d7b6b96e
176 changed files with 2331 additions and 1379 deletions

View File

@ -25,6 +25,7 @@
#include "nsCoord.h"
#include "nsObjCExceptions.h"
#include "nsWhitespaceTokenizer.h"
#include <prdtoa.h>
using namespace mozilla;
using namespace mozilla::a11y;
@ -38,11 +39,11 @@ using namespace mozilla::a11y;
#define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
#define NSAccessibilityMathUnderAttribute @"AXMathUnder"
#define NSAccessibilityMathOverAttribute @"AXMathOver"
#define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
// XXX WebKit also defines the following attributes.
// See bugs 1176970, 1176973 and 1176983.
// See bugs 1176970 and 1176983.
// - NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
// - NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
// - NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
// - NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
// - NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
@ -172,8 +173,7 @@ ConvertToNSArray(nsTArray<Accessible*>& aArray)
case roles::MATHML_FRACTION:
[additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
[additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
// XXX bug 1176973
// WebKit also defines NSAccessibilityMathLineThicknessAttribute
[additional addObject:NSAccessibilityMathLineThicknessAttribute];
break;
case roles::MATHML_SUB:
case roles::MATHML_SUP:
@ -422,8 +422,24 @@ ConvertToNSArray(nsTArray<Accessible*>& aArray)
return [self childAt:0];
if ([attribute isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
return [self childAt:1];
// XXX bug 1176973
// WebKit also defines NSAccessibilityMathLineThicknessAttribute
if ([attribute isEqualToString:NSAccessibilityMathLineThicknessAttribute]) {
// WebKit sets line thickness to some logical value parsed in the
// renderer object of the <mfrac> element. It's not clear whether the
// exact value is relevant to assistive technologies. From a semantic
// point of view, the only important point is to distinguish between
// <mfrac> elements that have a fraction bar and those that do not.
// Per the MathML 3 spec, the latter happens iff the linethickness
// attribute is of the form [zero-float][optional-unit]. In that case we
// set line thickness to zero and in the other cases we set it to one.
nsCOMPtr<nsIPersistentProperties> attributes = accWrap->Attributes();
nsAutoString thickness;
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::linethickness_, thickness);
double value = 1.0;
if (!thickness.IsEmpty())
value = PR_strtod(NS_LossyConvertUTF16toASCII(thickness).get(),
nullptr);
return [NSNumber numberWithInteger:(value ? 1 : 0)];
}
break;
case roles::MATHML_SUB:
if ([attribute isEqualToString:NSAccessibilityMathBaseAttribute])

View File

@ -126,12 +126,14 @@ var FullScreen = {
} else {
let topWin = event.target.ownerDocument.defaultView.top;
browser = gBrowser.getBrowserForContentWindow(topWin);
if (!browser) {
document.mozCancelFullScreen();
break;
}
}
if (!this.enterDomFullscreen(browser)) {
if (!browser || !this.enterDomFullscreen(browser)) {
if (document.mozFullScreen) {
// MozDOMFullscreen:Entered is dispatched synchronously in
// fullscreen change, hence we have to avoid calling this
// method synchronously here.
setTimeout(() => document.mozCancelFullScreen(), 0);
}
break;
}
// If it is a remote browser, send a message to ask the content
@ -176,7 +178,6 @@ var FullScreen = {
// active. If not, we exit fullscreen since the "full-screen document" isn't
// actually visible now.
if (gBrowser.selectedBrowser != aBrowser) {
document.mozCancelFullScreen();
return false;
}
@ -184,7 +185,6 @@ var FullScreen = {
if (focusManager.activeWindow != window) {
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
document.mozCancelFullScreen();
return false;
}

View File

@ -12,6 +12,7 @@ const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const TargetFactory = devtools.TargetFactory;
const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
const {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// All tests are asynchronous
waitForExplicitFinish();
@ -40,9 +41,9 @@ Services.prefs.setBoolPref(NEW_UI_PREF, false);
// Uncomment this pref to dump all devtools protocol traffic
// Services.prefs.setBoolPref("devtools.debugger.log", true);
// Set the testing flag on gDevTools and reset it when the test ends
gDevTools.testing = true;
registerCleanupFunction(() => gDevTools.testing = false);
// Set the testing flag on DevToolsUtils and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clean-up all prefs that might have been changed during a test run
// (safer here because if the test fails, then the pref is never reverted)
@ -162,9 +163,10 @@ let waitForAnimationInspectorReady = Task.async(function*(inspector) {
let win = inspector.sidebar.getWindowForTab("animationinspector");
let updated = inspector.once("inspector-updated");
// In e10s, if we wait for underlying toolbox actors to load (by setting
// gDevTools.testing to true), we miss the "animationinspector-ready" event on
// the sidebar, so check to see if the iframe is already loaded.
// In e10s, if we wait for underlying toolbox actors to
// load (by setting DevToolsUtils.testing to true), we miss the
// "animationinspector-ready" event on the sidebar, so check to see if the
// iframe is already loaded.
let tabReady = win.document.readyState === "complete" ?
promise.resolve() :
inspector.sidebar.once("animationinspector-ready");

View File

@ -11,6 +11,7 @@ const {devtools} =
const {require} = devtools;
const {AppProjects} = require("devtools/app-manager/app-projects");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const APP_MANAGER_URL = "about:app-manager";
const TEST_BASE =
@ -19,9 +20,9 @@ const HOSTED_APP_MANIFEST = TEST_BASE + "hosted_app.manifest";
const PACKAGED_APP_DIR_PATH = getTestFilePath(".");
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
function addTab(url, targetWindow = window) {

View File

@ -10,7 +10,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/devtools/Console.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
const devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
const { require } = devtools;
@ -18,11 +17,12 @@ const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/toolkit/event-emitter");
const { CallWatcherFront } = require("devtools/server/actors/call-watcher");
const { CanvasFront } = require("devtools/server/actors/canvas");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const Telemetry = require("devtools/shared/telemetry");
const telemetry = new Telemetry();
const CANVAS_ACTOR_RECORDING_ATTEMPT = gDevTools.testing ? 500 : 5000;
const CANVAS_ACTOR_RECORDING_ATTEMPT = DevToolsUtils.testing ? 500 : 5000;
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
@ -36,9 +36,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsUtils",
"resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "NetworkHelper", function() {
return require("devtools/toolkit/webconsole/network-helper");
});

View File

@ -21,6 +21,7 @@ let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.j
let { CallWatcherFront } = devtools.require("devtools/server/actors/call-watcher");
let { CanvasFront } = devtools.require("devtools/server/actors/canvas");
let { setTimeout } = devtools.require("sdk/timers");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let TiltGL = devtools.require("devtools/tilt/tilt-gl");
let TargetFactory = devtools.TargetFactory;
let Toolbox = devtools.Toolbox;
@ -44,10 +45,11 @@ waitForExplicitFinish();
let gToolEnabled = Services.prefs.getBoolPref("devtools.canvasdebugger.enabled");
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
info("finish() was called, cleaning up...");
DevToolsUtils.testing = false;
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
Services.prefs.setBoolPref("devtools.canvasdebugger.enabled", gToolEnabled);

View File

@ -5,17 +5,19 @@
const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/commandline/test/";
const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/commandline/test/";
var require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
var console = require("resource://gre/modules/devtools/Console.jsm").console;
let { require } =
Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let console = require("resource://gre/modules/devtools/Console.jsm").console;
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
Services.scriptloader.loadSubScript(testDir + "/mockCommands.js", this);
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
function whenDelayedStartupFinished(aWindow, aCallback) {

View File

@ -31,9 +31,9 @@ let Toolbox = devtools.Toolbox;
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
const FRAME_SCRIPT_URL = getRootDirectory(gTestPath) + "code_frame-script.js";
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
// All tests are asynchronous.

View File

@ -12,15 +12,16 @@ const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {})
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
const BASE_URI = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/"
// All test are asynchronous
waitForExplicitFinish();
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
registerCleanupFunction(function*() {

View File

@ -50,8 +50,6 @@ this.DevTools = function DevTools() {
this.destroy = this.destroy.bind(this);
this._teardown = this._teardown.bind(this);
this._testing = false;
EventEmitter.decorate(this);
Services.obs.addObserver(this._teardown, "devtools-unloaded", false);
@ -59,36 +57,6 @@ this.DevTools = function DevTools() {
};
DevTools.prototype = {
/**
* When the testing flag is set we take appropriate action to prevent race
* conditions in our testing environment. This means setting
* dom.send_after_paint_to_content to false to prevent infinite MozAfterPaint
* loops and not autohiding the highlighter.
*/
get testing() {
return this._testing;
},
set testing(state) {
let oldState = this._testing;
this._testing = state;
if (state !== oldState) {
if (state) {
this._savedSendAfterPaintToContentPref =
Services.prefs.getBoolPref("dom.send_after_paint_to_content");
// dom.send_after_paint_to_content is set to true (non-default) in
// testing/profiles/prefs_general.js so lets set it to the same as it is
// in a default browser profile for the duration of the test.
Services.prefs.setBoolPref("dom.send_after_paint_to_content", false);
} else {
Services.prefs.setBoolPref("dom.send_after_paint_to_content",
this._savedSendAfterPaintToContentPref);
}
}
},
/**
* Register a new developer tool.
*

View File

@ -9,8 +9,8 @@ add_task(function*() {
// TODO: This test tries to verify the normal behavior of the netmonitor and
// therefore needs to avoid the explicit check for tests. Bug 1167188 will
// allow us to remove this workaround.
let isTesting = gDevTools.testing;
gDevTools.testing = false;
let isTesting = DevToolsUtils.testing;
DevToolsUtils.testing = false;
let tab = yield addTab(URL_ROOT + "doc_viewsource.html");
let target = TargetFactory.forTab(tab);
@ -26,5 +26,5 @@ add_task(function*() {
yield gDevTools.closeToolbox(target);
tab = target = toolbox = panel = null;
gBrowser.removeCurrentTab();
gDevTools.testing = isTesting;
DevToolsUtils.testing = isTesting;
});

View File

@ -8,6 +8,7 @@ const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {ScratchpadManager} = Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", {});
const {TargetFactory} = devtools;
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
const TEST_DIR = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
const CHROME_URL_ROOT = TEST_DIR + "/";
@ -29,9 +30,9 @@ function getFrameScript() {
return mm;
}
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
Services.prefs.clearUserPref("devtools.dump.emit");
Services.prefs.clearUserPref("devtools.toolbox.host");
Services.prefs.clearUserPref("devtools.toolbox.previousHost");

View File

@ -7,7 +7,7 @@
const {Cc, Ci, Cu} = require("chrome");
const {Promise: promise} = require("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
/**
* Client-side highlighter shared module.
@ -244,15 +244,15 @@ exports.getHighlighterUtils = function(toolbox) {
/**
* Hide the highlighter.
* @param {Boolean} forceHide Only really matters in test mode (when
* gDevTools.testing is true). In test mode, hovering over several nodes in
* the markup view doesn't hide/show the highlighter to ease testing. The
* DevToolsUtils.testing is true). In test mode, hovering over several nodes
* in the markup view doesn't hide/show the highlighter to ease testing. The
* highlighter stays visible at all times, except when the mouse leaves the
* markup view, which is when this param is passed to true
* @return a promise that resolves when the highlighter is hidden
*/
let unhighlight = exported.unhighlight = Task.async(
function*(forceHide=false) {
forceHide = forceHide || !gDevTools.testing;
forceHide = forceHide || !DevToolsUtils.testing;
// Note that if isRemoteHighlightable is true, there's no need to hide the
// highlighter as the walker uses setTimeout to hide it after some time

View File

@ -418,7 +418,7 @@ Toolbox.prototype = {
// destruction event, resulting in the shared profiler connection being
// opened and closed outside of the test that originally opened the
// toolbox.
if (gDevTools.testing) {
if (DevToolsUtils.testing) {
yield profilerReady;
}
@ -1729,7 +1729,7 @@ Toolbox.prototype = {
this.walker.on("highlighter-ready", this._highlighterReady);
this.walker.on("highlighter-hide", this._highlighterHidden);
let autohide = !gDevTools.testing;
let autohide = !DevToolsUtils.testing;
this._highlighter = yield this._inspector.getHighlighter(autohide);
}
}.bind(this));
@ -1914,7 +1914,7 @@ Toolbox.prototype = {
// Force GC to prevent long GC pauses when running tests and to free up
// memory in general when the toolbox is closed.
if (gDevTools.testing) {
if (DevToolsUtils.testing) {
win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.garbageCollect();

View File

@ -26,14 +26,15 @@ waitForExplicitFinish();
let {TargetFactory, require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
registerCleanupFunction(() => {

View File

@ -10,6 +10,7 @@ let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let {console} = Components.utils.import("resource://gre/modules/devtools/Console.jsm", {});
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// All test are asynchronous
waitForExplicitFinish();
@ -21,9 +22,9 @@ const TEST_URL_ROOT = "http://example.com/browser/browser/devtools/layoutview/te
// Services.prefs.setBoolPref("devtools.debugger.log", true);
// Set the testing flag on gDevTools and reset it when the test ends
gDevTools.testing = true;
registerCleanupFunction(() => gDevTools.testing = false);
// Set the testing flag on DevToolsUtils and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clean-up all prefs that might have been changed during a test run
// (safer here because if the test fails, then the pref is never reverted)

View File

@ -11,7 +11,7 @@ let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared
let clipboard = devtools.require("sdk/clipboard");
let {setTimeout, clearTimeout} = devtools.require("sdk/timers");
let {promiseInvoke} = devtools.require("devtools/async-utils");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// All test are asynchronous
waitForExplicitFinish();
@ -23,9 +23,9 @@ SimpleTest.requestCompleteLog();
// Uncomment this pref to dump all devtools emitted events to the console.
// Services.prefs.setBoolPref("devtools.dump.emit", true);
// Set the testing flag on gDevTools and reset it when the test ends
gDevTools.testing = true;
registerCleanupFunction(() => gDevTools.testing = false);
// Set the testing flag on DevToolsUtils and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clear preferences that may be set during the course of tests.
registerCleanupFunction(() => {

View File

@ -123,6 +123,7 @@ const EventEmitter = require("devtools/toolkit/event-emitter");
const Editor = require("devtools/sourceeditor/editor");
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
const {ToolSidebar} = require("devtools/framework/sidebar");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
XPCOMUtils.defineLazyModuleGetter(this, "Chart",
"resource:///modules/devtools/Chart.jsm");
@ -139,9 +140,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsUtils",
"resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
@ -800,7 +798,7 @@ const WDA_DEFAULT_VERIFY_INTERVAL = 50; // ms
// and two seconds is quite short on slow debug builds. The timeout here should
// be at least equal to the general mochitest timeout of 45 seconds so that this
// never gets hit during testing.
const WDA_DEFAULT_GIVE_UP_TIMEOUT = gDevTools.testing ? 45000 : 2000; // ms
const WDA_DEFAULT_GIVE_UP_TIMEOUT = DevToolsUtils.testing ? 45000 : 2000; // ms
/**
* Helper method for debugging.

View File

@ -7,9 +7,6 @@
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsUtils",
"resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "HarExporter", function() {
return devtools.require("devtools/netmonitor/har/har-exporter.js").HarExporter;
});

View File

@ -11,6 +11,7 @@ let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let { CurlUtils } = Cu.import("resource:///modules/devtools/Curl.jsm", {});
let NetworkHelper = devtools.require("devtools/toolkit/webconsole/network-helper");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let TargetFactory = devtools.TargetFactory;
let Toolbox = devtools.Toolbox;
@ -54,9 +55,9 @@ const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAA
const FRAME_SCRIPT_UTILS_URL = "chrome://browser/content/devtools/frame-script-utils.js"
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
// All tests are asynchronous.

View File

@ -441,7 +441,7 @@ PerformanceFront.prototype = {
* Used only in tests.
*/
_request: function (actorName, method, ...args) {
if (!gDevTools.testing) {
if (!DevToolsUtils.testing) {
throw new Error("PerformanceFront._request may only be used in tests.");
}
let actor = this[`_${actorName}`];

View File

@ -532,7 +532,7 @@ let PerformanceController = {
// have realtime rendering tests in non-e10s. This function is
// overridden wholesale in tests when we want to test multiprocess support
// specifically.
if (gDevTools.testing) {
if (DevToolsUtils.testing) {
return { supported: true, enabled: true };
}
let supported = system.constants.E10S_TESTING_ONLY;

View File

@ -45,7 +45,7 @@ const EXPERIMENTAL_PREF = "devtools.performance.ui.experimental";
// All tests are asynchronous.
waitForExplicitFinish();
gDevTools.testing = true;
DevToolsUtils.testing = true;
let DEFAULT_PREFS = [
"devtools.debugger.log",
@ -84,7 +84,7 @@ function loadFrameScripts () {
}
registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
info("finish() was called, cleaning up...");
// Rollback any pref changes

View File

@ -10,6 +10,7 @@ const promise = devtools.require("sdk/core/promise");
const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const ProjectEditor = devtools.require("projecteditor/projecteditor");
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
const TEST_URL_ROOT = "http://mochi.test:8888/browser/browser/devtools/projecteditor/test/";
const SAMPLE_WEBAPP_URL = TEST_URL_ROOT + "/helper_homepage.html";
@ -22,9 +23,9 @@ waitForExplicitFinish();
// Uncomment this pref to dump all devtools emitted events to the console.
// Services.prefs.setBoolPref("devtools.dump.emit", true);
// Set the testing flag on gDevTools and reset it when the test ends
gDevTools.testing = true;
registerCleanupFunction(() => gDevTools.testing = false);
// Set the testing flag on DevToolsUtils and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clear preferences that may be set during the course of tests.
registerCleanupFunction(() => {
@ -332,4 +333,3 @@ function onPopupHidden(menu) {
});
return defer.promise;
}

View File

@ -7,14 +7,15 @@ const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {})
let {devtools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let TargetFactory = devtools.TargetFactory;
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
/**

View File

@ -14,9 +14,9 @@ const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let gScratchpadWindow; // Reference to the Scratchpad chrome window object
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
/**

View File

@ -18,6 +18,7 @@ let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.j
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
let { WebGLFront } = devtools.require("devtools/server/actors/webgl");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let TiltGL = devtools.require("devtools/tilt/tilt-gl");
let TargetFactory = devtools.TargetFactory;
let Toolbox = devtools.Toolbox;
@ -36,10 +37,11 @@ waitForExplicitFinish();
let gToolEnabled = Services.prefs.getBoolPref("devtools.shadereditor.enabled");
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
info("finish() was called, cleaning up...");
DevToolsUtils.testing = false;
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
Services.prefs.setBoolPref("devtools.shadereditor.enabled", gToolEnabled);

View File

@ -9,10 +9,11 @@ let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
const {Hosts} = require("devtools/framework/toolbox-hosts");
const {defer} = require("sdk/core/promise");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
const TEST_URI_ROOT = "http://example.com/browser/browser/devtools/shared/test/";

View File

@ -8,10 +8,11 @@ const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {})
const { require } = devtools;
const Editor = require("devtools/sourceeditor/editor");
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
/**

View File

@ -21,18 +21,19 @@ const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH;
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
waitForExplicitFinish();
let gToolbox, gPanelWindow, gWindow, gUI;
Services.prefs.setBoolPref(STORAGE_PREF, true);
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
gToolbox = gPanelWindow = gWindow = gUI = null;
Services.prefs.clearUserPref(STORAGE_PREF);
Services.prefs.clearUserPref(SPLIT_CONSOLE_PREF);
gDevTools.testing = false;
DevToolsUtils.testing = false;
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}

View File

@ -9,9 +9,6 @@
const TEST_URL = TEST_BASE_HTTP + "doc_uncached.html";
add_task(function*() {
let isTesting = gDevTools.testing;
gDevTools.testing = true;
info("Opening netmonitor");
let tab = yield addTab("about:blank");
let target = TargetFactory.forTab(tab);
@ -29,7 +26,6 @@ add_task(function*() {
yield styleeditor.UI.editors[0].getSourceEditor();
info("Checking Netmonitor contents.");
let requestsForCss = 0;
let attachments = [];
for (let item of netmonitor._view.RequestsMenu) {
if (item.attachment.url.endsWith("doc_uncached.css")) {
@ -41,5 +37,4 @@ add_task(function*() {
"Got two requests for doc_uncached.css after Style Editor was loaded.");
ok(attachments[1].fromCache,
"Second request was loaded from browser cache");
gDevTools.testing = isTesting;
});

View File

@ -11,16 +11,15 @@ let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
/**

View File

@ -11,6 +11,7 @@ let TargetFactory = devtools.TargetFactory;
let {CssHtmlTree} = devtools.require("devtools/styleinspector/computed-view");
let {CssRuleView, _ElementStyle} = devtools.require("devtools/styleinspector/rule-view");
let {CssLogic, CssSelector} = devtools.require("devtools/styleinspector/css-logic");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let {editableField, getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
let {console} = Components.utils.import("resource://gre/modules/devtools/Console.jsm", {});
@ -37,8 +38,8 @@ registerCleanupFunction(function*() {
// Services.prefs.setBoolPref("devtools.dump.emit", true);
// Set the testing flag on gDevTools and reset it when the test ends
gDevTools.testing = true;
registerCleanupFunction(() => gDevTools.testing = false);
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clean-up all prefs that might have been changed during a test run
// (safer here because if the test fails, then the pref is never reverted)

View File

@ -8,6 +8,7 @@ let TiltGL = devtools.require("devtools/tilt/tilt-gl");
let {EPSILON, TiltMath, vec3, mat3, mat4, quat4} = devtools.require("devtools/tilt/tilt-math");
let TiltUtils = devtools.require("devtools/tilt/tilt-utils");
let {TiltVisualizer} = devtools.require("devtools/tilt/tilt-visualizer");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let tempScope = {};
Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope);
@ -55,9 +56,9 @@ const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED;
const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
gDevTools.testing = true;
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
});
function isTiltEnabled() {

View File

@ -23,6 +23,7 @@ const STRINGS_URI = "chrome://browser/locale/devtools/webaudioeditor.properties"
const L10N = new ViewHelpers.L10N(STRINGS_URI);
const Telemetry = require("devtools/shared/telemetry");
const telemetry = new Telemetry();
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
devtools.lazyRequireGetter(this, "LineGraphWidget",
"devtools/shared/widgets/LineGraphWidget");

View File

@ -19,6 +19,7 @@ let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.j
let { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
let { WebAudioFront } = devtools.require("devtools/server/actors/webaudio");
let DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let TargetFactory = devtools.TargetFactory;
let audioNodes = devtools.require("devtools/server/actors/utils/audionodes.json");
let mm = null;
@ -41,10 +42,10 @@ waitForExplicitFinish();
let gToolEnabled = Services.prefs.getBoolPref("devtools.webaudioeditor.enabled");
gDevTools.testing = true;
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
info("finish() was called, cleaning up...");
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", gToolEnabled);

View File

@ -222,7 +222,7 @@ let ContextView = {
// Fire an event upon completed rendering, with extra information
// if in testing mode only.
let info = {};
if (gDevTools.testing) {
if (DevToolsUtils.testing) {
info = gAudioNodes.getInfo();
}
window.emit(EVENTS.UI_GRAPH_RENDERED, info.nodes, info.edges, info.paramEdges);

View File

@ -13,6 +13,7 @@ let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let {require, TargetFactory} = devtools;
let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils");
let {Messages} = require("devtools/webconsole/console-output");
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const asyncStorage = require("devtools/toolkit/shared/async-storage");
// Services.prefs.setBoolPref("devtools.debugger.log", true);
@ -41,7 +42,7 @@ const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/" +
"webconsole.properties";
let WCUL10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
gDevTools.testing = true;
DevToolsUtils.testing = true;
function asyncTest(generator) {
return () => {
@ -333,7 +334,7 @@ let finishTest = Task.async(function* () {
});
registerCleanupFunction(function*() {
gDevTools.testing = false;
DevToolsUtils.testing = false;
// Remove stored console commands in between tests
yield asyncStorage.removeItem("webConsoleHistory");

View File

@ -14,7 +14,8 @@ const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {require} = devtools;
const promise = require("promise");
const {AppProjects} = require("devtools/app-manager/app-projects");
gDevTools.testing = true;
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
DevToolsUtils.testing = true;
let TEST_BASE;
if (window.location === "chrome://browser/content/browser.xul") {
@ -37,7 +38,7 @@ Services.prefs.setCharPref("devtools.devices.url", TEST_BASE + "browser_devices.
let registerCleanupFunction = registerCleanupFunction ||
SimpleTest.registerCleanupFunction;
registerCleanupFunction(() => {
gDevTools.testing = false;
DevToolsUtils.testing = false;
Services.prefs.clearUserPref("devtools.webide.enabled");
Services.prefs.clearUserPref("devtools.webide.enableLocalRuntime");
Services.prefs.clearUserPref("devtools.webide.autoinstallADBHelper");

View File

@ -149,6 +149,7 @@ browser.jar:
skin/classic/browser/controlcenter/conn-not-secure.svg (../shared/controlcenter/conn-not-secure.svg)
skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg)
skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg)
skin/classic/browser/controlcenter/mcb-disabled.svg (../shared/controlcenter/mcb-disabled.svg)
skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg)
skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg)

View File

@ -193,6 +193,7 @@ browser.jar:
skin/classic/browser/controlcenter/conn-not-secure.svg (../shared/controlcenter/conn-not-secure.svg)
skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg)
skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg)
skin/classic/browser/controlcenter/mcb-disabled.svg (../shared/controlcenter/mcb-disabled.svg)
skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg)
skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg)

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="24" height="24" viewBox="0 0 24 24">
<defs>
<rect id="shape-lock-clasp-outer" x="5" y="1" width="14" height="20" rx="7" ry="7" />
<rect id="shape-lock-clasp-inner" x="8" y="4" width="8" height="14" rx="4" ry="4" />
<rect id="shape-lock-base" x="3" y="10" width="18" height="13" rx="1.5" ry="1.5" />
<mask id="mask-clasp-cutout">
<rect width="24" height="24" fill="#000" />
<use xlink:href="#shape-lock-clasp-outer" fill="#fff" />
<use xlink:href="#shape-lock-clasp-inner" fill="#000" />
<line x1="3" y1="21" x2="21.5" y2="0.5" stroke="#000" stroke-width="3" />
<line x1="3" y1="25" x2="21.5" y2="4.5" stroke="#000" stroke-width="3" />
<rect x="3" y="10" width="18" height="13" rx="1.5" ry="1.5" />
</mask>
<mask id="mask-base-cutout">
<rect width="24" height="24" fill="#000" />
<use xlink:href="#shape-lock-base" fill="#fff" />
<line x1="2.25" y1="24.75" x2="21.5" y2="4.5" stroke="#000" stroke-width="3" />
</mask>
</defs>
<use xlink:href="#shape-lock-clasp-outer" mask="url(#mask-clasp-cutout)" fill="#999" />
<use xlink:href="#shape-lock-base" mask="url(#mask-base-cutout)" fill="#999" />
<line x1="2.25" y1="22.75" x2="21.5" y2="2.5" stroke="#d92d21" stroke-width="3" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -208,6 +208,11 @@
background-image: url(chrome://browser/skin/controlcenter/conn-secure-ev.svg);
}
#identity-popup-securityView.mixedActiveContent,
#identity-popup-security-content.mixedActiveContent {
background-image: url(chrome://browser/skin/controlcenter/mcb-disabled.svg);
}
#identity-popup-securityView-header {
border-bottom: 1px solid #e5e5e5;
padding-bottom: 1em;

View File

@ -196,6 +196,7 @@ browser.jar:
skin/classic/browser/controlcenter/conn-not-secure.svg (../shared/controlcenter/conn-not-secure.svg)
skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg)
skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg)
skin/classic/browser/controlcenter/mcb-disabled.svg (../shared/controlcenter/mcb-disabled.svg)
skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg)
skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg)

View File

@ -18,6 +18,7 @@
#include "nsPIDOMWindow.h"
class nsIConsoleAPIStorage;
class nsIPrincipal;
class nsIProfiler;
class nsIXPConnectJSObjectHolder;

View File

@ -5,8 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceEntry.h"
#include "nsIURI.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceEntryBinding.h"
#include "nsIURI.h"
using namespace mozilla::dom;

View File

@ -8,6 +8,8 @@
#define mozilla_dom_PerformanceEntry_h___
#include "nsDOMNavigationTiming.h"
#include "nsString.h"
#include "nsWrapperCache.h"
class nsISupports;

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceMark.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceMarkBinding.h"
using namespace mozilla::dom;

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceMeasure.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceMeasureBinding.h"
using namespace mozilla::dom;

View File

@ -16,6 +16,7 @@
#include "nsGlobalWindow.h"
#include "nsIPresShell.h"
#include "nsIPrincipal.h"
#include "nsPresContext.h"
namespace mozilla {
namespace dom {

View File

@ -11,9 +11,11 @@
#include "nsCOMPtr.h"
#include "nsRefPtr.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
class nsGlobalWindow;
class nsIPrincipal;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {

View File

@ -8,6 +8,7 @@
#include "nsContentCID.h"
#include "nsDOMClassInfoID.h"
#include "mozilla/HoldDropJSObjects.h"
using namespace mozilla;
using namespace mozilla::dom;

View File

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SameProcessMessageQueue.h"
#include "nsThreadUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

View File

@ -33,6 +33,7 @@
#include "xpcpublic.h"
#include "nsObserverService.h"
#include "nsFocusManager.h"
#include "nsIInterfaceRequestorUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

View File

@ -16,11 +16,13 @@
#include "nsContentPolicy.h"
#include "nsIURI.h"
#include "nsIDocShell.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMWindow.h"
#include "nsIContent.h"
#include "nsILoadContext.h"
#include "nsCOMArray.h"
#include "nsContentUtils.h"
using mozilla::LogLevel;

View File

@ -17,6 +17,8 @@
#include "mozilla/dom/Animation.h"
#include "mozilla/dom/KeyframeEffect.h"
using mozilla::dom::Animation;
nsAutoTArray<nsRefPtr<nsDOMMutationObserver>, 4>*
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
@ -345,12 +347,12 @@ void
nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
AnimationMutation aMutationType)
{
KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
mozilla::dom::KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
if (!effect) {
return;
}
Element* animationTarget = effect->GetTarget();
mozilla::dom::Element* animationTarget = effect->GetTarget();
if (!animationTarget) {
return;
}

View File

@ -3536,6 +3536,7 @@ nsDOMWindowUtils::RequestCompositorProperty(const nsAString& property,
NS_IMETHODIMP
nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
const nsAString& aProperty,
const nsAString& aPseudoElement,
nsAString& aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
@ -3547,6 +3548,15 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
nsRefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
nsIFrame* frame = element->GetPrimaryFrame();
if (frame && !aPseudoElement.IsEmpty()) {
if (aPseudoElement.EqualsLiteral("::before")) {
frame = nsLayoutUtils::GetBeforeFrame(frame);
} else if (aPseudoElement.EqualsLiteral("::after")) {
frame = nsLayoutUtils::GetAfterFrame(frame);
} else {
return NS_ERROR_INVALID_ARG;
}
}
if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
if (aProperty.EqualsLiteral("opacity")) {
Layer* layer =

View File

@ -3904,6 +3904,9 @@ nsDocument::DeleteShell()
if (IsEventHandlingEnabled()) {
RevokeAnimationFrameNotifications();
}
if (nsPresContext* presContext = mPresShell->GetPresContext()) {
presContext->RefreshDriver()->CancelPendingEvents(this);
}
// When our shell goes away, request that all our images be immediately
// discarded, so we don't carry around decoded image data for a document we
@ -9213,15 +9216,32 @@ NotifyPageHide(nsIDocument* aDocument, void* aData)
return true;
}
static void
DispatchCustomEventWithFlush(nsINode* aTarget, const nsAString& aEventType,
bool aBubbles, bool aOnlyChromeDispatch)
{
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMEvent(getter_AddRefs(event), aTarget, nullptr, nullptr);
nsresult rv = event->InitEvent(aEventType, aBubbles, false);
if (NS_FAILED(rv)) {
return;
}
event->SetTrusted(true);
if (aOnlyChromeDispatch) {
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
}
if (nsIPresShell* shell = aTarget->OwnerDoc()->GetShell()) {
shell->GetPresContext()->
RefreshDriver()->ScheduleEventDispatch(aTarget, event);
}
}
static void
DispatchFullScreenChange(nsIDocument* aTarget)
{
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(aTarget,
NS_LITERAL_STRING("mozfullscreenchange"),
true,
false);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
aTarget, NS_LITERAL_STRING("mozfullscreenchange"),
/* Bubbles */ true, /* OnlyChrome */ false);
}
void
@ -11167,11 +11187,10 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
// Dispatch MozDOMFullscreen:Exited to the last document in
// the list since we want this event to follow the same path
// MozDOMFullscreen:Entered dispatched.
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(changed.LastElement(),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
true, true);
asyncDispatcher->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
changed.LastElement(), ToSupports(changed.LastElement()),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
// Move the top-level window out of fullscreen mode.
FullscreenRoots::Remove(root);
SetWindowFullScreen(root, false);
@ -11250,9 +11269,10 @@ nsDocument::RestorePreviousFullScreenState()
// If we are fully exiting fullscreen, don't touch anything here,
// just wait for the window to get out from fullscreen first.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
(new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* Cancelable */ false,
/* DefaultAction */ nullptr);
} else {
SetWindowFullScreen(this, false);
}
@ -11295,11 +11315,9 @@ nsDocument::RestorePreviousFullScreenState()
if (!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, doc) ||
(!nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen") &&
!static_cast<nsDocument*>(doc)->mIsApprovedForFullscreen)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
}
}
break;
@ -11691,9 +11709,9 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// If we are not the top level process, dispatch an event to make
// our parent process go fullscreen first.
(new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:Request"),
/* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Request"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
} else {
// Make the window fullscreen.
FullscreenRequest* lastRequest = sPendingFullscreenRequests.getLast();
@ -11820,13 +11838,6 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
}
}
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
// order so that the events for the root document arrives before the leaf
// document, as required by the spec.
for (uint32_t i = 0; i < changed.Length(); ++i) {
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
}
// If this document hasn't already been approved in this session,
// check to see if the user has granted the fullscreen access
// to the document's principal's host, if it has one. Note that documents
@ -11839,17 +11850,17 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
}
FullscreenRoots::Add(this);
// If it is the first entry of the fullscreen, trigger an event so
// that the UI can response to this change, e.g. hide chrome, or
// notifying parent process to enter fullscreen. Note that chrome
// code may also want to listen to MozDOMFullscreen:NewOrigin event
// to pop up warning/approval UI.
if (!previousFullscreenDoc) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
elem, NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(elem), NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
}
// The origin which is fullscreen gets changed. Trigger an event so
@ -11861,14 +11872,17 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
// shouldn't rely on this event itself.
if (aRequest.mShouldNotifyNewOrigin &&
!nsContentUtils::HaveEqualPrincipals(previousFullscreenDoc, this)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
this, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
}
FullscreenRoots::Add(this);
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
// order so that the events for the root document arrives before the leaf
// document, as required by the spec.
for (uint32_t i = 0; i < changed.Length(); ++i) {
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
}
}
NS_IMETHODIMP

View File

@ -206,7 +206,7 @@ class BlobURLsReporter final : public nsIMemoryReporter
{
EnumArg* envp = static_cast<EnumArg*>(aUserArg);
nsCOMPtr<nsIDOMBlob> tmp = do_QueryInterface(aInfo->mObject);
nsRefPtr<Blob> blob = static_cast<Blob*>(tmp.get());
nsRefPtr<mozilla::dom::Blob> blob = static_cast<mozilla::dom::Blob*>(tmp.get());
if (blob) {
NS_NAMED_LITERAL_CSTRING

View File

@ -106,7 +106,7 @@ nsHostObjectURI::Serialize(mozilla::ipc::URIParams& aParams)
hostParams.principal() = info;
} else {
hostParams.principal() = void_t();
hostParams.principal() = mozilla::void_t();
}
aParams = hostParams;

View File

@ -6,6 +6,8 @@
#include "nsIGlobalObject.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsHostObjectProtocolHandler.h"
nsIGlobalObject::~nsIGlobalObject()
{

View File

@ -17,6 +17,7 @@
#include "nsIIOService.h"
#include "nsIExternalProtocolHandler.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
NS_IMPL_ISUPPORTS(nsNoDataProtocolContentPolicy, nsIContentPolicy)

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script src='test.js'></script>
<script type='application/javascript;version=1.7'>
function runTests() {
return Promise.resolve()
.then(() => { return navigator.serviceWorker.ready })
.then((registration) => {
return new Promise((resolve) => {
var worker = registration.waiting || registration.active;
worker.postMessage('read');
navigator.serviceWorker.onmessage = (message) => {
if (message.data.type == 'done') {
ok(!message.data.cached, 'No cached data');
resolve();
}
};
});
})
.then(done);
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script src='test.js'></script>
<script type='application/javascript;version=1.7'>
function runTests() {
return Promise.resolve()
.then(() => { return navigator.serviceWorker.ready })
.then((registration) => {
return new Promise((resolve) => {
var worker = registration.waiting || registration.active;
worker.postMessage('write');
navigator.serviceWorker.onmessage = (message) => {
if (message.data.type == 'written') {
worker.postMessage('read');
} else if (message.data.type == 'done') {
ok(message.data.cached, 'Write success');
resolve();
}
};
});
})
.then(done);
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

41
dom/cache/test/mochitest/app/index.html vendored Normal file
View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script type='application/javascript;version=1.7'>
function ok(aCondition, aMessage) {
if (aCondition) {
alert('OK: ' + aMessage);
} else {
alert('KO: ' + aMessage);
}
}
function ready() {
alert('READY');
}
function registerServiceWorker() {
return new Promise((resolve, reject) => {
navigator.serviceWorker.ready.then(() => {
ready();
resolve();
});
navigator.serviceWorker.register('sw.js', {scope: '.'})
.then(registration => {
ok(true, 'service worker registered');
})
.catch(reject);
});
}
function runTests() {
return Promise.resolve()
.then(registerServiceWorker)
.then(ready)
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

View File

@ -0,0 +1,5 @@
{
"name": "App",
"launch_path": "/index.html",
"description": "Test app for bug 1172562"
}

View File

@ -0,0 +1 @@
Content-Type: application/manifest+json

18
dom/cache/test/mochitest/app/sw.js vendored Normal file
View File

@ -0,0 +1,18 @@
self.addEventListener('message', (message) => {
caches.open('acache').then((cache) => {
if(message.data == 'write') {
cache.add('aurl').then(() => {
message.source.postMessage({
type: 'written'
});
});
} else if (message.data == 'read') {
cache.match('aurl').then((result) => {
message.source.postMessage({
type: 'done',
cached: !!result
});
});
}
});
});

15
dom/cache/test/mochitest/app/test.js vendored Normal file
View File

@ -0,0 +1,15 @@
function ok(aCondition, aMessage) {
if (aCondition) {
alert('OK: ' + aMessage);
} else {
alert('KO: ' + aMessage);
}
}
function ready() {
alert('READY');
}
function done() {
alert('DONE');
}

View File

@ -23,6 +23,7 @@ support-files =
test_cache_https.js
large_url_list.js
empty.html
app/*
[test_cache.html]
[test_cache_add.html]
@ -40,6 +41,8 @@ support-files =
skip-if = buildapp == 'b2g' # bug 1162353
[test_cache_restart.html]
[test_cache_shrink.html]
[test_cache_clear_on_app_uninstall.html]
skip-if = e10s || buildapp == 'b2g' # bug 1178685
[test_cache_orphaned_cache.html]
[test_cache_orphaned_body.html]
[test_cache_untrusted.html]

View File

@ -0,0 +1,163 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1172562 - Clear QuotaManager storage when uninstalling an app</title>
<script type='text/javascript' src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css' />
</head>
<body onload='runTests()'>
<p id='display'></p>
<div id='content' style='display: none'></div>
<pre id='test'></pre>
<script class='testbody' type='application/javascript;version=1.7'>
SimpleTest.waitForExplicitFinish();
const gOrigin = 'http://mochi.test:8888/tests/dom/cache/test/mochitest/app';
const appManifestURL = gOrigin + '/manifest.webapp';
let gApp;
function setup() {
return new Promise((resolve, reject) => {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.pushPrefEnv({'set': [
['dom.mozBrowserFramesEnabled', true],
['dom.serviceWorkers.exemptFromPerDomainMax', true],
['dom.serviceWorkers.enabled', true],
['dom.serviceWorkers.testing.enabled', true],
['dom.caches.enabled', true],
]}, () => {
SpecialPowers.pushPermissions([
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
{ 'type': 'browser', 'allow': 1, 'context': document },
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
], () => {
SpecialPowers.autoConfirmAppInstall(() => {
SpecialPowers.autoConfirmAppUninstall(resolve);
});
});
});
});
}
function installApp() {
return new Promise((resolve, reject) => {
let req = navigator.mozApps.install(appManifestURL);
req.onsuccess = function() {
gApp = req.result;
is(req.result.manifestURL, appManifestURL, 'app installed');
if (req.result.installState == 'installed') {
is(req.result.installState, 'installed', 'app downloaded');
resolve()
} else {
req.result.ondownloadapplied = function() {
is(req.result.installState, 'installed', 'app downloaded');
resolve();
}
}
}
req.onerror = reject;
});
}
function launchApp() {
if (!gApp) {
ok(false, 'No test application to launch');
return Promise.reject();
}
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('mozapp', gApp.manifestURL);
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/READY/.exec(message)) {
ok(true, "Message from app: " + message);
resolve();
} else {
ok(false, "Unexpected message received: " + message);
}
}, false);
let domParent = document.getElementById('container');
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
gOrigin + gApp.manifest.launch_path;
});
}
function loadControlled(aUrl) {
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('mozapp', gApp.manifestURL);
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
let domParent = document.getElementById('container');
domParent.removeChild(iframe);
resolve();
} else {
ok(false, "Unexpected message received: " + message);
}
}, false);
let domParent = document.getElementById('container');
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
gOrigin + aUrl;
});
}
function loadBeforeClear() {
return loadControlled('/before_clear.html');
}
function loadAfterClear() {
return loadControlled('/after_clear.html');
}
function uninstallApp() {
return new Promise((resolve, reject) => {
if (!gApp) {
return reject();
}
let req = navigator.mozApps.mgmt.uninstall(gApp);
req.onsuccess = resolve;
req.onerror = reject;
});
}
function runTests() {
setup()
.then(installApp)
.then(launchApp)
.then(loadBeforeClear)
.then(uninstallApp)
.then(installApp)
.then(launchApp)
.then(loadAfterClear)
.then(uninstallApp)
.then(SimpleTest.finish)
.catch((e) => {
ok(false, 'Unexpected error ' + e.target.error.name);
SimpleTest.finish();
});
}
</script>
<div id='container'></div>
</body>
</html>

View File

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(e7b44320-8255-4ad1-bbe9-d78a8a1867c9)]
[scriptable, uuid(336a8683-5626-4512-a3d5-ec280c13e5c2)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1746,7 +1746,8 @@ interface nsIDOMWindowUtils : nsISupports {
* If the property is NOT currently being animated on the compositor thread,
* returns an empty string.
*/
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty);
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty,
[optional] in AString aPseudoElement);
/**
* Special function that gets a property syncronously from the last composite

View File

@ -10,6 +10,7 @@
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIInputStreamPump.h"
#include "nsIIOService.h"
#include "nsIProtocolHandler.h"
@ -870,6 +871,16 @@ private:
return rv;
}
// If we are loading a script for a ServiceWorker then we must not
// try to intercept it. If the interception matches the current
// ServiceWorker's scope then we could deadlock the load.
if (mWorkerPrivate->IsServiceWorker()) {
nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(channel);
if (internal) {
internal->ForceNoIntercept();
}
}
if (loadInfo.mCacheStatus != ScriptLoadInfo::ToBeCached) {
rv = channel->AsyncOpen(loader, indexSupports);
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@ -51,6 +51,11 @@ ServiceWorker::ServiceWorker(nsPIDOMWindow* aWindow,
MOZ_ASSERT(aInfo);
MOZ_ASSERT(mSharedWorker);
if (aWindow) {
mDocument = aWindow->GetExtantDoc();
mWindow = aWindow->GetOuterWindow();
}
// This will update our state too.
mInfo->AppendWorker(this);
}
@ -68,7 +73,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorker)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorker, DOMEventTargetHelper,
mSharedWorker)
mSharedWorker, mDocument, mWindow)
JSObject*
ServiceWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
@ -97,9 +102,12 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(doc));
MOZ_ASSERT(mDocument && mWindow,
"Cannot call PostMessage on a ServiceWorker object that doesn't "
"have a window");
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(
new ServiceWorkerClientInfo(mDocument, mWindow));
workerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
clientInfo, aRv);

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState.
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
@ -91,6 +92,10 @@ private:
// can be released and recreated as required rather than re-implement some of
// the SharedWorker logic.
nsRefPtr<SharedWorker> mSharedWorker;
// We need to keep the document and window alive for PostMessage to be able
// to access them.
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsPIDOMWindow> mWindow;
};
} // namespace workers

View File

@ -28,7 +28,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc,
nsPIDOMWindow* aWindow)
: mWindowId(0)
{
MOZ_ASSERT(aDoc);
@ -53,7 +54,7 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
NS_WARNING("Failed to get focus information.");
}
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aWindow);
MOZ_ASSERT(outerWindow);
if (!outerWindow->IsTopLevelWindow()) {
mFrameType = FrameType::Nested;

View File

@ -14,6 +14,9 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ClientBinding.h"
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
namespace workers {
@ -29,7 +32,7 @@ class ServiceWorkerClientInfo final
friend class ServiceWorkerWindowClient;
public:
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
ServiceWorkerClientInfo(nsIDocument* aDoc, nsPIDOMWindow* aWindow);
private:
nsString mClientId;

View File

@ -3551,7 +3551,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
if (!isNavigation) {
MOZ_ASSERT(aDoc);
aRv = GetDocumentController(aDoc->GetInnerWindow(), getter_AddRefs(serviceWorker));
clientInfo = new ServiceWorkerClientInfo(aDoc);
clientInfo = new ServiceWorkerClientInfo(aDoc, aDoc->GetWindow());
} else {
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@ -3924,7 +3924,7 @@ EnumControlledDocuments(nsISupports* aKey,
return PL_DHASH_NEXT;
}
ServiceWorkerClientInfo clientInfo(document);
ServiceWorkerClientInfo clientInfo(document, document->GetWindow());
data->mDocuments.AppendElement(clientInfo);
return PL_DHASH_NEXT;

View File

@ -87,7 +87,8 @@ public:
ErrorResult result;
//FIXME(catalinb): Bug 1144660 - check if we are allowed to focus here.
window->Focus(result);
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument()));
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument(),
window->GetOuterWindow()));
}
DispatchResult(Move(clientInfo));

View File

@ -11,6 +11,7 @@
#include "nsCOMPtr.h"
#include "nscore.h"
class nsILoadInfo;
class nsIPrincipal;
namespace IPC {

View File

@ -286,12 +286,7 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
if (aProperty == eCSSProperty_transform && aFrame->Preserves3D()) {
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
}
nsIContent* content = aFrame->GetContent();
if (content) {
return nsLayoutUtils::HasCurrentAnimationsForProperties(content, &aProperty, 1);
}
return false;
return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1);
}
/* static */ bool

View File

@ -4773,11 +4773,10 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
if (canDraw2D) {
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
if (aContainerFrame->GetContent() &&
aContainerItem &&
if (aContainerItem &&
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
nsLayoutUtils::HasAnimationsForCompositor(
aContainerFrame->GetContent(), eCSSProperty_transform)) {
aContainerFrame, eCSSProperty_transform)) {
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
@ -4795,7 +4794,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
// compute scale using the animation on the container (ignoring
// its ancestors)
scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
aContainerFrame->GetContent(), aVisibleRect.Size(),
aContainerFrame, aVisibleRect.Size(),
displaySize);
// multiply by the scale inherited from ancestors
scale.width *= aIncomingScale.mXScale;

View File

@ -515,14 +515,11 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
RestyleManager::GetMaxAnimationGenerationForFrame(aFrame);
aLayer->SetAnimationGeneration(animationGeneration);
nsIContent* content = aFrame->GetContent();
if (!content) {
return;
}
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* transitions =
nsTransitionManager::GetAnimationsForCompositor(content, aProperty);
presContext->TransitionManager()->GetAnimationsForCompositor(aFrame, aProperty);
AnimationCollection* animations =
nsAnimationManager::GetAnimationsForCompositor(content, aProperty);
presContext->AnimationManager()->GetAnimationsForCompositor(aFrame, aProperty);
if (!animations && !transitions) {
return;
@ -723,8 +720,7 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
nsRect overflowRect = aFrame->GetVisualOverflowRect();
if (aFrame->IsTransformed() &&
nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
eCSSProperty_transform)) {
nsLayoutUtils::HasAnimationsForCompositor(aFrame, eCSSProperty_transform)) {
/**
* Add a fuzz factor to the overflow rectangle so that elements only just
* out of view are pulled into the display list, so they can be
@ -3856,11 +3852,8 @@ nsDisplayOpacity::NeedsActiveLayer(nsDisplayListBuilder* aBuilder)
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_opacity) &&
!IsItemTooSmallForActiveLayer(this))
return true;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_opacity)) {
return true;
}
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame, eCSSProperty_opacity)) {
return true;
}
return false;
}
@ -5087,9 +5080,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
// might have only just had its transform animated in which case
// the ActiveLayerManager may not have been notified yet.
if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
(!aFrame->GetContent() ||
!nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
eCSSProperty_transform))) {
!nsLayoutUtils::HasAnimationsForCompositor(aFrame, eCSSProperty_transform)) {
if (aLogAnimations) {
nsCString message;
message.AppendLiteral("Performance warning: Async animation disabled because frame was not marked active for transform animation");
@ -5245,11 +5236,8 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_transform) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_transform)) {
return LAYER_ACTIVE;
}
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame, eCSSProperty_transform)) {
return LAYER_ACTIVE;
}
const nsStyleDisplay* disp = mFrame->StyleDisplay();

View File

@ -372,81 +372,79 @@ TextAlignTrueEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
}
bool
nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
nsLayoutUtils::HasAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
return nsAnimationManager::GetAnimationsForCompositor(aContent, aProperty) ||
nsTransitionManager::GetAnimationsForCompositor(aContent, aProperty);
}
static AnimationCollection*
GetAnimationsOrTransitions(nsIContent* aContent,
nsIAtom* aAnimationProperty,
nsCSSProperty aProperty)
{
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(
aAnimationProperty));
if (collection) {
bool propertyMatches = collection->HasAnimationOfProperty(aProperty);
if (propertyMatches) {
return collection;
}
}
return nullptr;
nsPresContext* presContext = aFrame->PresContext();
return presContext->AnimationManager()->GetAnimationsForCompositor(aFrame, aProperty) ||
presContext->TransitionManager()->GetAnimationsForCompositor(aFrame, aProperty);
}
bool
nsLayoutUtils::HasAnimations(nsIContent* aContent,
nsLayoutUtils::HasAnimations(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return false;
return GetAnimationsOrTransitions(aContent, nsGkAtoms::animationsProperty,
aProperty) ||
GetAnimationsOrTransitions(aContent, nsGkAtoms::transitionsProperty,
aProperty);
}
bool
nsLayoutUtils::HasCurrentAnimations(nsIContent* aContent,
nsIAtom* aAnimationProperty)
{
if (!aContent->MayHaveAnimations())
return false;
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
static_cast<AnimationCollection*>(
aContent->GetProperty(aAnimationProperty));
return (collection && collection->HasCurrentAnimations());
presContext->AnimationManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasAnimationOfProperty(aProperty)) {
return true;
}
collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasAnimationOfProperty(aProperty)) {
return true;
}
return false;
}
bool
nsLayoutUtils::HasCurrentAnimationsForProperties(nsIContent* aContent,
nsLayoutUtils::HasCurrentAnimations(const nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->AnimationManager()->GetAnimationCollection(aFrame);
return collection &&
collection->HasCurrentAnimations();
}
bool
nsLayoutUtils::HasCurrentTransitions(const nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
return collection &&
collection->HasCurrentAnimations();
}
bool
nsLayoutUtils::HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
const nsCSSProperty* aProperties,
size_t aPropertyCount)
{
if (!aContent->MayHaveAnimations())
return false;
static nsIAtom* const sAnimProps[] = { nsGkAtoms::transitionsProperty,
nsGkAtoms::animationsProperty,
nullptr };
for (nsIAtom* const* animProp = sAnimProps; *animProp; animProp++) {
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(*animProp));
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->AnimationManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
return false;
}
static gfxSize
GetScaleForValue(const StyleAnimationValue& aValue, nsIFrame* aFrame)
GetScaleForValue(const StyleAnimationValue& aValue, const nsIFrame* aFrame)
{
if (!aFrame) {
NS_WARNING("No frame.");
@ -491,7 +489,7 @@ GetSuitableScale(float aMaxScale, float aMinScale,
}
static void
GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
GetMinAndMaxScaleForAnimationProperty(const nsIFrame* aFrame,
AnimationCollection* aAnimations,
gfxSize& aMaxScale,
gfxSize& aMinScale)
@ -507,14 +505,12 @@ GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
if (prop.mProperty == eCSSProperty_transform) {
for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) {
AnimationPropertySegment& segment = prop.mSegments[segIdx];
gfxSize from = GetScaleForValue(segment.mFromValue,
aContent->GetPrimaryFrame());
gfxSize from = GetScaleForValue(segment.mFromValue, aFrame);
aMaxScale.width = std::max<float>(aMaxScale.width, from.width);
aMaxScale.height = std::max<float>(aMaxScale.height, from.height);
aMinScale.width = std::min<float>(aMinScale.width, from.width);
aMinScale.height = std::min<float>(aMinScale.height, from.height);
gfxSize to = GetScaleForValue(segment.mToValue,
aContent->GetPrimaryFrame());
gfxSize to = GetScaleForValue(segment.mToValue, aFrame);
aMaxScale.width = std::max<float>(aMaxScale.width, to.width);
aMaxScale.height = std::max<float>(aMaxScale.height, to.height);
aMinScale.width = std::min<float>(aMinScale.width, to.width);
@ -526,7 +522,7 @@ GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
}
gfxSize
nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent,
nsLayoutUtils::ComputeSuitableScaleForAnimation(const nsIFrame* aFrame,
const nsSize& aVisibleSize,
const nsSize& aDisplaySize)
{
@ -534,20 +530,21 @@ nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent,
std::numeric_limits<gfxFloat>::min());
gfxSize minScale(std::numeric_limits<gfxFloat>::max(),
std::numeric_limits<gfxFloat>::max());
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* animations =
nsAnimationManager::GetAnimationsForCompositor(aContent,
eCSSProperty_transform);
presContext->AnimationManager()->GetAnimationsForCompositor(
aFrame, eCSSProperty_transform);
if (animations) {
GetMinAndMaxScaleForAnimationProperty(aContent, animations,
GetMinAndMaxScaleForAnimationProperty(aFrame, animations,
maxScale, minScale);
}
animations =
nsTransitionManager::GetAnimationsForCompositor(aContent,
eCSSProperty_transform);
presContext->TransitionManager()->GetAnimationsForCompositor(
aFrame, eCSSProperty_transform);
if (animations) {
GetMinAndMaxScaleForAnimationProperty(aContent, animations,
GetMinAndMaxScaleForAnimationProperty(aFrame, animations,
maxScale, minScale);
}

View File

@ -2135,32 +2135,48 @@ public:
bool clear);
/**
* Returns true if the content node has animations or transitions that can be
* Given a frame with possibly animated content, finds the content node
* that contains its animations as well as the frame's pseudo-element type
* relative to the resulting content node. Returns true if animated content
* was found, otherwise it returns false and the output parameters are
* undefined.
*/
static bool GetAnimationContent(const nsIFrame* aFrame,
nsIContent* &aContentResult,
nsCSSPseudoElements::Type &aPseudoTypeResult);
/**
* Returns true if the frame has animations or transitions that can be
* performed on the compositor.
*/
static bool HasAnimationsForCompositor(nsIContent* aContent,
static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty);
/**
* Returns true if the content node has animations or transitions for the
* Returns true if the frame has animations or transitions for the
* property.
*/
static bool HasAnimations(nsIContent* aContent, nsCSSProperty aProperty);
static bool HasAnimations(const nsIFrame* aFrame, nsCSSProperty aProperty);
/**
* Returns true if the content node has any current animations or transitions
* (depending on the value of |aAnimationProperty|).
* Returns true if the frame has any current animations.
* A current animation is any animation that has not yet finished playing
* including paused animations.
*/
static bool HasCurrentAnimations(nsIContent* aContent,
nsIAtom* aAnimationProperty);
static bool HasCurrentAnimations(const nsIFrame* aFrame);
/**
* Returns true if the content node has any current animations or transitions
* Returns true if the frame has any current transitions.
* A current transition is any transition that has not yet finished playing
* including paused transitions.
*/
static bool HasCurrentTransitions(const nsIFrame* aFrame);
/**
* Returns true if the frame has any current animations or transitions
* for any of the specified properties.
*/
static bool HasCurrentAnimationsForProperties(nsIContent* aContent,
static bool HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
const nsCSSProperty* aProperties,
size_t aPropertyCount);
@ -2175,7 +2191,7 @@ public:
static bool IsAnimationLoggingEnabled();
/**
* Find a suitable scale for an element (aContent) over the course of any
* Find a suitable scale for a element (aFrame's content) over the course of any
* animations and transitions of the CSS transform property on the
* element that run on the compositor thread.
* It will check the maximum and minimum scale during the animations and
@ -2185,7 +2201,7 @@ public:
* @param aVisibleSize is the size of the area we want to paint
* @param aDisplaySize is the size of the display area of the pres context
*/
static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent,
static gfxSize ComputeSuitableScaleForAnimation(const nsIFrame* aFrame,
const nsSize& aVisibleSize,
const nsSize& aDisplaySize);

View File

@ -27,6 +27,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/IntegerRange.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsRefreshDriver.h"
#include "nsITimer.h"
@ -1341,6 +1342,7 @@ nsRefreshDriver::ObserverCount() const
// style changes, etc.
sum += mStyleFlushObservers.Length();
sum += mLayoutFlushObservers.Length();
sum += mPendingEvents.Length();
sum += mFrameRequestCallbackDocs.Length();
sum += mThrottledFrameRequestCallbackDocs.Length();
sum += mViewManagerFlushIsPending;
@ -1476,6 +1478,17 @@ TakeFrameRequestCallbacksFrom(nsIDocument* aDocument,
aDocument->TakeFrameRequestCallbacks(aTarget.LastElement().mCallbacks);
}
void
nsRefreshDriver::DispatchPendingEvents()
{
// Swap out the current pending events
nsTArray<PendingEvent> pendingEvents(Move(mPendingEvents));
for (PendingEvent& event : pendingEvents) {
bool dummy;
event.mTarget->DispatchEvent(event.mEvent, &dummy);
}
}
void
nsRefreshDriver::RunFrameRequestCallbacks(int64_t aNowEpoch, TimeStamp aNowTime)
{
@ -1657,6 +1670,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
if (i == 0) {
// This is the Flush_Style case.
DispatchPendingEvents();
RunFrameRequestCallbacks(aNowEpoch, aNowTime);
if (mPresContext && mPresContext->GetPresShell()) {
@ -2131,4 +2145,22 @@ nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument)
// running; that will happen automatically when it fires.
}
void
nsRefreshDriver::ScheduleEventDispatch(nsINode* aTarget, nsIDOMEvent* aEvent)
{
mPendingEvents.AppendElement(PendingEvent{aTarget, aEvent});
// make sure that the timer is running
EnsureTimerStarted();
}
void
nsRefreshDriver::CancelPendingEvents(nsIDocument* aDocument)
{
for (auto i : Reversed(MakeRange(mPendingEvents.Length()))) {
if (mPendingEvents[i].mTarget->OwnerDoc() == aDocument) {
mPendingEvents.RemoveElementAt(i);
}
}
}
#undef LOG

View File

@ -29,6 +29,8 @@ class nsPresContext;
class nsIPresShell;
class nsIDocument;
class imgIRequest;
class nsIDOMEvent;
class nsINode;
namespace mozilla {
class RefreshDriverTimer;
@ -222,6 +224,17 @@ public:
*/
void RevokeFrameRequestCallbacks(nsIDocument* aDocument);
/**
* Queue a new event to dispatch in next tick before the style flush
*/
void ScheduleEventDispatch(nsINode* aTarget, nsIDOMEvent* aEvent);
/**
* Cancel all pending events scheduled by ScheduleEventDispatch which
* targets any node in aDocument.
*/
void CancelPendingEvents(nsIDocument* aDocument);
/**
* Tell the refresh driver that it is done driving refreshes and
* should stop its timer and forget about its pres context. This may
@ -308,6 +321,7 @@ private:
};
typedef nsClassHashtable<nsUint32HashKey, ImageStartData> ImageStartTable;
void DispatchPendingEvents();
void RunFrameRequestCallbacks(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
@ -403,6 +417,11 @@ private:
RequestTable mRequests;
ImageStartTable mStartTable;
struct PendingEvent {
nsCOMPtr<nsINode> mTarget;
nsCOMPtr<nsIDOMEvent> mEvent;
};
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
nsAutoTArray<nsIPresShell*, 16> mPresShellsToInvalidateIfHidden;
@ -410,6 +429,7 @@ private:
nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
nsTArray<nsIDocument*> mThrottledFrameRequestCallbackDocs;
nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
nsTArray<PendingEvent> mPendingEvents;
// Helper struct for processing image requests
struct ImageRequestParameters {

View File

@ -1082,7 +1082,7 @@ nsIFrame::IsTransformed() const
(StyleDisplay()->HasTransform(this) ||
IsSVGTransformed() ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
nsLayoutUtils::HasAnimationsForCompositor(this,
eCSSProperty_transform) &&
IsFrameOfType(eSupportsCSSTransforms) &&
mContent->GetPrimaryFrame() == this)));
@ -1096,7 +1096,7 @@ nsIFrame::HasOpacityInternal(float aThreshold) const
return StyleDisplay()->mOpacity < aThreshold ||
(displayStyle->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
nsLayoutUtils::HasAnimationsForCompositor(this,
eCSSProperty_opacity) &&
mContent->GetPrimaryFrame() == this);
}
@ -1946,7 +1946,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting() &&
!aBuilder->WillComputePluginGeometry() &&
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
!nsLayoutUtils::HasAnimations(mContent, eCSSProperty_opacity) &&
!nsLayoutUtils::HasAnimations(this, eCSSProperty_opacity) &&
!needEventRegions) {
return;
}

View File

@ -2591,7 +2591,7 @@ public:
*
* @return whether the frame correspods to generated content
*/
bool IsGeneratedContentFrame() {
bool IsGeneratedContentFrame() const {
return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
}

View File

@ -134,15 +134,45 @@ CommonAnimationManager::NeedsRefresh() const
}
AnimationCollection*
CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent,
nsIAtom* aElementProperty,
CommonAnimationManager::GetAnimationCollection(const nsIFrame* aFrame)
{
nsIContent* content = aFrame->GetContent();
if (!content) {
return nullptr;
}
nsIAtom* animProp;
if (aFrame->IsGeneratedContentFrame()) {
nsIFrame* parent = aFrame->GetParent();
if (parent->IsGeneratedContentFrame()) {
return nullptr;
}
nsIAtom* name = content->NodeInfo()->NameAtom();
if (name == nsGkAtoms::mozgeneratedcontentbefore) {
animProp = GetAnimationsBeforeAtom();
} else if (name == nsGkAtoms::mozgeneratedcontentafter) {
animProp = GetAnimationsAfterAtom();
} else {
return nullptr;
}
content = content->GetParent();
if (!content) {
return nullptr;
}
} else {
if (!content->MayHaveAnimations()) {
return nullptr;
}
animProp = GetAnimationsAtom();
}
return static_cast<AnimationCollection*>(content->GetProperty(animProp));
}
AnimationCollection*
CommonAnimationManager::GetAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return nullptr;
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(aElementProperty));
AnimationCollection* collection = GetAnimationCollection(aFrame);
if (!collection ||
!collection->HasAnimationOfProperty(aProperty) ||
!collection->CanPerformOnCompositorThread(
@ -337,11 +367,12 @@ CommonAnimationManager::GetAnimations(dom::Element *aElement,
&AnimationCollection::PropertyDtor, false);
if (NS_FAILED(rv)) {
NS_WARNING("SetProperty failed");
delete collection;
// The collection must be destroyed via PropertyDtor, otherwise
// mCalledPropertyDtor assertion is triggered in destructor.
AnimationCollection::PropertyDtor(aElement, propName, collection, nullptr);
return nullptr;
}
if (propName == nsGkAtoms::animationsProperty ||
propName == nsGkAtoms::transitionsProperty) {
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
aElement->SetMayHaveAnimations();
}
@ -577,21 +608,12 @@ bool
AnimationCollection::CanPerformOnCompositorThread(
CanAnimateFlags aFlags) const
{
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement);
if (!frame) {
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
if (mElementProperty != nsGkAtoms::transitionsProperty &&
mElementProperty != nsGkAtoms::animationsProperty) {
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
nsCString message;
message.AppendLiteral("Gecko bug: Async animation of pseudoelements"
" not supported. See bug 771367 (");
message.Append(nsAtomCString(mElementProperty));
message.Append(")");
LogAsyncAnimationFailure(message, mElement);
}
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(element);
if (!frame) {
return false;
}
@ -628,7 +650,7 @@ AnimationCollection::CanPerformOnCompositorThread(
for (size_t propIdx = 0, propEnd = effect->Properties().Length();
propIdx != propEnd; ++propIdx) {
const AnimationProperty& prop = effect->Properties()[propIdx];
if (!CanAnimatePropertyOnCompositor(mElement,
if (!CanAnimatePropertyOnCompositor(element,
prop.mProperty,
aFlags) ||
IsCompositorAnimationDisabledForFrame(frame)) {
@ -839,10 +861,15 @@ AnimationCollection::CanThrottleTransformChanges(TimeStamp aTime)
return true;
}
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
// If the nearest scrollable ancestor has overflow:hidden,
// we don't care about overflow.
nsIScrollableFrame* scrollable = nsLayoutUtils::GetNearestScrollableFrame(
nsLayoutUtils::GetStyleFrame(mElement));
nsLayoutUtils::GetStyleFrame(element));
if (!scrollable) {
return true;
}
@ -860,7 +887,11 @@ AnimationCollection::CanThrottleTransformChanges(TimeStamp aTime)
bool
AnimationCollection::CanThrottleAnimation(TimeStamp aTime)
{
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement);
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(element);
if (!frame) {
return false;
}

View File

@ -161,19 +161,26 @@ protected:
return false;
}
public:
// Return an AnimationCollection* if we have an animation for
// the element aContent and pseudo-element indicator aElementProperty
// that can be performed on the compositor thread (as defined by
// AnimationCollection::CanPerformOnCompositorThread).
// the frame aFrame that can be performed on the compositor thread (as
// defined by AnimationCollection::CanPerformOnCompositorThread).
//
// Note that this does not test whether the element's layer uses
// Note that this does not test whether the frame's layer uses
// off-main-thread compositing, although it does check whether
// off-main-thread compositing is enabled as a whole.
static AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent,
nsIAtom* aElementProperty,
AnimationCollection*
GetAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty);
// Given the frame aFrame with possibly animated content, finds its
// associated collection of animations. If it is a generated content
// frame, it may examine the parent frame to search for such animations.
AnimationCollection*
GetAnimationCollection(const nsIFrame* aFrame);
protected:
PRCList mElementCollections;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
bool mIsObservingRefreshDriver;

View File

@ -163,13 +163,6 @@ public:
{
}
static mozilla::AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty)
{
return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor(
aContent, nsGkAtoms::animationsProperty, aProperty);
}
void UpdateStyleAndEvents(mozilla::AnimationCollection* aEA,
mozilla::TimeStamp aRefreshTime,
mozilla::EnsureStyleRuleFlags aFlags);

View File

@ -117,13 +117,6 @@ public:
typedef mozilla::AnimationCollection AnimationCollection;
static AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty)
{
return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor(
aContent, nsGkAtoms::transitionsProperty, aProperty);
}
/**
* StyleContextChanged
*

View File

@ -404,19 +404,23 @@ const ExpectComparisonTo = {
};
(function() {
window.omta_todo_is = function(elem, property, expected, runningOn, desc) {
window.omta_todo_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Fail);
ExpectComparisonTo.Fail, pseudo);
};
window.omta_is = function(elem, property, expected, runningOn, desc) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc);
window.omta_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Pass, pseudo);
};
// Many callers of this method will pass 'undefined' for
// expectedComparisonResult.
window.omta_is_approx = function(elem, property, expected, tolerance,
runningOn, desc, expectedComparisonResult) {
runningOn, desc, expectedComparisonResult,
pseudo) {
// Check input
const omtaProperties = [ "transform", "opacity" ];
if (omtaProperties.indexOf(property) === -1) {
@ -434,8 +438,8 @@ const ExpectComparisonTo = {
// Get actual values
var compositorStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(elem, property);
var computedStr = window.getComputedStyle(elem)[property];
SpecialPowers.DOMWindowUtils.getOMTAStyle(elem, property, pseudo);
var computedStr = window.getComputedStyle(elem, pseudo)[property];
// Prepare expected value
var expectedValue = normalize(expected);

View File

@ -86,6 +86,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646
from, to { transform: translate(50px) }
}
#withbefore::before, #withafter::after {
content: "test";
animation: anim4 1s linear alternate 3;
display:block;
}
@keyframes multiprop {
0% {
transform: translate(10px); opacity: 0.3;
@ -1436,8 +1442,72 @@ addAsyncAnimTest(function *() {
* http://dev.w3.org/csswg/css3-animations/#the-animation-shorthand-property-
*/
// (Unlike test_animations.html, pseudo-elements are not tested here since they
// are currently not run on the compositor thread.)
/**
* Basic tests of animations on pseudo-elements
*/
addAsyncAnimTest(function *() {
new_div("");
listen();
gDiv.id = "withbefore";
yield waitForPaintsFlushed();
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":before test at 0ms", "::before");
advance_clock(400);
omta_is("transform", { ty: 40 }, RunningOn.Compositor,
":before test at 400ms", "::before");
advance_clock(800);
omta_is("transform", { ty: 80 }, RunningOn.Compositor,
":before test at 1200ms", "::before");
omta_is("transform", { ty: 0 }, RunningOn.MainThread,
":before animation should not affect element");
advance_clock(800);
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":before test at 2000ms", "::before");
advance_clock(300);
omta_is("transform", { ty: 30 }, RunningOn.Compositor,
":before test at 2300ms", "::before");
advance_clock(700);
check_events([ { type: "animationstart", animationName: "anim4",
elapsedTime: 0, pseudoElement: "::before" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 1, pseudoElement: "::before" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 2, pseudoElement: "::before" },
{ type: "animationend", animationName: "anim4",
elapsedTime: 3, pseudoElement: "::before" }]);
done_div();
new_div("");
listen();
gDiv.id = "withafter";
yield waitForPaintsFlushed();
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":after test at 0ms", "::after");
advance_clock(400);
omta_is("transform", { ty: 40 }, RunningOn.Compositor,
":after test at 400ms", "::after");
advance_clock(800);
omta_is("transform", { ty: 80 }, RunningOn.Compositor,
":after test at 1200ms", "::after");
omta_is("transform", { ty: 0 }, RunningOn.MainThread,
":before animation should not affect element");
advance_clock(800);
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":after test at 2000ms", "::after");
advance_clock(300);
omta_is("transform", { ty: 30 }, RunningOn.Compositor,
":after test at 2300ms", "::after");
advance_clock(700);
check_events([ { type: "animationstart", animationName: "anim4",
elapsedTime: 0, pseudoElement: "::after" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 1, pseudoElement: "::after" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 2, pseudoElement: "::after" },
{ type: "animationend", animationName: "anim4",
elapsedTime: 3, pseudoElement: "::after" }]);
done_div();
});
/**
* Test handling of properties that are present in only some of the

View File

@ -521,8 +521,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
// for it to finish before firing the popupshown event.
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::animate,
nsGkAtoms::open, eCaseMatters) &&
nsLayoutUtils::HasCurrentAnimations(mContent,
nsGkAtoms::transitionsProperty)) {
nsLayoutUtils::HasCurrentTransitions(this)) {
mPopupShownDispatcher = new nsXULPopupShownEvent(mContent, pc);
mContent->AddSystemEventListener(NS_LITERAL_STRING("transitionend"),
mPopupShownDispatcher, false, false);

View File

@ -1473,8 +1473,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
if (!popupFrame)
return;
if (nsLayoutUtils::HasCurrentAnimations(aPopup,
nsGkAtoms::transitionsProperty)) {
if (nsLayoutUtils::HasCurrentTransitions(popupFrame)) {
nsRefPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aDeselectMenu);
aPopup->AddSystemEventListener(NS_LITERAL_STRING("transitionend"),
ender, false, false);

View File

@ -119,7 +119,7 @@ GetInterfaces(std::vector<NetworkInterface>* aInterfaces)
int
nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
int aDropLoopback, int* aCount)
int aDropLoopback, int aDropLinkLocal, int* aCount)
{
nsresult rv;
int r;
@ -141,7 +141,6 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
for (size_t i = 0; i < num_interface; ++i) {
NetworkInterface &interface = interfaces[i];
if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr),
sizeof(struct sockaddr_in),
IPPROTO_UDP, 0, &(aAddrs[n].addr))) {
r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
return R_FAILED;
@ -154,7 +153,7 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
}
*aCount = n;
r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount);
r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aDropLinkLocal, aCount);
if (r != 0) {
return r;
}

View File

@ -337,20 +337,11 @@ static int nr_transport_addr_to_praddr(nr_transport_addr *addr,
naddr->inet.ip = addr->u.addr4.sin_addr.s_addr;
break;
case NR_IPV6:
#if 0
naddr->ipv6.family = PR_AF_INET6;
naddr->ipv6.port = addr->u.addr6.sin6_port;
#ifdef LINUX
memcpy(naddr->ipv6.ip._S6_un._S6_u8,
&addr->u.addr6.sin6_addr.__in6_u.__u6_addr8, 16);
#else
memcpy(naddr->ipv6.ip._S6_un._S6_u8,
&addr->u.addr6.sin6_addr.__u6_addr.__u6_addr8, 16);
#endif
#else
// TODO: make IPv6 work
ABORT(R_INTERNAL);
#endif
naddr->ipv6.flowinfo = addr->u.addr6.sin6_flowinfo;
memcpy(&naddr->ipv6.ip, &addr->u.addr6.sin6_addr, sizeof(in6_addr));
naddr->ipv6.scope_id = addr->u.addr6.sin6_scope_id;
break;
default:
ABORT(R_BAD_ARGS);
@ -440,6 +431,7 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
int _status;
int r;
struct sockaddr_in ip4;
struct sockaddr_in6 ip6;
switch(praddr->raw.family) {
case PR_AF_INET:
@ -447,18 +439,19 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
ip4.sin_addr.s_addr = praddr->inet.ip;
ip4.sin_port = praddr->inet.port;
if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip4,
sizeof(ip4),
protocol, keep,
addr)))
ABORT(r);
break;
case PR_AF_INET6:
#if 0
r = nr_sockaddr_to_transport_addr((sockaddr *)&praddr->raw,
sizeof(struct sockaddr_in6),IPPROTO_UDP,keep,addr);
ip6.sin6_family = PF_INET6;
ip6.sin6_port = praddr->ipv6.port;
ip6.sin6_flowinfo = praddr->ipv6.flowinfo;
memcpy(&ip6.sin6_addr, &praddr->ipv6.ip, sizeof(in6_addr));
ip6.sin6_scope_id = praddr->ipv6.scope_id;
if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip6,protocol,keep,addr)))
ABORT(r);
break;
#endif
ABORT(R_BAD_ARGS);
default:
MOZ_ASSERT(false);
ABORT(R_BAD_ARGS);
@ -516,14 +509,16 @@ int NrSocket::create(nr_transport_addr *addr) {
switch (addr->protocol) {
case IPPROTO_UDP:
if (!(fd_ = PR_NewUDPSocket())) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket");
if (!(fd_ = PR_OpenUDPSocket(naddr.raw.family))) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create UDP socket, "
"family=%d, err=%d", naddr.raw.family, PR_GetError());
ABORT(R_INTERNAL);
}
break;
case IPPROTO_TCP:
if (!(fd_ = PR_NewTCPSocket())) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket");
if (!(fd_ = PR_OpenTCPSocket(naddr.raw.family))) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create TCP socket, "
"family=%d, err=%d", naddr.raw.family, PR_GetError());
ABORT(R_INTERNAL);
}
// Set ReuseAddr for TCP sockets to enable having several
@ -686,7 +681,8 @@ int NrSocket::sendto(const void *msg, size_t len,
if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
ABORT(R_WOULDBLOCK);
r_log(LOG_GENERIC, LOG_INFO, "Error in sendto: %s", to->as_string);
r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s: %d",
to->as_string, PR_GetError());
ABORT(R_IO_ERROR);
}

View File

@ -380,7 +380,8 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
bool offerer,
bool set_interface_priorities,
bool allow_loopback,
bool tcp_enabled) {
bool tcp_enabled,
bool allow_link_local) {
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);
@ -472,6 +473,10 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
if (allow_loopback) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
}
if (allow_link_local) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
}
}
// Create the ICE context

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