Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-06-27 15:56:37 +02:00
commit 7fdfacf9ee
292 changed files with 15067 additions and 12863 deletions

View File

@ -472,13 +472,6 @@ SettingsListener.observe('debugger.remote-mode', false, function(value) {
#endif
});
// If debug access to certified apps is allowed, we need to preserve system
// sources so that they are visible in the debugger.
let forbidCertified =
Services.prefs.getBoolPref('devtools.debugger.forbid-certified-apps');
Services.prefs.setBoolPref('javascript.options.discardSystemSource',
forbidCertified);
// =================== Device Storage ====================
SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) {
if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) {

View File

@ -1512,6 +1512,7 @@ pref("image.mem.max_decoded_image_kb", 256000);
#ifdef MOZ_LOOP
pref("loop.server", "https://loop.services.mozilla.com");
pref("loop.do_not_disturb", false);
pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
#endif
// serverURL to be assigned by services team

View File

@ -34,22 +34,22 @@ addMessageListener("Browser:HideSessionRestoreButton", function (message) {
}
});
addEventListener("DOMFormHasPassword", function(event) {
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
LoginManagerContent.onFormPassword(event);
});
addEventListener("DOMAutoComplete", function(event) {
LoginManagerContent.onUsernameInput(event);
});
addEventListener("blur", function(event) {
LoginManagerContent.onUsernameInput(event);
});
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
addEventListener("contextmenu", function (event) {
sendAsyncMessage("contextmenu", {}, { event: event });
}, false);
} else {
addEventListener("DOMFormHasPassword", function(event) {
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
LoginManagerContent.onFormPassword(event);
});
addEventListener("DOMAutoComplete", function(event) {
LoginManagerContent.onUsernameInput(event);
});
addEventListener("blur", function(event) {
LoginManagerContent.onUsernameInput(event);
});
addEventListener("mozUITour", function(event) {
if (!Services.prefs.getBoolPref("browser.uitour.enabled"))
return;

View File

@ -24,6 +24,9 @@ this.EXPORTED_SYMBOLS = ["injectLoopAPI"];
* @param {nsIDOMWindow} targetWindow The content window to attach the API.
*/
function injectLoopAPI(targetWindow) {
let ringer;
let ringerStopper;
let api = {
/**
* Sets and gets the "do not disturb" mode activation flag.
@ -149,6 +152,50 @@ function injectLoopAPI(targetWindow) {
value: function(prefName) {
return MozLoopService.getLoopCharPref(prefName);
}
},
/**
* Starts alerting the user about an incoming call
*/
startAlerting: {
enumerable: true,
configurable: true,
writable: true,
value: function() {
let chromeWindow = getChromeWindow(targetWindow);
chromeWindow.getAttention();
ringer = new chromeWindow.Audio();
ringer.src = Services.prefs.getCharPref("loop.ringtone");
ringer.loop = true;
ringer.load();
ringer.play();
targetWindow.document.addEventListener("visibilitychange",
ringerStopper = function(event) {
if (event.currentTarget.hidden) {
api.stopAlerting.value();
}
});
}
},
/**
* Stops alerting the user about an incoming call
*/
stopAlerting: {
enumerable: true,
configurable: true,
writable: true,
value: function() {
if (ringerStopper) {
targetWindow.document.removeEventListener("visibilitychange",
ringerStopper);
ringerStopper = null;
}
if (ringer) {
ringer.pause();
ringer = null;
}
}
}
};
@ -168,3 +215,12 @@ function injectLoopAPI(targetWindow) {
// Handle window.close correctly on the panel and chatbox.
hookWindowCloseForPanelClose(targetWindow);
}
function getChromeWindow(contentWin) {
return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}

View File

@ -53,8 +53,7 @@ loop.conversation = (function(OT, mozL10n) {
*/
handleDecline: function(event) {
event.preventDefault();
// XXX For now, we just close the window.
window.close();
this.model.trigger("decline");
}
});
@ -95,6 +94,7 @@ loop.conversation = (function(OT, mozL10n) {
routes: {
"incoming/:version": "incoming",
"call/accept": "accept",
"call/decline": "decline",
"call/ongoing": "conversation",
"call/ended": "ended"
},
@ -120,10 +120,14 @@ loop.conversation = (function(OT, mozL10n) {
* by the router from the URL.
*/
incoming: function(loopVersion) {
window.navigator.mozLoop.startAlerting();
this._conversation.set({loopVersion: loopVersion});
this._conversation.once("accept", function() {
this.navigate("call/accept", {trigger: true});
}.bind(this));
this._conversation.once("decline", function() {
this.navigate("call/decline", {trigger: true});
}.bind(this));
this.loadView(new IncomingCallView({model: this._conversation}));
},
@ -131,12 +135,22 @@ loop.conversation = (function(OT, mozL10n) {
* Accepts an incoming call.
*/
accept: function() {
window.navigator.mozLoop.stopAlerting();
this._conversation.initiate({
baseServerUrl: window.navigator.mozLoop.serverUrl,
outgoing: false
});
},
/**
* Declines an incoming call.
*/
decline: function() {
window.navigator.mozLoop.stopAlerting();
// XXX For now, we just close the window
window.close();
},
/**
* conversation is the route when the conversation is active. The start
* route should be navigated to first.

View File

@ -21,6 +21,7 @@ browser.jar:
content/browser/loop/shared/libs/sjcl-dev20140604.js (content/shared/libs/sjcl-dev20140604.js)
content/browser/loop/shared/libs/token.js (content/shared/libs/token.js)
content/browser/loop/shared/libs/hawk-browser-2.2.1.js (content/shared/libs/hawk-browser-2.2.1.js)
content/browser/loop/shared/sounds/Firefox-Long.ogg (content/shared/sounds/Firefox-Long.ogg)
content/browser/loop/libs/l10n.js (content/libs/l10n.js)
content/browser/loop/js/desktopRouter.js (content/js/desktopRouter.js)
content/browser/loop/js/conversation.js (content/js/conversation.js)

View File

@ -26,6 +26,12 @@ describe("loop.conversation", function() {
window.navigator.mozLoop = {
get serverUrl() {
return "http://example.com";
},
startAlerting: function() {
},
stopAlerting: function() {
}
};
});
@ -119,6 +125,13 @@ describe("loop.conversation", function() {
sinon.assert.calledWithExactly(router.loadView,
sinon.match.instanceOf(loop.conversation.IncomingCallView));
});
it("should start alerting", function() {
sandbox.stub(window.navigator.mozLoop, "startAlerting");
router.incoming("fakeVersion");
sinon.assert.calledOnce(window.navigator.mozLoop.startAlerting);
});
});
describe("#accept", function() {
@ -131,6 +144,13 @@ describe("loop.conversation", function() {
outgoing: false
});
});
it("should stop alerting", function() {
sandbox.stub(window.navigator.mozLoop, "stopAlerting");
router.accept();
sinon.assert.calledOnce(window.navigator.mozLoop.stopAlerting);
});
});
describe("#conversation", function() {
@ -163,6 +183,25 @@ describe("loop.conversation", function() {
});
});
describe("#decline", function() {
beforeEach(function() {
sandbox.stub(window, "close");
});
it("should close the window", function() {
router.decline();
sinon.assert.calledOnce(window.close);
});
it("should stop alerting", function() {
sandbox.stub(window.navigator.mozLoop, "stopAlerting");
router.decline();
sinon.assert.calledOnce(window.navigator.mozLoop.stopAlerting);
});
});
describe("#ended", function() {
// XXX When the call is ended gracefully, we should check that we
// close connections nicely
@ -254,13 +293,14 @@ describe("loop.conversation", function() {
});
describe("#handleDecline", function() {
it("should close the window", function() {
sandbox.stub(window, "close");
it("should trigger an 'decline' conversation model event" ,
function(done) {
conversation.once("decline", function() {
done();
});
view.handleDecline({preventDefault: sandbox.spy()});
sinon.assert.calledOnce(window.close);
});
view.handleDecline({preventDefault: sandbox.spy()});
});
});
});
});

View File

@ -93,9 +93,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
"resource://gre/modules/AsyncShutdown.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
"resource://gre/modules/LoginManagerParent.jsm");
#ifdef NIGHTLY_BUILD
XPCOMUtils.defineLazyModuleGetter(this, "SignInToWebsiteUX",
"resource:///modules/SignInToWebsite.jsm");
@ -510,8 +507,6 @@ BrowserGlue.prototype = {
RemotePrompt.init();
}
LoginManagerParent.init();
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
},

View File

@ -33,13 +33,11 @@ let test = asyncTest(function*() {
* Just check current page
*/
function* navigate(usage, options) {
let running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
ok(!usage.isRunning(), "csscoverage is not running");
yield usage.oneshot();
running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
ok(!usage.isRunning(), "csscoverage is still not running");
}
/**

View File

@ -35,8 +35,7 @@ let test = asyncTest(function*() {
function* navigate(usage, options) {
yield usage.start();
let running = yield usage._testOnly_isRunning();
ok(running, "csscoverage is running");
ok(usage.isRunning(), "csscoverage is running");
yield helpers.navigate(PAGE_1, options);
@ -49,8 +48,7 @@ function* navigate(usage, options) {
yield usage.stop();
running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
ok(!usage.isRunning(), "csscoverage not is running");
}
/**

View File

@ -4,18 +4,19 @@
(function() {
const DEVTOOLS_SKIN_URL = "chrome://browser/skin/devtools/";
let documentElement = document.documentElement;
function forceStyle() {
let computedStyle = window.getComputedStyle(document.documentElement);
let computedStyle = window.getComputedStyle(documentElement);
if (!computedStyle) {
// Null when documentElement is not ready. This method is anyways not
// required then as scrollbars would be in their state without flushing.
return;
}
let display = computedStyle.display; // Save display value
document.documentElement.style.display = "none";
window.getComputedStyle(document.documentElement).display; // Flush
document.documentElement.style.display = display; // Restore
documentElement.style.display = "none";
window.getComputedStyle(documentElement).display; // Flush
documentElement.style.display = display; // Restore
}
function switchTheme(newTheme, oldTheme) {
@ -61,8 +62,8 @@
forceStyle();
}
document.documentElement.classList.remove("theme-" + oldTheme);
document.documentElement.classList.add("theme-" + newTheme);
documentElement.classList.remove("theme-" + oldTheme);
documentElement.classList.add("theme-" + newTheme);
}
function handlePrefChange(event, data) {
@ -78,11 +79,14 @@
const {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
const StylesheetUtils = devtools.require("sdk/stylesheet/utils");
let theme = Services.prefs.getCharPref("devtools.theme");
switchTheme(theme);
if (documentElement.hasAttribute("force-theme")) {
switchTheme(documentElement.getAttribute("force-theme"));
} else {
switchTheme(Services.prefs.getCharPref("devtools.theme"));
gDevTools.on("pref-changed", handlePrefChange);
window.addEventListener("unload", function() {
gDevTools.off("pref-changed", handlePrefChange);
});
gDevTools.on("pref-changed", handlePrefChange);
window.addEventListener("unload", function() {
gDevTools.off("pref-changed", handlePrefChange);
});
}
})();

View File

@ -157,6 +157,7 @@ function Editor(config) {
autoCloseBrackets: "()[]{}''\"\"",
autoCloseEnabled: useAutoClose,
theme: "mozilla",
themeSwitching: true,
autocomplete: false
};
@ -258,6 +259,9 @@ Editor.prototype = {
env.removeEventListener("load", onLoad, true);
let win = env.contentWindow.wrappedJSObject;
if (!this.config.themeSwitching)
win.document.documentElement.setAttribute("force-theme", "light");
CM_SCRIPTS.forEach((url) =>
Services.scriptloader.loadSubScript(url, win, "utf8"));

View File

@ -2869,7 +2869,13 @@ function getParentTextProperty(node) {
if (!parent) {
return null;
}
return parent.querySelector(".ruleview-propertyvalue").textProperty;
let propValue = parent.querySelector(".ruleview-propertyvalue");
if (!propValue) {
return null;
}
return propValue.textProperty;
}
/**

View File

@ -270,6 +270,7 @@ run-if = os == "mac"
[browser_webconsole_expandable_timestamps.js]
[browser_webconsole_autocomplete_in_debugger_stackframe.js]
[browser_webconsole_autocomplete_popup_close_on_tab_switch.js]
[browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
[browser_console_hide_jsterm_when_devtools_chrome_enabled_false.js]
[browser_webconsole_output_01.js]
[browser_webconsole_output_02.js]

View File

@ -0,0 +1,42 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
// Test that properties starting with underscores or dollars can be
// autocompleted (bug 967468).
function test() {
const TEST_URI = "data:text/html;charset=utf8,test autocompletion with $ or _";
Task.spawn(runner).then(finishTest);
function* runner() {
function autocomplete(term) {
let deferred = promise.defer();
jsterm.setInputValue(term);
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, deferred.resolve);
yield deferred.promise;
ok(popup.itemCount > 0, "There's suggestions for '" + term + "'");
}
yield addTab(TEST_URI);
let { jsterm } = yield openConsole(tab);
let popup = jsterm.autocompletePopup;
jsterm.execute("let testObject = {$$aaab: '', $$aaac: ''}");
// Should work with bug 967468.
yield autocomplete("Object.__d");
yield autocomplete("testObject.$$a");
// Here's when things go wrong in bug 967468.
yield autocomplete("Object.__de");
yield autocomplete("testObject.$$aa");
}
}

View File

@ -4292,8 +4292,8 @@ JSTerm.prototype = {
if (this._autocompleteQuery && input.startsWith(this._autocompleteQuery)) {
let filterBy = input;
// Find the last non-alphanumeric if exists.
let lastNonAlpha = input.match(/[^a-zA-Z0-9][a-zA-Z0-9]*$/);
// Find the last non-alphanumeric other than _ or $ if it exists.
let lastNonAlpha = input.match(/[^a-zA-Z0-9_$][a-zA-Z0-9_$]*$/);
// If input contains non-alphanumerics, use the part after the last one
// to filter the cache
if (lastNonAlpha) {

View File

@ -233,7 +233,15 @@ let UI = {
/********** RUNTIME **********/
updateRuntimeList: function() {
let wifiHeaderNode = document.querySelector("#runtime-header-wifi-devices");
if (AppManager.isWiFiScanningEnabled) {
wifiHeaderNode.removeAttribute("hidden");
} else {
wifiHeaderNode.setAttribute("hidden", "true");
}
let USBListNode = document.querySelector("#runtime-panel-usbruntime");
let WiFiListNode = document.querySelector("#runtime-panel-wifi-devices");
let simulatorListNode = document.querySelector("#runtime-panel-simulators");
let customListNode = document.querySelector("#runtime-panel-custom");
@ -261,6 +269,7 @@ let UI = {
for (let [type, parent] of [
["usb", USBListNode],
["wifi", WiFiListNode],
["simulator", simulatorListNode],
["custom", customListNode],
]) {
@ -775,6 +784,8 @@ let Cmds = {
},
showRuntimePanel: function() {
AppManager.scanForWiFiRuntimes();
let panel = document.querySelector("#runtime-panel");
let anchor = document.querySelector("#runtime-panel-button > .panel-button-anchor");

View File

@ -144,6 +144,8 @@
<toolbarbutton class="panel-item-help" label="&runtimePanel_nousbdevice;" id="runtime-panel-nousbdevice" command="cmd_showTroubleShooting"/>
<toolbarbutton class="panel-item-help" label="&runtimePanel_noadbhelper;" id="runtime-panel-noadbhelper" command="cmd_showAddons"/>
<vbox id="runtime-panel-usbruntime"></vbox>
<label class="panel-header" id="runtime-header-wifi-devices">&runtimePanel_WiFiDevices;</label>
<vbox id="runtime-panel-wifi-devices"></vbox>
<label class="panel-header">&runtimePanel_simulators;</label>
<toolbarbutton class="panel-item-help" label="&runtimePanel_nosimulator;" id="runtime-panel-nosimulator" command="cmd_showAddons"/>
<vbox id="runtime-panel-simulators"></vbox>

View File

@ -59,6 +59,7 @@
<!ENTITY projectPanel_myProjects "My Projects">
<!ENTITY projectPanel_runtimeApps "Runtime Apps">
<!ENTITY runtimePanel_USBDevices "USB Devices">
<!ENTITY runtimePanel_WiFiDevices "WiFi Devices">
<!ENTITY runtimePanel_simulators "Simulators">
<!ENTITY runtimePanel_custom "Custom">
<!ENTITY runtimePanel_nosimulator "Install Simulator">

View File

@ -20,10 +20,14 @@ const AppActorFront = require("devtools/app-actor-front");
const {getDeviceFront} = require("devtools/server/actors/device");
const {setTimeout} = require("sdk/timers");
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const {USBRuntime, SimulatorRuntime, gLocalRuntime, gRemoteRuntime} = require("devtools/webide/runtimes");
const {USBRuntime, WiFiRuntime, SimulatorRuntime,
gLocalRuntime, gRemoteRuntime} = require("devtools/webide/runtimes");
const discovery = require("devtools/toolkit/discovery/discovery");
const Strings = Services.strings.createBundle("chrome://webide/content/webide.properties");
const WIFI_SCANNING_PREF = "devtools.remote.wifi.scan";
exports.AppManager = AppManager = {
// FIXME: will break when devtools/app-manager will be removed:
@ -42,12 +46,21 @@ exports.AppManager = AppManager = {
this.webAppsStore = new WebappsStore(this.connection);
this.webAppsStore.on("store-ready", this.onWebAppsStoreready);
this.runtimeList = {usb: [], simulator: [], custom: [gRemoteRuntime]};
this.runtimeList = {
usb: [],
wifi: [],
simulator: [],
custom: [gRemoteRuntime]
};
if (Services.prefs.getBoolPref("devtools.webide.enableLocalRuntime")) {
this.runtimeList.custom.push(gLocalRuntime);
}
this.trackUSBRuntimes();
this.trackWiFiRuntimes();
this.trackSimulatorRuntimes();
this.observe = this.observe.bind(this);
Services.prefs.addObserver(WIFI_SCANNING_PREF, this, false);
},
uninit: function() {
@ -55,6 +68,7 @@ exports.AppManager = AppManager = {
this.selectedProject = null;
this.selectedRuntime = null;
this.untrackUSBRuntimes();
this.untrackWiFiRuntimes();
this.untrackSimulatorRuntimes();
this._runningApps.clear();
this.runtimeList = null;
@ -65,6 +79,17 @@ exports.AppManager = AppManager = {
this._listTabsResponse = null;
this.connection.disconnect();
this.connection = null;
Services.prefs.removeObserver(WIFI_SCANNING_PREF, this);
},
observe: function(subject, topic, data) {
if (data !== WIFI_SCANNING_PREF) {
return;
}
// Cycle WiFi tracking to reflect the new value
this.untrackWiFiRuntimes();
this.trackWiFiRuntimes();
this._updateWiFiRuntimes();
},
update: function(what, details) {
@ -505,6 +530,40 @@ exports.AppManager = AppManager = {
this.update("runtimelist");
},
get isWiFiScanningEnabled() {
return Services.prefs.getBoolPref(WIFI_SCANNING_PREF);
},
scanForWiFiRuntimes: function() {
if (!this.isWiFiScanningEnabled) {
return;
}
discovery.scan();
},
trackWiFiRuntimes: function() {
if (!this.isWiFiScanningEnabled) {
return;
}
this._updateWiFiRuntimes = this._updateWiFiRuntimes.bind(this);
discovery.on("devtools-device-added", this._updateWiFiRuntimes);
discovery.on("devtools-device-updated", this._updateWiFiRuntimes);
discovery.on("devtools-device-removed", this._updateWiFiRuntimes);
},
untrackWiFiRuntimes: function() {
if (!this.isWiFiScanningEnabled) {
return;
}
discovery.off("devtools-device-added", this._updateWiFiRuntimes);
discovery.off("devtools-device-updated", this._updateWiFiRuntimes);
discovery.off("devtools-device-removed", this._updateWiFiRuntimes);
},
_updateWiFiRuntimes: function() {
this.runtimeList.wifi = [];
for (let device of discovery.getRemoteDevicesWithService("devtools")) {
this.runtimeList.wifi.push(new WiFiRuntime(device));
}
this.update("runtimelist");
},
trackSimulatorRuntimes: function() {
this._updateSimulatorRuntimes = this._updateSimulatorRuntimes.bind(this);
Simulator.on("register", this._updateSimulatorRuntimes);

View File

@ -8,6 +8,7 @@ const {Services} = Cu.import("resource://gre/modules/Services.jsm");
const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
const {DebuggerServer} = require("resource://gre/modules/devtools/dbg-server.jsm");
const discovery = require("devtools/toolkit/discovery/discovery");
const Strings = Services.strings.createBundle("chrome://webide/content/webide.properties");
@ -19,7 +20,7 @@ USBRuntime.prototype = {
connect: function(connection) {
let device = Devices.getByName(this.id);
if (!device) {
return promise.reject("Can't find device: " + id);
return promise.reject("Can't find device: " + this.getName());
}
return device.connect().then((port) => {
connection.host = "localhost";
@ -35,6 +36,29 @@ USBRuntime.prototype = {
},
}
function WiFiRuntime(deviceName) {
this.deviceName = deviceName;
}
WiFiRuntime.prototype = {
connect: function(connection) {
let service = discovery.getRemoteService("devtools", this.deviceName);
if (!service) {
return promise.reject("Can't find device: " + this.getName());
}
connection.host = service.host;
connection.port = service.port;
connection.connect();
return promise.resolve();
},
getID: function() {
return this.deviceName;
},
getName: function() {
return this.deviceName;
},
}
function SimulatorRuntime(version) {
this.version = version;
}
@ -44,7 +68,7 @@ SimulatorRuntime.prototype = {
let port = ConnectionManager.getFreeTCPPort();
let simulator = Simulator.getByVersion(this.version);
if (!simulator || !simulator.launch) {
return promise.reject("Can't find simulator: " + this.version);
return promise.reject("Can't find simulator: " + this.getName());
}
return simulator.launch({port: port}).then(() => {
connection.port = port;
@ -102,6 +126,7 @@ let gRemoteRuntime = {
}
exports.USBRuntime = USBRuntime;
exports.WiFiRuntime = WiFiRuntime;
exports.SimulatorRuntime = SimulatorRuntime;
exports.gRemoteRuntime = gRemoteRuntime;
exports.gLocalRuntime = gLocalRuntime;

View File

@ -187,6 +187,7 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
#runtime-permissions,
#runtime-screenshot,
.runtime-panel-item-usb,
.runtime-panel-item-wifi,
.runtime-panel-item-custom,
.runtime-panel-item-simulator {
list-style-image: url("icons.png");
@ -195,6 +196,7 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
#runtime-screenshot { -moz-image-region: rect(200px, 640px, 240px, 600px) }
#runtime-permissions { -moz-image-region: rect(100px, 840px, 140px, 800px) }
.runtime-panel-item-usb { -moz-image-region: rect(100px, 640px, 140px, 600px) }
.runtime-panel-item-wifi { -moz-image-region: rect(100px, 640px, 140px, 600px) }
.runtime-panel-item-custom { -moz-image-region: rect(100px, 640px, 140px, 600px) }
.runtime-panel-item-simulator { -moz-image-region: rect(100px, 740px, 140px, 700px) }

View File

@ -7,9 +7,6 @@
Cu.import("resource://gre/modules/devtools/dbg-server.jsm")
Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
"resource://gre/modules/LoginManagerParent.jsm");
/**
* Constants
*/
@ -170,7 +167,6 @@ var BrowserUI = {
DialogUI.init();
FormHelperUI.init();
FindHelperUI.init();
LoginManagerParent.init();
#ifdef NIGHTLY_BUILD
PdfJs.init();
#endif

View File

@ -39,6 +39,18 @@ class nsIFile;
class nsIInputStream;
class nsIClassInfo;
#define PIDOMFILEIMPL_IID \
{ 0x218ee173, 0xf44f, 0x4d30, \
{ 0xab, 0x0c, 0xd6, 0x66, 0xea, 0xc2, 0x84, 0x47 } }
class PIDOMFileImpl : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(PIDOMFILEIMPL_IID)
};
NS_DEFINE_STATIC_IID_ACCESSOR(PIDOMFileImpl, PIDOMFILEIMPL_IID)
namespace mozilla {
namespace dom {
@ -48,67 +60,19 @@ class FileInfo;
class DOMFileImpl;
// XXX bug 827823 will get rid of DOMFileBase
class DOMFileBase : public nsIDOMFile
, public nsIXHRSendable
, public nsIMutable
, public nsIJSNativeInitializer
class DOMFile MOZ_FINAL : public nsIDOMFile
, public nsIXHRSendable
, public nsIMutable
, public nsIJSNativeInitializer
{
// XXX bug 827823 will get rid of DOMFileCC
friend class DOMFileCC;
public:
NS_DECL_NSIDOMBLOB
NS_DECL_NSIDOMFILE
NS_DECL_NSIXHRSENDABLE
NS_DECL_NSIMUTABLE
DOMFileBase(DOMFileImpl* aImpl)
: mImpl(aImpl)
{
MOZ_ASSERT(mImpl);
}
DOMFileImpl* Impl() const
{
return mImpl;
}
const nsTArray<nsCOMPtr<nsIDOMBlob>>* GetSubBlobs() const;
bool IsSizeUnknown() const;
bool IsDateUnknown() const;
bool IsFile() const;
void SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, uint64_t aLastModifiedDate);
already_AddRefed<nsIDOMBlob>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType);
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
const JS::CallArgs& aArgs) MOZ_OVERRIDE;
protected:
virtual ~DOMFileBase() {};
private:
// The member is the real backend implementation of this DOMFile/DOMBlob.
// It's thread-safe and not CC-able and it's the only element that is moved
// between threads.
const nsRefPtr<DOMFileImpl> mImpl;
};
// XXX bug 827823 - this class should be MOZ_FINAL
class DOMFile : public DOMFileBase
{
public:
// XXX bug 827823 will make this class CC and not thread-safe
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DOMFile, nsIDOMFile)
static already_AddRefed<DOMFile>
Create(const nsAString& aName, const nsAString& aContentType,
@ -159,37 +123,54 @@ public:
const nsAString& aContentType);
explicit DOMFile(DOMFileImpl* aImpl)
: DOMFileBase(aImpl)
{}
protected:
virtual ~DOMFile() {};
};
// XXX bug 827823 will get rid of this class
class DOMFileCC MOZ_FINAL : public DOMFileBase
{
public:
DOMFileCC(DOMFileImpl* aImpl)
: DOMFileBase(aImpl)
{}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DOMFileCC, nsIDOMFile)
protected:
virtual ~DOMFileCC() {};
};
// This is the virtual class for any DOMFile backend. It must be nsISupports
// because this class must be ref-counted and it has to work with IPC.
class DOMFileImpl : public nsISupports
{
public:
DOMFileImpl()
: mImpl(aImpl)
{
MOZ_ASSERT(mImpl);
}
DOMFileImpl* Impl() const
{
return mImpl;
}
const nsTArray<nsRefPtr<DOMFileImpl>>* GetSubBlobImpls() const;
bool IsSizeUnknown() const;
bool IsDateUnknown() const;
bool IsFile() const;
void SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, uint64_t aLastModifiedDate);
already_AddRefed<nsIDOMBlob>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType);
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
const JS::CallArgs& aArgs) MOZ_OVERRIDE;
private:
~DOMFile() {};
// The member is the real backend implementation of this DOMFile/DOMBlob.
// It's thread-safe and not CC-able and it's the only element that is moved
// between threads.
// Note: we should not store any other state in this class!
const nsRefPtr<DOMFileImpl> mImpl;
};
// This is the abstract class for any DOMFile backend. It must be nsISupports
// because this class must be ref-counted and it has to work with IPC.
class DOMFileImpl : public PIDOMFileImpl
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
DOMFileImpl() {}
virtual nsresult GetName(nsAString& aName) = 0;
virtual nsresult GetPath(nsAString& aName) = 0;
@ -215,8 +196,8 @@ public:
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) = 0;
virtual const nsTArray<nsCOMPtr<nsIDOMBlob>>*
GetSubBlobs() const = 0;
virtual const nsTArray<nsRefPtr<DOMFileImpl>>*
GetSubBlobImpls() const = 0;
virtual nsresult GetInternalStream(nsIInputStream** aStream) = 0;
@ -259,6 +240,11 @@ public:
virtual void Unlink() = 0;
virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) = 0;
virtual bool IsCCed() const
{
return false;
}
protected:
virtual ~DOMFileImpl() {}
};
@ -266,8 +252,6 @@ protected:
class DOMFileImplBase : public DOMFileImpl
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
DOMFileImplBase(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, uint64_t aLastModifiedDate)
: mIsFile(true)
@ -344,8 +328,8 @@ public:
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
virtual const nsTArray<nsCOMPtr<nsIDOMBlob>>*
GetSubBlobs() const MOZ_OVERRIDE
virtual const nsTArray<nsRefPtr<DOMFileImpl>>*
GetSubBlobImpls() const MOZ_OVERRIDE
{
return nullptr;
}
@ -462,6 +446,8 @@ protected:
class DOMFileImplMemory MOZ_FINAL : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
DOMFileImplMemory(void* aMemoryBuffer, uint64_t aLength,
const nsAString& aName,
const nsAString& aContentType,
@ -556,6 +542,8 @@ private:
class DOMFileImplTemporaryFileBlob MOZ_FINAL : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
DOMFileImplTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos,
uint64_t aLength, const nsAString& aContentType)
: DOMFileImplBase(aContentType, aLength)
@ -593,6 +581,8 @@ private:
class DOMFileImplFile MOZ_FINAL : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
// Create as a file
explicit DOMFileImplFile(nsIFile* aFile)
: DOMFileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)

View File

@ -21,6 +21,8 @@
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS_INHERITED0(DOMMultipartFileImpl, DOMFileImpl)
nsresult
DOMMultipartFileImpl::GetSize(uint64_t* aLength)
{
@ -39,11 +41,11 @@ DOMMultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
uint32_t i;
for (i = 0; i < mBlobs.Length(); i++) {
for (i = 0; i < mBlobImpls.Length(); i++) {
nsCOMPtr<nsIInputStream> scratchStream;
nsIDOMBlob* blob = mBlobs.ElementAt(i).get();
DOMFileImpl* blobImpl = mBlobImpls.ElementAt(i).get();
rv = blob->GetInternalStream(getter_AddRefs(scratchStream));
rv = blobImpl->GetInternalStream(getter_AddRefs(scratchStream));
NS_ENSURE_SUCCESS(rv, rv);
rv = stream->AppendStream(scratchStream);
@ -58,27 +60,27 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
// If we clamped to nothing we create an empty blob
nsTArray<nsCOMPtr<nsIDOMBlob> > blobs;
nsTArray<nsRefPtr<DOMFileImpl>> blobImpls;
uint64_t length = aLength;
uint64_t skipStart = aStart;
// Prune the list of blobs if we can
uint32_t i;
for (i = 0; length && skipStart && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
for (i = 0; length && skipStart && i < mBlobImpls.Length(); i++) {
DOMFileImpl* blobImpl = mBlobImpls[i].get();
uint64_t l;
nsresult rv = blob->GetSize(&l);
nsresult rv = blobImpl->GetSize(&l);
NS_ENSURE_SUCCESS(rv, nullptr);
if (skipStart < l) {
uint64_t upperBound = std::min<uint64_t>(l - skipStart, length);
nsCOMPtr<nsIDOMBlob> firstBlob;
rv = blob->Slice(skipStart, skipStart + upperBound,
aContentType, 3,
getter_AddRefs(firstBlob));
rv = blobImpl->Slice(skipStart, skipStart + upperBound,
aContentType, 3,
getter_AddRefs(firstBlob));
NS_ENSURE_SUCCESS(rv, nullptr);
// Avoid wrapping a single blob inside an DOMMultipartFileImpl
@ -86,7 +88,7 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
return firstBlob.forget();
}
blobs.AppendElement(firstBlob);
blobImpls.AppendElement(static_cast<DOMFile*>(firstBlob.get())->Impl());
length -= upperBound;
i++;
break;
@ -95,29 +97,29 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
}
// Now append enough blobs until we're done
for (; length && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
for (; length && i < mBlobImpls.Length(); i++) {
DOMFileImpl* blobImpl = mBlobImpls[i].get();
uint64_t l;
nsresult rv = blob->GetSize(&l);
nsresult rv = blobImpl->GetSize(&l);
NS_ENSURE_SUCCESS(rv, nullptr);
if (length < l) {
nsCOMPtr<nsIDOMBlob> lastBlob;
rv = blob->Slice(0, length, aContentType, 3,
getter_AddRefs(lastBlob));
rv = blobImpl->Slice(0, length, aContentType, 3,
getter_AddRefs(lastBlob));
NS_ENSURE_SUCCESS(rv, nullptr);
blobs.AppendElement(lastBlob);
blobImpls.AppendElement(static_cast<DOMFile*>(lastBlob.get())->Impl());
} else {
blobs.AppendElement(blob);
blobImpls.AppendElement(blobImpl);
}
length -= std::min<uint64_t>(l, length);
}
// we can create our blob now
nsCOMPtr<nsIDOMBlob> blob =
new DOMFile(new DOMMultipartFileImpl(blobs, aContentType));
new DOMFile(new DOMMultipartFileImpl(blobImpls, aContentType));
return blob.forget();
}
@ -225,13 +227,16 @@ DOMMultipartFileImpl::ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue,
JS::Rooted<JSObject*> obj(aCx, &element.toObject());
nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, obj);
if (blob) {
nsRefPtr<DOMFileImpl> blobImpl =
static_cast<DOMFile*>(blob.get())->Impl();
// Flatten so that multipart blobs will never nest
DOMFile* file = static_cast<DOMFile*>(static_cast<nsIDOMBlob*>(blob));
const nsTArray<nsCOMPtr<nsIDOMBlob>>* subBlobs = file->GetSubBlobs();
if (subBlobs) {
blobSet.AppendBlobs(*subBlobs);
const nsTArray<nsRefPtr<DOMFileImpl>>* subBlobImpls =
blobImpl->GetSubBlobImpls();
if (subBlobImpls) {
blobSet.AppendBlobImpls(*subBlobImpls);
} else {
blobSet.AppendBlob(blob);
blobSet.AppendBlobImpl(blobImpl);
}
continue;
}
@ -257,7 +262,7 @@ DOMMultipartFileImpl::ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue,
NS_ENSURE_SUCCESS(rv, rv);
}
mBlobs = blobSet.GetBlobs();
mBlobImpls = blobSet.GetBlobImpls();
SetLengthAndModifiedDate();
@ -272,18 +277,12 @@ DOMMultipartFileImpl::SetLengthAndModifiedDate()
uint64_t totalLength = 0;
for (uint32_t index = 0, count = mBlobs.Length(); index < count; index++) {
nsCOMPtr<nsIDOMBlob>& blob = mBlobs[index];
for (uint32_t index = 0, count = mBlobImpls.Length(); index < count; index++) {
nsRefPtr<DOMFileImpl>& blob = mBlobImpls[index];
#ifdef DEBUG
{
// XXX This is only safe so long as all blob implementations in our tree
// inherit nsDOMFileBase.
const auto* blobBase = static_cast<DOMFile*>(blob.get());
MOZ_ASSERT(!blobBase->IsSizeUnknown());
MOZ_ASSERT(!blobBase->IsDateUnknown());
}
MOZ_ASSERT(!blob->IsSizeUnknown());
MOZ_ASSERT(!blob->IsDateUnknown());
#endif
uint64_t subBlobLength;
@ -303,17 +302,16 @@ DOMMultipartFileImpl::SetLengthAndModifiedDate()
nsresult
DOMMultipartFileImpl::GetMozFullPathInternal(nsAString& aFilename)
{
if (!mIsFromNsiFile || mBlobs.Length() == 0) {
if (!mIsFromNsiFile || mBlobImpls.Length() == 0) {
return DOMFileImplBase::GetMozFullPathInternal(aFilename);
}
nsIDOMBlob* blob = mBlobs.ElementAt(0).get();
if (!blob) {
DOMFileImpl* blobImpl = mBlobImpls.ElementAt(0).get();
if (!blobImpl) {
return DOMFileImplBase::GetMozFullPathInternal(aFilename);
}
DOMFile* domFile = static_cast<DOMFile*>(blob);
return domFile->GetMozFullPathInternal(aFilename);
return blobImpl->GetMozFullPathInternal(aFilename);
}
nsresult
@ -412,8 +410,8 @@ DOMMultipartFileImpl::InitChromeFile(JSContext* aCx,
}
BlobSet blobSet;
blobSet.AppendBlob(blob);
mBlobs = blobSet.GetBlobs();
blobSet.AppendBlobImpl(static_cast<DOMFile*>(blob.get())->Impl());
mBlobImpls = blobSet.GetBlobImpls();
SetLengthAndModifiedDate();
@ -496,21 +494,21 @@ BlobSet::AppendString(JSString* aString, bool nativeEOL, JSContext* aCx)
}
nsresult
BlobSet::AppendBlob(nsIDOMBlob* aBlob)
BlobSet::AppendBlobImpl(DOMFileImpl* aBlobImpl)
{
NS_ENSURE_ARG_POINTER(aBlob);
NS_ENSURE_ARG_POINTER(aBlobImpl);
Flush();
mBlobs.AppendElement(aBlob);
mBlobImpls.AppendElement(aBlobImpl);
return NS_OK;
}
nsresult
BlobSet::AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob)
BlobSet::AppendBlobImpls(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls)
{
Flush();
mBlobs.AppendElements(aBlob);
mBlobImpls.AppendElements(aBlobImpls);
return NS_OK;
}

View File

@ -20,25 +20,29 @@
{ 0x94, 0x96, 0xdf, 0x5d, 0x6f, 0xcd, 0xd7, 0x8f } }
#define NS_DOMMULTIPARTFILE_CONTRACTID "@mozilla.org/dom/multipart-file;1"
class DOMMultipartFileImpl MOZ_FINAL : public mozilla::dom::DOMFileImplBase
using namespace mozilla::dom;
class DOMMultipartFileImpl MOZ_FINAL : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
// Create as a file
DOMMultipartFileImpl(const nsTArray<nsCOMPtr<nsIDOMBlob>>& aBlobs,
DOMMultipartFileImpl(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls,
const nsAString& aName,
const nsAString& aContentType)
: mozilla::dom::DOMFileImplBase(aName, aContentType, UINT64_MAX),
mBlobs(aBlobs),
: DOMFileImplBase(aName, aContentType, UINT64_MAX),
mBlobImpls(aBlobImpls),
mIsFromNsiFile(false)
{
SetLengthAndModifiedDate();
}
// Create as a blob
DOMMultipartFileImpl(const nsTArray<nsCOMPtr<nsIDOMBlob>>& aBlobs,
DOMMultipartFileImpl(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls,
const nsAString& aContentType)
: mozilla::dom::DOMFileImplBase(aContentType, UINT64_MAX),
mBlobs(aBlobs),
: DOMFileImplBase(aContentType, UINT64_MAX),
mBlobImpls(aBlobImpls),
mIsFromNsiFile(false)
{
SetLengthAndModifiedDate();
@ -46,14 +50,14 @@ public:
// Create as a file to be later initialized
explicit DOMMultipartFileImpl(const nsAString& aName)
: mozilla::dom::DOMFileImplBase(aName, EmptyString(), UINT64_MAX),
: DOMFileImplBase(aName, EmptyString(), UINT64_MAX),
mIsFromNsiFile(false)
{
}
// Create as a blob to be later initialized
DOMMultipartFileImpl()
: mozilla::dom::DOMFileImplBase(EmptyString(), UINT64_MAX),
: DOMFileImplBase(EmptyString(), UINT64_MAX),
mIsFromNsiFile(false)
{
}
@ -96,9 +100,9 @@ public:
return NewFile(EmptyString(), aNewObject);
}
virtual const nsTArray<nsCOMPtr<nsIDOMBlob>>* GetSubBlobs() const MOZ_OVERRIDE
virtual const nsTArray<nsRefPtr<DOMFileImpl>>* GetSubBlobImpls() const MOZ_OVERRIDE
{
return &mBlobs;
return &mBlobImpls;
}
virtual nsresult GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
@ -109,7 +113,7 @@ protected:
void SetLengthAndModifiedDate();
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
nsTArray<nsRefPtr<DOMFileImpl>> mBlobImpls;
bool mIsFromNsiFile;
};
@ -126,17 +130,17 @@ public:
nsresult AppendVoidPtr(const void* aData, uint32_t aLength);
nsresult AppendString(JSString* aString, bool nativeEOL, JSContext* aCx);
nsresult AppendBlob(nsIDOMBlob* aBlob);
nsresult AppendBlobImpl(DOMFileImpl* aBlobImpl);
nsresult AppendArrayBuffer(JSObject* aBuffer);
nsresult AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob);
nsresult AppendBlobImpls(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls);
nsTArray<nsCOMPtr<nsIDOMBlob> >& GetBlobs() { Flush(); return mBlobs; }
nsTArray<nsRefPtr<DOMFileImpl>>& GetBlobImpls() { Flush(); return mBlobImpls; }
already_AddRefed<nsIDOMBlob>
GetBlobInternal(const nsACString& aContentType)
{
nsCOMPtr<nsIDOMBlob> blob = new mozilla::dom::DOMFile(
new DOMMultipartFileImpl(GetBlobs(), NS_ConvertASCIItoUTF16(aContentType)));
nsCOMPtr<nsIDOMBlob> blob = new DOMFile(
new DOMMultipartFileImpl(GetBlobImpls(), NS_ConvertASCIItoUTF16(aContentType)));
return blob.forget();
}
@ -174,16 +178,16 @@ protected:
// If we have some data, create a blob for it
// and put it on the stack
nsCOMPtr<nsIDOMBlob> blob =
mozilla::dom::DOMFile::CreateMemoryFile(mData, mDataLen, EmptyString());
mBlobs.AppendElement(blob);
nsRefPtr<DOMFileImpl> blobImpl =
new DOMFileImplMemory(mData, mDataLen, EmptyString());
mBlobImpls.AppendElement(blobImpl);
mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
}
}
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
nsTArray<nsRefPtr<DOMFileImpl>> mBlobImpls;
void* mData;
uint64_t mDataLen;
uint64_t mDataBufferLen;

View File

@ -125,7 +125,19 @@ nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
////////////////////////////////////////////////////////////////////////////
// mozilla::dom::DOMFile implementation
NS_INTERFACE_MAP_BEGIN(DOMFile)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMFile)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMFile)
MOZ_ASSERT(tmp->mImpl);
tmp->mImpl->Unlink();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMFile)
MOZ_ASSERT(tmp->mImpl);
tmp->mImpl->Traverse(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMFile)
// This class should not receive any nsIRemoteBlob QI!
MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsIRemoteBlob)));
@ -139,8 +151,8 @@ NS_INTERFACE_MAP_BEGIN(DOMFile)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !(IsFile()))
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(DOMFile)
NS_IMPL_RELEASE(DOMFile)
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMFile)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMFile)
/* static */ already_AddRefed<DOMFile>
DOMFile::Create(const nsAString& aName, const nsAString& aContentType,
@ -251,99 +263,96 @@ DOMFile::CreateFromFile(nsIFile* aFile, const nsAString& aName,
return file.forget();
}
////////////////////////////////////////////////////////////////////////////
// mozilla::dom::DOMFileBase implementation
const nsTArray<nsCOMPtr<nsIDOMBlob>>*
DOMFileBase::GetSubBlobs() const
const nsTArray<nsRefPtr<DOMFileImpl>>*
DOMFile::GetSubBlobImpls() const
{
return mImpl->GetSubBlobs();
return mImpl->GetSubBlobImpls();
}
bool
DOMFileBase::IsSizeUnknown() const
DOMFile::IsSizeUnknown() const
{
return mImpl->IsSizeUnknown();
}
bool
DOMFileBase::IsDateUnknown() const
DOMFile::IsDateUnknown() const
{
return mImpl->IsDateUnknown();
}
bool
DOMFileBase::IsFile() const
DOMFile::IsFile() const
{
return mImpl->IsFile();
}
void
DOMFileBase::SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, uint64_t aLastModifiedDate)
DOMFile::SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, uint64_t aLastModifiedDate)
{
return mImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
}
already_AddRefed<nsIDOMBlob>
DOMFileBase::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
DOMFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
return mImpl->CreateSlice(aStart, aLength, aContentType);
}
NS_IMETHODIMP
DOMFileBase::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
const JS::CallArgs& aArgs)
DOMFile::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
const JS::CallArgs& aArgs)
{
return mImpl->Initialize(aOwner, aCx, aObj, aArgs);
}
NS_IMETHODIMP
DOMFileBase::GetName(nsAString& aFileName)
DOMFile::GetName(nsAString& aFileName)
{
return mImpl->GetName(aFileName);
}
NS_IMETHODIMP
DOMFileBase::GetPath(nsAString& aPath)
DOMFile::GetPath(nsAString& aPath)
{
return mImpl->GetPath(aPath);
}
NS_IMETHODIMP
DOMFileBase::GetLastModifiedDate(JSContext* aCx,
JS::MutableHandle<JS::Value> aDate)
DOMFile::GetLastModifiedDate(JSContext* aCx,
JS::MutableHandle<JS::Value> aDate)
{
return mImpl->GetLastModifiedDate(aCx, aDate);
}
NS_IMETHODIMP
DOMFileBase::GetMozFullPath(nsAString &aFileName)
DOMFile::GetMozFullPath(nsAString &aFileName)
{
return mImpl->GetMozFullPath(aFileName);
}
NS_IMETHODIMP
DOMFileBase::GetMozFullPathInternal(nsAString &aFileName)
DOMFile::GetMozFullPathInternal(nsAString &aFileName)
{
return mImpl->GetMozFullPathInternal(aFileName);
}
NS_IMETHODIMP
DOMFileBase::GetSize(uint64_t* aSize)
DOMFile::GetSize(uint64_t* aSize)
{
return mImpl->GetSize(aSize);
}
NS_IMETHODIMP
DOMFileBase::GetType(nsAString &aType)
DOMFile::GetType(nsAString &aType)
{
return mImpl->GetType(aType);
}
NS_IMETHODIMP
DOMFileBase::GetMozLastModifiedDate(uint64_t* aDate)
DOMFile::GetMozLastModifiedDate(uint64_t* aDate)
{
return mImpl->GetMozLastModifiedDate(aDate);
}
@ -386,67 +395,67 @@ ParseSize(int64_t aSize, int64_t& aStart, int64_t& aEnd)
}
NS_IMETHODIMP
DOMFileBase::Slice(int64_t aStart, int64_t aEnd,
const nsAString& aContentType, uint8_t aArgc,
nsIDOMBlob **aBlob)
DOMFile::Slice(int64_t aStart, int64_t aEnd,
const nsAString& aContentType, uint8_t aArgc,
nsIDOMBlob **aBlob)
{
MOZ_ASSERT(mImpl);
return mImpl->Slice(aStart, aEnd, aContentType, aArgc, aBlob);
}
NS_IMETHODIMP
DOMFileBase::GetInternalStream(nsIInputStream** aStream)
DOMFile::GetInternalStream(nsIInputStream** aStream)
{
return mImpl->GetInternalStream(aStream);
}
NS_IMETHODIMP
DOMFileBase::GetInternalUrl(nsIPrincipal* aPrincipal, nsAString& aURL)
DOMFile::GetInternalUrl(nsIPrincipal* aPrincipal, nsAString& aURL)
{
return mImpl->GetInternalUrl(aPrincipal, aURL);
}
NS_IMETHODIMP_(int64_t)
DOMFileBase::GetFileId()
DOMFile::GetFileId()
{
return mImpl->GetFileId();
}
NS_IMETHODIMP_(void)
DOMFileBase::AddFileInfo(indexedDB::FileInfo* aFileInfo)
DOMFile::AddFileInfo(indexedDB::FileInfo* aFileInfo)
{
mImpl->AddFileInfo(aFileInfo);
}
indexedDB::FileInfo*
DOMFileBase::GetFileInfo(indexedDB::FileManager* aFileManager)
DOMFile::GetFileInfo(indexedDB::FileManager* aFileManager)
{
return mImpl->GetFileInfo(aFileManager);
}
NS_IMETHODIMP
DOMFileBase::GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset)
DOMFile::GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset)
{
return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
}
NS_IMETHODIMP
DOMFileBase::GetMutable(bool* aMutable)
DOMFile::GetMutable(bool* aMutable)
{
return mImpl->GetMutable(aMutable);
}
NS_IMETHODIMP
DOMFileBase::SetMutable(bool aMutable)
DOMFile::SetMutable(bool aMutable)
{
return mImpl->SetMutable(aMutable);
}
NS_IMETHODIMP_(bool)
DOMFileBase::IsMemoryFile()
DOMFile::IsMemoryFile()
{
return mImpl->IsMemoryFile();
}
@ -481,7 +490,14 @@ DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
}
////////////////////////////////////////////////////////////////////////////
// DOMFileImplBase implementation
// DOMFileImpl implementation
NS_IMPL_ISUPPORTS(DOMFileImpl, PIDOMFileImpl)
////////////////////////////////////////////////////////////////////////////
// DOMFileImplFile implementation
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplFile, DOMFileImpl)
nsresult
DOMFileImplBase::GetName(nsAString& aName)
@ -727,35 +743,6 @@ DOMFileImplBase::SetMutable(bool aMutable)
return rv;
}
NS_IMPL_ISUPPORTS0(DOMFileImplBase)
////////////////////////////////////////////////////////////////////////////
// DOMFileCC implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMFileCC)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMFileCC)
tmp->mImpl->Unlink();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMFileCC)
tmp->mImpl->Traverse(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMFileCC)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, IsFile())
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, IsFile())
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !(IsFile()))
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMFileCC)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMFileCC)
////////////////////////////////////////////////////////////////////////////
// DOMFileImplFile implementation
@ -890,6 +877,8 @@ DOMFileImplFile::SetPath(const nsAString& aPath)
////////////////////////////////////////////////////////////////////////////
// DOMFileImplMemory implementation
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplMemory, DOMFileImpl)
already_AddRefed<nsIDOMBlob>
DOMFileImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
@ -1013,6 +1002,8 @@ DOMFileImplMemory::DataOwner::EnsureMemoryReporterRegistered()
////////////////////////////////////////////////////////////////////////////
// DOMFileImplTemporaryFileBlob implementation
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplTemporaryFileBlob, DOMFileImpl)
already_AddRefed<nsIDOMBlob>
DOMFileImplTemporaryFileBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)

View File

@ -10,12 +10,14 @@
#include "nsClassHashtable.h"
#include "nsNetUtil.h"
#include "nsIPrincipal.h"
#include "nsIDOMFile.h"
#include "nsDOMFile.h"
#include "nsIDOMMediaStream.h"
#include "mozilla/dom/MediaSource.h"
#include "nsIMemoryReporter.h"
#include "mozilla/Preferences.h"
using mozilla::dom::DOMFileImpl;
// -----------------------------------------------------------------------
// Hash table
struct DataInfo
@ -478,8 +480,9 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
if (!info) {
return NS_ERROR_DOM_BAD_URI;
}
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
if (!blob) {
nsCOMPtr<PIDOMFileImpl> blobImpl = do_QueryInterface(info->mObject);
if (!blobImpl) {
return NS_ERROR_DOM_BAD_URI;
}
@ -492,6 +495,7 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
}
#endif
DOMFileImpl* blob = static_cast<DOMFileImpl*>(blobImpl.get());
nsCOMPtr<nsIInputStream> stream;
nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, rv);
@ -508,10 +512,9 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
rv = blob->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
if (file) {
if (blob->IsFile()) {
nsString filename;
rv = file->GetName(filename);
rv = blob->GetName(filename);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetContentDispositionFilename(filename);
}
@ -574,11 +577,12 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
*aStream = nullptr;
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(GetDataObject(aURI));
if (!blob) {
nsCOMPtr<PIDOMFileImpl> blobImpl = do_QueryInterface(GetDataObject(aURI));
if (!blobImpl) {
return NS_ERROR_DOM_BAD_URI;
}
DOMFileImpl* blob = static_cast<DOMFileImpl*>(blobImpl.get());
return blob->GetInternalStream(aStream);
}

View File

@ -542,7 +542,7 @@ WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
// a texture might be attached more that once while editing the framebuffer
}
}
@ -560,8 +560,8 @@ WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
{
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[0].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
if (mColorAttachments[i].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
// a renderbuffer might be attached more that once while editing the framebuffer
}
}

View File

@ -11,5 +11,7 @@ conformance/limits/gl-min-textures.html
conformance/misc/error-reporting.html
conformance/misc/object-deletion-behaviour.html
conformance/misc/type-conversion-test.html
conformance/reading/read-pixels-test.html
conformance/renderbuffers/framebuffer-object-attachment.html
conformance/textures/tex-image-and-sub-image-2d-with-video.html
conformance/textures/texture-npot-video.html

View File

@ -532,6 +532,10 @@ function start() {
failingTestsFilename = 'failing_tests_android_x86.txt';
skippedTestsFilename = 'skipped_tests_android_x86.txt';
break;
case GLDRIVER_MESA:
failingTestsFilename = 'failing_tests_android_x86.txt';
skippedTestsFilename = 'skipped_tests_android_x86.txt';
break;
default:
failingTestsFilename = 'failing_tests_android.txt';
skippedTestsFilename = 'skipped_tests_android.txt';

View File

@ -457,13 +457,13 @@ MP4Reader::Flush(TrackType aTrack)
// Set a flag so that we ignore all output while we call
// MediaDataDecoder::Flush().
{
data.mIsFlushing = true;
MonitorAutoLock mon(data.mMonitor);
data.mIsFlushing = true;
}
data.mDecoder->Flush();
{
data.mIsFlushing = false;
MonitorAutoLock mon(data.mMonitor);
data.mIsFlushing = false;
}
}

View File

@ -466,7 +466,8 @@ nsresult
MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
int64_t aCurrentTime)
{
if (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)) {
double target = static_cast<double>(aTime) / USECS_PER_S;
if (!mMediaSource->ActiveSourceBuffers()->AllContainsTime(target)) {
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
}
@ -474,7 +475,7 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
// This is a workaround for our lack of async functionality in the
// MediaDecoderStateMachine. Bug 979104 implements what we need and
// we'll remove this for an async approach based on that in bug XXXXXXX.
while (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)
while (!mMediaSource->ActiveSourceBuffers()->AllContainsTime(target)
&& !IsShutdown()) {
mMediaSource->WaitForData();
MaybeSwitchVideoReaders();

View File

@ -187,6 +187,7 @@ support-files =
owl-funny-id3.mp3^headers^
owl.mp3
owl.mp3^headers^
parser.vtt
r11025_msadpcm_c1.wav
r11025_msadpcm_c1.wav^headers^
r11025_s16_c1.wav
@ -447,6 +448,7 @@ skip-if = buildapp == 'b2g' # bug 1021682
[test_VideoPlaybackQuality.html]
[test_VideoPlaybackQuality_disabled.html]
[test_volume.html]
[test_vttparser.html]
[test_webvtt_disabled.html]

View File

@ -0,0 +1,6 @@
WEBVTT
00:00.500 --> 00:00.700
Test
00:00.500 --> 00:00.700
Stuff

View File

@ -58,7 +58,7 @@ function startTest(test, token) {
is(evt.data.type, expectedMimeType,
'Blob data received should have type = ' + expectedMimeType);
is(mediaRecorder.mimeType, expectedMimeType,
'Mime type in ondataavailable = ' + expectedMimeType);
'Mime type in ondataavailable = ' + mediaRecorder.mimeType);
// We'll stop recording upon the 1st blob being received
if (dataAvailableCount === 1) {

View File

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<title>WebVTT Parser Regression Tests</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
function() {
var video = document.createElement("video");
video.src = "seek.webm";
video.preload = "auto";
var trackElement = document.createElement("track");
trackElement.src = "parser.vtt";
trackElement.kind = "subtitles";
trackElement.default = true;
document.getElementById("content").appendChild(video);
video.appendChild(trackElement);
video.addEventListener("loadedmetadata", function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
is(trackElement.track.cues.length, 2, "Track should have two Cues.");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

View File

@ -8,7 +8,7 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
* Code below is vtt.js the JS WebVTT implementation.
* Current source code can be found at http://github.com/mozilla/vtt.js
*
* Code taken from commit 65ae2daaf6ec7e710f591214893bb03d8b7a94b5
* Code taken from commit f5a1a60775a615cd9670d6cdaedddf2c6f25fae3
*/
/**
* Copyright 2013 vtt.js Contributors
@ -29,7 +29,7 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
(function(global) {
_objCreate = Object.create || (function() {
var _objCreate = Object.create || (function() {
function F() {}
return function(o) {
if (arguments.length !== 1) {
@ -165,11 +165,14 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
}
function parseCue(input, cue, regionList) {
// Remember the original input if we need to throw an error.
var oInput = input;
// 4.1 WebVTT timestamp
function consumeTimeStamp() {
var ts = parseTimeStamp(input);
if (ts === null) {
throw new ParsingError(ParsingError.Errors.BadTimeStamp);
throw new ParsingError(ParsingError.Errors.BadTimeStamp,
"Malformed timestamp: " + oInput);
}
// Remove time stamp from input.
input = input.replace(/^[^\sa-zA-Z-]+/, "");
@ -254,7 +257,8 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
skipWhitespace();
if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
throw new ParsingError(ParsingError.Errors.BadTimeStamp,
"Malformed time stamp (time stamps must be separated by '-->').");
"Malformed time stamp (time stamps must be separated by '-->'): " +
oInput);
}
input = input.substr(3);
skipWhitespace();
@ -1304,13 +1308,18 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
self.state = "HEADER";
}
var alreadyCollectedLine = false;
while (self.buffer) {
// We can't parse a line until we have the full line.
if (!/\r\n|\n/.test(self.buffer)) {
return this;
}
line = collectNextLine();
if (!alreadyCollectedLine) {
line = collectNextLine();
} else {
alreadyCollectedLine = false;
}
switch (self.state) {
case "HEADER":
@ -1361,8 +1370,12 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
self.state = "CUETEXT";
continue;
case "CUETEXT":
// 41-53 - Collect the cue text, create a cue, and add it to the output.
if (!line) {
var hasSubstring = line.indexOf("-->") !== -1;
// 34 - If we have an empty line then report the cue.
// 35 - If we have the special substring '-->' then report the cue,
// but do not collect the line as we need to process the current
// one as a new cue.
if (!line || hasSubstring && (alreadyCollectedLine = true)) {
// We are done parsing self cue.
self.oncue && self.oncue(self.cue);
self.cue = null;

View File

@ -52,6 +52,7 @@ const kMessages =["Webapps:Connect",
this.InterAppCommService = {
init: function() {
Services.obs.addObserver(this, "xpcom-shutdown", false);
Services.obs.addObserver(this, "webapps-clear-data", false);
kMessages.forEach(function(aMsg) {
ppmm.addMessageListener(aMsg, this);
@ -932,11 +933,80 @@ this.InterAppCommService = {
switch (aTopic) {
case "xpcom-shutdown":
Services.obs.removeObserver(this, "xpcom-shutdown");
Services.obs.removeObserver(this, "webapps-clear-data");
kMessages.forEach(function(aMsg) {
ppmm.removeMessageListener(aMsg, this);
}, this);
ppmm = null;
break;
case "webapps-clear-data":
let params =
aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams);
if (!params) {
if (DEBUG) {
debug("Error updating registered/allowed connections for an " +
"uninstalled app.");
}
return;
}
// Only update registered/allowed connections for apps.
if (params.browserOnly) {
if (DEBUG) {
debug("Only update registered/allowed connections for apps.");
}
return;
}
let manifestURL = appsService.getManifestURLByLocalId(params.appId);
if (!manifestURL) {
if (DEBUG) {
debug("Error updating registered/allowed connections for an " +
"uninstalled app.");
}
return;
}
// Update registered connections.
for (let keyword in this._registeredConnections) {
let subAppManifestURLs = this._registeredConnections[keyword];
if (subAppManifestURLs[manifestURL]) {
delete subAppManifestURLs[manifestURL];
if (DEBUG) {
debug("Remove " + manifestURL + " from registered connections " +
"due to app uninstallation.");
}
}
}
// Update allowed connections.
for (let keyword in this._allowedConnections) {
let allowedPubAppManifestURLs = this._allowedConnections[keyword];
if (allowedPubAppManifestURLs[manifestURL]) {
delete allowedPubAppManifestURLs[manifestURL];
if (DEBUG) {
debug("Remove " + manifestURL + " (as a pub app) from allowed " +
"connections due to app uninstallation.");
}
}
for (let pubAppManifestURL in allowedPubAppManifestURLs) {
let subAppManifestURLs = allowedPubAppManifestURLs[pubAppManifestURL];
for (let i = subAppManifestURLs.length - 1; i >= 0; i--) {
if (subAppManifestURLs[i] === manifestURL) {
subAppManifestURLs.splice(i, 1);
if (DEBUG) {
debug("Remove " + manifestURL + " (as a sub app to pub " +
pubAppManifestURL + ") from allowed connections " +
"due to app uninstallation.");
}
}
}
}
}
debug("Finish updating registered/allowed connections for an " +
"uninstalled app.");
break;
}
}
};

View File

@ -84,7 +84,7 @@ ArchiveZipItem::File(ArchiveReader* aArchiveReader)
return nullptr;
}
return new DOMFileCC(
return new DOMFile(
new ArchiveZipFileImpl(filename,
NS_ConvertUTF8toUTF16(GetType()),
StrToInt32(mCentralStruct.orglen),

View File

@ -402,8 +402,10 @@ ArchiveZipFileImpl::CreateSlice(uint64_t aStart,
const nsAString& aContentType)
{
nsCOMPtr<nsIDOMBlob> t =
new DOMFileCC(new ArchiveZipFileImpl(mFilename, mContentType,
aStart, mLength, mCentral,
mArchiveReader));
new DOMFile(new ArchiveZipFileImpl(mFilename, mContentType,
aStart, mLength, mCentral,
mArchiveReader));
return t.forget();
}
NS_IMPL_ISUPPORTS_INHERITED0(ArchiveZipFileImpl, DOMFileImpl)

View File

@ -23,6 +23,8 @@ BEGIN_ARCHIVEREADER_NAMESPACE
class ArchiveZipFileImpl : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
ArchiveZipFileImpl(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
@ -63,6 +65,11 @@ public:
virtual void Unlink() MOZ_OVERRIDE;
virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) MOZ_OVERRIDE;
virtual bool IsCCed() const MOZ_OVERRIDE
{
return true;
}
protected:
virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart,
uint64_t aLength,

View File

@ -6,7 +6,7 @@
#include "URL.h"
#include "nsGlobalWindow.h"
#include "nsIDOMFile.h"
#include "nsDOMFile.h"
#include "DOMMediaStream.h"
#include "mozilla/dom/MediaSource.h"
#include "mozilla/dom/URLBinding.h"
@ -116,7 +116,10 @@ URL::CreateObjectURL(const GlobalObject& aGlobal,
nsString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, aBlob,
DOMFile* blob = static_cast<DOMFile*>(aBlob);
MOZ_ASSERT(blob);
CreateObjectURLInternal(aGlobal, blob->Impl(),
NS_LITERAL_CSTRING(BLOBURI_SCHEME), aOptions, aResult,
aError);
}

View File

@ -2941,91 +2941,6 @@ nsDOMWindowUtils::AreDialogsEnabled(bool* aResult)
return NS_OK;
}
static nsIDOMBlob*
GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
return blob;
}
static nsresult
GetFileOrBlob(const nsAString& aName, JS::Handle<JS::Value> aBlobParts,
JS::Handle<JS::Value> aParameters, JSContext* aCx,
uint8_t aOptionalArgCount, nsISupports** aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsresult rv;
nsCOMPtr<nsISupports> file;
if (aName.IsVoid()) {
rv = DOMMultipartFileImpl::NewBlob(getter_AddRefs(file));
}
else {
rv = DOMMultipartFileImpl::NewFile(aName, getter_AddRefs(file));
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(file);
MOZ_ASSERT(blob);
nsRefPtr<DOMFile> domFile = static_cast<DOMFile*>(blob.get());
DOMFileImpl* fileImpl = domFile->Impl();
MOZ_ASSERT(fileImpl);
DOMMultipartFileImpl* domFileImpl =
static_cast<DOMMultipartFileImpl*>(fileImpl);
JS::AutoValueArray<2> args(aCx);
args[0].set(aBlobParts);
args[1].set(aParameters);
rv = domFileImpl->InitBlob(aCx, aOptionalArgCount, args.begin(),
GetXPConnectNative);
NS_ENSURE_SUCCESS(rv, rv);
file.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetFile(const nsAString& aName, JS::Handle<JS::Value> aBlobParts,
JS::Handle<JS::Value> aParameters, JSContext* aCx,
uint8_t aOptionalArgCount, nsIDOMFile** aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsISupports> file;
nsresult rv = GetFileOrBlob(aName, aBlobParts, aParameters, aCx,
aOptionalArgCount, getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMFile> result = do_QueryInterface(file);
result.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetBlob(JS::Handle<JS::Value> aBlobParts,
JS::Handle<JS::Value> aParameters, JSContext* aCx,
uint8_t aOptionalArgCount, nsIDOMBlob** aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsISupports> blob;
nsresult rv = GetFileOrBlob(NullString(), aBlobParts, aParameters, aCx,
aOptionalArgCount, getter_AddRefs(blob));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMBlob> result = do_QueryInterface(blob);
result.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
int64_t* aResult)

View File

@ -7840,7 +7840,22 @@ PostMessageReadStructuredClone(JSContext* cx,
uint32_t data,
void* closure)
{
if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
if (tag == SCTAG_DOM_BLOB) {
NS_ASSERTION(!data, "Data should be empty");
// What we get back from the reader is a DOMFileImpl.
// From that we create a new DOMFile.
nsISupports* supports;
if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
nsCOMPtr<nsIDOMBlob> file = new DOMFile(static_cast<DOMFileImpl*>(supports));
JS::Rooted<JS::Value> val(cx);
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, file, &val))) {
return val.toObjectOrNull();
}
}
}
if (tag == SCTAG_DOM_FILELIST) {
NS_ASSERTION(!data, "Data should be empty");
nsISupports* supports;
@ -7879,8 +7894,11 @@ PostMessageWriteStructuredClone(JSContext* cx,
nsISupports* supports = wrappedNative->Native();
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
if (blob && scInfo->subsumes)
if (blob && scInfo->subsumes) {
scTag = SCTAG_DOM_BLOB;
DOMFile* file = static_cast<DOMFile*>(blob.get());
supports = file->Impl();
}
nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
if (list && scInfo->subsumes)
@ -11384,7 +11402,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
#endif // MOZ_B2G
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
MOZ_ASSERT(!nsCRT::strcmp(NS_ConvertUTF16toUTF8(aData).get(), "intl.accept_languages"));
MOZ_ASSERT(!NS_strcmp(aData, MOZ_UTF16("intl.accept_languages")));
MOZ_ASSERT(IsInnerWindow());
// The user preferred languages have changed, we need to fire an event on

View File

@ -40,14 +40,9 @@ function getRandomView(size)
return view;
}
function getBlob(type, view)
{
return SpecialPowers.unwrap(utils.getBlob([view], {type: type}));
}
function getRandomBlob(size)
{
return getBlob("binary/random", getRandomView(size));
return new Blob([getRandomView(size)], { type: "binary/random" });
}
function compareBuffers(buffer1, buffer2)

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/IDBDatabaseBinding.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/indexedDB/IDBDatabase.h"
#include "mozilla/dom/indexedDB/IDBEvents.h"
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/indexedDB/IDBIndex.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
@ -25,13 +26,59 @@ using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
class VersionChangeListener MOZ_FINAL : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
VersionChangeListener(IDBDatabase* aDatabase)
: mDatabase(aDatabase)
{}
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent)
{
nsString type;
nsresult rv = aEvent->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!type.EqualsASCII("versionchange")) {
MOZ_ASSUME_UNREACHABLE("This should not happen");
return NS_ERROR_FAILURE;
}
rv = mDatabase->RemoveEventListener(NS_LITERAL_STRING("versionchange"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
#ifdef DEBUG
nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent);
MOZ_ASSERT(event);
Nullable<uint64_t> version = event->GetNewVersion();
MOZ_ASSERT(version.IsNull());
#endif
return mDatabase->Close();
}
private:
IDBDatabase* mDatabase;
};
NS_IMPL_ISUPPORTS(VersionChangeListener, nsIDOMEventListener)
NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener)
DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName)
: mState(Inactive)
{
mDatabaseName.Assign(aName);
mDatabaseName.AppendASCII("|");
mDatabaseName.Append('|');
mDatabaseName.Append(aManifestURL);
}
@ -204,6 +251,14 @@ DataStoreDB::DatabaseOpened()
return rv;
}
nsRefPtr<VersionChangeListener> listener =
new VersionChangeListener(mDatabase);
rv = mDatabase->EventTarget::AddEventListener(
NS_LITERAL_STRING("versionchange"), listener, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<IDBTransaction> txn = mDatabase->Transaction(mObjectStores,
mTransactionMode,
error);

View File

@ -199,9 +199,9 @@ GeneratePermissionName(nsAString& aPermission,
const nsAString& aName,
const nsAString& aManifestURL)
{
aPermission.AssignASCII("indexedDB-chrome-");
aPermission.AssignLiteral("indexedDB-chrome-");
aPermission.Append(aName);
aPermission.AppendASCII("|");
aPermission.Append('|');
aPermission.Append(aManifestURL);
}
@ -252,7 +252,7 @@ ResetPermission(uint32_t aAppId, const nsAString& aOriginURL,
{
nsCString permission;
permission.Append(basePermission);
permission.AppendASCII("-write");
permission.AppendLiteral("-write");
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(),
@ -279,7 +279,7 @@ ResetPermission(uint32_t aAppId, const nsAString& aOriginURL,
{
nsCString permission;
permission.Append(basePermission);
permission.AppendASCII("-read");
permission.AppendLiteral("-read");
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(),
@ -616,9 +616,9 @@ public:
new RevisionAddedEnableStoreCallback(mAppId, mName, mManifestURL);
// If the revision doesn't exist, let's create it.
nsRefPtr<DataStoreRevision> mRevision = new DataStoreRevision();
return mRevision->AddRevision(cx, store, 0, DataStoreRevision::RevisionVoid,
callback);
nsRefPtr<DataStoreRevision> revision = new DataStoreRevision();
return revision->AddRevision(cx, store, 0, DataStoreRevision::RevisionVoid,
callback);
}
private:

View File

@ -2396,11 +2396,11 @@ private:
class WriteFileEvent : public nsRunnable
{
public:
WriteFileEvent(nsIDOMBlob* aBlob,
WriteFileEvent(DOMFileImpl* aBlobImpl,
DeviceStorageFile *aFile,
already_AddRefed<DOMRequest> aRequest,
int32_t aRequestType)
: mBlob(aBlob)
: mBlobImpl(aBlobImpl)
, mFile(aFile)
, mRequest(aRequest)
, mRequestType(aRequestType)
@ -2417,7 +2417,7 @@ public:
MOZ_ASSERT(!NS_IsMainThread());
nsCOMPtr<nsIInputStream> stream;
mBlob->GetInternalStream(getter_AddRefs(stream));
mBlobImpl->GetInternalStream(getter_AddRefs(stream));
bool check = false;
mFile->mFile->Exists(&check);
@ -2461,7 +2461,7 @@ public:
}
private:
nsCOMPtr<nsIDOMBlob> mBlob;
nsRefPtr<DOMFileImpl> mBlobImpl;
nsRefPtr<DeviceStorageFile> mFile;
nsRefPtr<DOMRequest> mRequest;
int32_t mRequestType;
@ -2887,7 +2887,10 @@ public:
->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK;
}
r = new WriteFileEvent(mBlob, mFile, mRequest.forget(), mRequestType);
DOMFile* blob = static_cast<DOMFile*>(mBlob.get());
r = new WriteFileEvent(blob->Impl(), mFile, mRequest.forget(),
mRequestType);
break;
}
@ -2929,7 +2932,10 @@ public:
->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK;
}
r = new WriteFileEvent(mBlob, mFile, mRequest.forget(), mRequestType);
DOMFile* blob = static_cast<DOMFile*>(mBlob.get());
r = new WriteFileEvent(blob->Impl(), mFile, mRequest.forget(),
mRequestType);
break;
}
@ -4228,9 +4234,9 @@ nsDOMDeviceStorage::Observe(nsISupports *aSubject,
// these notifications are specific for apps storage.
nsRefPtr<DeviceStorageFile> file =
new DeviceStorageFile(mStorageType, mStorageName);
if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "full")) {
if (!NS_strcmp(aData, MOZ_UTF16("full"))) {
Notify("low-disk-space", file);
} else if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "free")) {
} else if (!NS_strcmp(aData, MOZ_UTF16("free"))) {
Notify("available-disk-space", file);
}
return NS_OK;

View File

@ -15,6 +15,8 @@ namespace dom {
using indexedDB::IndexedDatabaseManager;
NS_IMPL_ISUPPORTS_INHERITED0(FileImpl, DOMFileImpl)
// Create as a file
FileImpl::FileImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile, FileHandle* aFileHandle)
@ -99,7 +101,7 @@ FileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIDOMBlob> t =
new DOMFileCC(new FileImpl(this, aStart, aLength, aContentType));
new DOMFile(new FileImpl(this, aStart, aLength, aContentType));
return t.forget();
}

View File

@ -24,6 +24,8 @@ class FileImpl : public DOMFileImplBase
friend class File;
public:
NS_DECL_ISUPPORTS_INHERITED
// Create as a file
FileImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile, FileHandle* aFileHandle);
@ -41,6 +43,11 @@ public:
virtual void Unlink() MOZ_OVERRIDE;
virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) MOZ_OVERRIDE;
virtual bool IsCCed() const MOZ_OVERRIDE
{
return true;
}
protected:
// Create slice
FileImpl(const FileImpl* aOther, uint64_t aStart, uint64_t aLength,

View File

@ -106,7 +106,7 @@ already_AddRefed<nsIDOMFile>
MutableFile::CreateFileObject(FileHandle* aFileHandle, uint32_t aFileSize)
{
nsCOMPtr<nsIDOMFile> file =
new DOMFileCC(new FileImpl(mName, mType, aFileSize, mFile, aFileHandle));
new DOMFile(new FileImpl(mName, mType, aFileSize, mFile, aFileHandle));
return file.forget();
}

View File

@ -194,14 +194,9 @@ function compareBuffers(buffer1, buffer2)
return true;
}
function getBlob(type, buffer)
{
return SpecialPowers.unwrap(utils.getBlob([buffer], {type: type}));
}
function getRandomBlob(size)
{
return getBlob("binary/random", getRandomBuffer(size));
return new Blob([getRandomBuffer(size)], { type: "binary/random" });
}
function getFileId(blob)

View File

@ -19,7 +19,7 @@
var testBuffer = getRandomBuffer(100000);
var testBlob = getBlob("binary/random", testBuffer);
var testBlob = new Blob([testBuffer], {type: "binary/random"});
for each (let fileStorage in fileStorages) {
let request = getMutableFile(fileStorage.key, "test.txt");

View File

@ -19,7 +19,7 @@
var testBuffer = getRandomBuffer(100000);
var testBlob = getBlob("binary/random", testBuffer);
var testBlob = new Blob([testBuffer], {type: "binary/random"});
for each (let fileStorage in fileStorages) {
let request = getMutableFile(fileStorage.key, "test.txt");

View File

@ -119,7 +119,8 @@ FileSystemResponseValue
CreateFileTask::GetSuccessRequestResult() const
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
BlobParent* actor = GetBlobParent(mTargetFile);
nsRefPtr<DOMFile> file = new DOMFile(mTargetFileImpl);
BlobParent* actor = GetBlobParent(file);
if (!actor) {
return FileSystemErrorResponse(NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR);
}
@ -135,7 +136,7 @@ CreateFileTask::SetSuccessRequestResult(const FileSystemResponseValue& aValue)
FileSystemFileResponse r = aValue;
BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
mTargetFile = do_QueryInterface(blob);
mTargetFileImpl = static_cast<DOMFile*>(blob.get())->Impl();
}
nsresult
@ -252,7 +253,7 @@ CreateFileTask::Work()
return NS_ERROR_FAILURE;
}
mTargetFile = DOMFile::CreateFromFile(file);
mTargetFileImpl = new DOMFileImplFile(file);
return NS_OK;
}
@ -271,7 +272,7 @@ CreateFileTask::Work()
return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
}
mTargetFile = DOMFile::CreateFromFile(file);
mTargetFileImpl = new DOMFileImplFile(file);
return NS_OK;
}
@ -292,7 +293,8 @@ CreateFileTask::HandlerCallback()
return;
}
mPromise->MaybeResolve(mTargetFile);
nsCOMPtr<nsIDOMFile> file = new DOMFile(mTargetFileImpl);
mPromise->MaybeResolve(file);
mPromise = nullptr;
}

View File

@ -16,6 +16,7 @@ class nsIInputStream;
namespace mozilla {
namespace dom {
class DOMFileImpl;
class Promise;
class CreateFileTask MOZ_FINAL
@ -67,7 +68,10 @@ private:
nsCOMPtr<nsIInputStream> mBlobStream;
InfallibleTArray<uint8_t> mArrayData;
bool mReplace;
nsCOMPtr<nsIDOMFile> mTargetFile;
// This cannot be a DOMFile bacause this object is created on a different
// thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
nsRefPtr<DOMFileImpl> mTargetFileImpl;
};
} // namespace dom

View File

@ -77,7 +77,9 @@ GetFileOrDirectoryTask::GetSuccessRequestResult() const
if (mIsDirectory) {
return FileSystemDirectoryResponse(mTargetRealPath);
}
BlobParent* actor = GetBlobParent(mTargetFile);
nsRefPtr<DOMFile> file = new DOMFile(mTargetFileImpl);
BlobParent* actor = GetBlobParent(file);
if (!actor) {
return FileSystemErrorResponse(NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR);
}
@ -95,7 +97,7 @@ GetFileOrDirectoryTask::SetSuccessRequestResult(const FileSystemResponseValue& a
FileSystemFileResponse r = aValue;
BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
mTargetFile = do_QueryInterface(blob);
mTargetFileImpl = static_cast<DOMFile*>(blob.get())->Impl();
mIsDirectory = false;
break;
}
@ -180,7 +182,7 @@ GetFileOrDirectoryTask::Work()
return NS_ERROR_DOM_SECURITY_ERR;
}
mTargetFile = DOMFile::CreateFromFile(file);
mTargetFileImpl = new DOMFileImplFile(file);
return NS_OK;
}
@ -209,7 +211,8 @@ GetFileOrDirectoryTask::HandlerCallback()
return;
}
mPromise->MaybeResolve(mTargetFile);
nsCOMPtr<nsIDOMFile> file = new DOMFile(mTargetFileImpl);
mPromise->MaybeResolve(file);
mPromise = nullptr;
}

View File

@ -13,6 +13,8 @@
namespace mozilla {
namespace dom {
class DOMFileImpl;
class GetFileOrDirectoryTask MOZ_FINAL
: public FileSystemTaskBase
{
@ -54,7 +56,10 @@ private:
nsString mTargetRealPath;
// Whether we get a directory.
bool mIsDirectory;
nsCOMPtr<nsIDOMFile> mTargetFile;
// This cannot be a DOMFile bacause this object is created on a different
// thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
nsRefPtr<DOMFileImpl> mTargetFileImpl;
};
} // namespace dom

View File

@ -139,7 +139,7 @@ already_AddRefed<nsIDOMFile>
IDBMutableFile::CreateFileObject(mozilla::dom::FileHandle* aFileHandle,
uint32_t aFileSize)
{
nsCOMPtr<nsIDOMFile> file = new DOMFileCC(
nsCOMPtr<nsIDOMFile> file = new DOMFile(
new FileImpl(mName, mType, aFileSize, mFile, aFileHandle, mFileInfo));
return file.forget();

View File

@ -49,12 +49,12 @@ function compareBuffers(buffer1, buffer2)
function getBlob(type, view)
{
return SpecialPowers.unwrap(utils.getBlob([view], {type: type}));
return new Blob([view], {type: type});
}
function getFile(name, type, view)
{
return SpecialPowers.unwrap(utils.getFile(name, [view], {type: type}));
return new File([view], name, {type: type});
}
function getRandomBlob(size)

View File

@ -48,7 +48,7 @@ interface nsIRunnable;
interface nsICompositionStringSynthesizer;
interface nsITranslationNodeList;
[scriptable, uuid(75b7674b-3e6e-4fac-931b-8fd3c4e4e8d2)]
[scriptable, uuid(6f10cbf8-bd4e-4c56-8a5a-35641efcf286)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1438,24 +1438,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
boolean checkAndClearPaintedState(in nsIDOMElement aElement);
/**
* Internal file constructor intended for testing of File objects.
* Example of constructor usage:
* getFile("myfile.txt", [b1, "foo"], { type: "text/plain" })
*/
[optional_argc, implicit_jscontext]
nsIDOMFile getFile(in DOMString aName, [optional] in jsval aBlobParts,
[optional] in jsval aParameters);
/**
* Internal blob constructor intended for testing of Blob objects.
* Example of constructor usage:
* getBlob([b1, "foo"], { type: "text/plain" })
*/
[optional_argc, implicit_jscontext]
nsIDOMBlob getBlob([optional] in jsval aBlobParts,
[optional] in jsval aParameters);
/**
* Get internal id of the stored blob, file or file handle.
*/

View File

@ -870,7 +870,7 @@ class BlobChild::RemoteBlob::SliceHelper MOZ_FINAL
{
mozilla::Monitor mMonitor;
BlobChild* mActor;
nsCOMPtr<nsIDOMBlob> mSlice;
nsRefPtr<DOMFileImpl> mSlice;
uint64_t mStart;
uint64_t mLength;
nsString mContentType;
@ -888,14 +888,13 @@ public:
MOZ_ASSERT(aActor);
}
nsresult
DOMFileImpl*
GetSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType,
nsIDOMBlob** aSlice)
ErrorResult& aRv)
{
// This may be called on any thread.
MOZ_ASSERT(aSlice);
MOZ_ASSERT(mActor);
MOZ_ASSERT(!mSlice);
MOZ_ASSERT(!mDone);
@ -909,10 +908,15 @@ public:
}
else {
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
if (!mainThread) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
aRv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
if (aRv.Failed()) {
return nullptr;
}
{
MonitorAutoLock lock(mMonitor);
@ -926,11 +930,11 @@ public:
MOZ_ASSERT(mDone);
if (!mSlice) {
return NS_ERROR_UNEXPECTED;
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
mSlice.forget(aSlice);
return NS_OK;
return mSlice;
}
NS_IMETHOD
@ -973,7 +977,8 @@ private:
otherSideParams.optionalInputStreamParams() = mozilla::void_t();
if (mActor->Manager()->SendPBlobConstructor(newActor, otherSideParams)) {
mSlice = newActor->GetBlob();
nsCOMPtr<nsIDOMBlob> blob = newActor->GetBlob();
mSlice = static_cast<DOMFile*>(blob.get())->Impl();
}
mActor = nullptr;
@ -993,7 +998,7 @@ private:
* BlobChild::RemoteBlob Implementation
******************************************************************************/
NS_IMPL_ISUPPORTS_INHERITED(BlobChild::RemoteBlob, DOMFileImplBase, nsIRemoteBlob)
NS_IMPL_ISUPPORTS_INHERITED(BlobChild::RemoteBlob, DOMFileImpl, nsIRemoteBlob)
already_AddRefed<nsIDOMBlob>
BlobChild::
@ -1007,12 +1012,15 @@ RemoteBlob::CreateSlice(uint64_t aStart,
nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
nsCOMPtr<nsIDOMBlob> slice;
nsresult rv =
helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
NS_ENSURE_SUCCESS(rv, nullptr);
ErrorResult rv;
nsRefPtr<DOMFileImpl> slice = helper->GetSlice(aStart, aLength,
aContentType, rv);
if (rv.Failed()) {
return nullptr;
}
return slice.forget();
nsRefPtr<DOMFile> file = new DOMFile(slice);
return file.forget();
}
nsresult
@ -1568,7 +1576,7 @@ class BlobParent::RemoteBlob::SliceHelper MOZ_FINAL
{
mozilla::Monitor mMonitor;
BlobParent* mActor;
nsCOMPtr<nsIDOMBlob> mSlice;
nsRefPtr<DOMFileImpl> mSlice;
uint64_t mStart;
uint64_t mLength;
nsString mContentType;
@ -1586,14 +1594,13 @@ public:
MOZ_ASSERT(aActor);
}
nsresult
DOMFileImpl*
GetSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType,
nsIDOMBlob** aSlice)
ErrorResult& aRv)
{
// This may be called on any thread.
MOZ_ASSERT(aSlice);
MOZ_ASSERT(mActor);
MOZ_ASSERT(!mSlice);
MOZ_ASSERT(!mDone);
@ -1607,10 +1614,15 @@ public:
}
else {
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
if (!mainThread) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
aRv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
if (aRv.Failed()) {
return nullptr;
}
{
MonitorAutoLock lock(mMonitor);
@ -1624,11 +1636,11 @@ public:
MOZ_ASSERT(mDone);
if (!mSlice) {
return NS_ERROR_UNEXPECTED;
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
mSlice.forget(aSlice);
return NS_OK;
return mSlice;
}
NS_IMETHOD
@ -1673,7 +1685,8 @@ private:
ChildBlobConstructorParams otherSideParams = slicedParams;
if (mActor->Manager()->SendPBlobConstructor(newActor, otherSideParams)) {
mSlice = newActor->GetBlob();
nsCOMPtr<nsIDOMBlob> blob =newActor->GetBlob();
mSlice = static_cast<DOMFile*>(blob.get())->Impl();
}
mActor = nullptr;
@ -1693,8 +1706,7 @@ private:
* BlobChild::RemoteBlob Implementation
******************************************************************************/
NS_IMPL_ISUPPORTS_INHERITED(BlobParent::RemoteBlob, DOMFileImplBase,
nsIRemoteBlob)
NS_IMPL_ISUPPORTS_INHERITED(BlobParent::RemoteBlob, DOMFileImpl, nsIRemoteBlob)
already_AddRefed<nsIDOMBlob>
BlobParent::
@ -1708,12 +1720,15 @@ RemoteBlob::CreateSlice(uint64_t aStart,
nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
nsCOMPtr<nsIDOMBlob> slice;
nsresult rv =
helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
NS_ENSURE_SUCCESS(rv, nullptr);
ErrorResult rv;
nsRefPtr<DOMFileImpl> slice = helper->GetSlice(aStart, aLength,
aContentType, rv);
if (rv.Failed()) {
return nullptr;
}
return slice.forget();
nsRefPtr<DOMFile> file = new DOMFile(slice);
return file.forget();
}
nsresult

View File

@ -1893,10 +1893,15 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
DebugOnly<bool> opened = PCompositor::Open(this);
MOZ_ASSERT(opened);
#ifndef MOZ_WIDGET_GONK
if (gfxPrefs::AsyncVideoOOPEnabled()) {
opened = PImageBridge::Open(this);
MOZ_ASSERT(opened);
}
#else
opened = PImageBridge::Open(this);
MOZ_ASSERT(opened);
#endif
}
}
#ifdef MOZ_WIDGET_GONK

View File

@ -0,0 +1,187 @@
/* 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/. */
/**
* Returns true if res is a local rtp
*
* @param {Object} statObject
* One of the objects comprising the report received from getStats()
* @returns {boolean}
* True if object is a local rtp
*/
function isLocalRtp(statObject) {
return (typeof statObject === 'object' &&
statObject.isRemote === false);
}
/**
* Dumps the local, dynamic parts of the stats object as a formatted block
* Used for capturing and monitoring test status during execution
*
* @param {Object} stats
* Stats object to use for output
* @param {string} label
* Used in the header of the output
*/
function outputPcStats(stats, label) {
var outputStr = '\n\n';
function appendOutput(line) {
outputStr += line.toString() + '\n';
}
var firstRtp = true;
for (var prop in stats) {
if (isLocalRtp(stats[prop])) {
var rtp = stats[prop];
if (firstRtp) {
appendOutput(label.toUpperCase() + ' STATS ' +
'(' + new Date(rtp.timestamp).toISOString() + '):');
firstRtp = false;
}
appendOutput(' ' + rtp.id + ':');
if (rtp.type === 'inboundrtp') {
appendOutput(' bytesReceived: ' + rtp.bytesReceived);
appendOutput(' jitter: ' + rtp.jitter);
appendOutput(' packetsLost: ' + rtp.packetsLost);
appendOutput(' packetsReceived: ' + rtp.packetsReceived);
} else {
appendOutput(' bytesSent: ' + rtp.bytesSent);
appendOutput(' packetsSent: ' + rtp.packetsSent);
}
}
}
outputStr += '\n\n';
dump(outputStr);
}
var _lastStats = {};
/**
* Verifies the peer connection stats interval over interval
*
* @param {Object} stats
* Stats object to use for verification
* @param {string} label
* Identifies the peer connection. Differentiates stats for
* interval-over-interval verification in cases where more than one set
* is being verified
*/
function verifyPcStats(stats, label) {
const INCREASING_INBOUND_STAT_NAMES = [
'bytesReceived',
'packetsReceived'
];
const INCREASING_OUTBOUND_STAT_NAMES = [
'bytesSent',
'packetsSent'
];
if (_lastStats[label] !== undefined) {
function verifyIncrease(rtpName, statNames) {
var timestamp = new Date(stats[rtpName].timestamp).toISOString();
statNames.forEach(function (statName) {
ok(stats[rtpName][statName] > _lastStats[label][rtpName][statName],
timestamp + '.' + label + '.' + rtpName + '.' + statName,
label + '.' + rtpName + '.' + statName + ' increased (value=' +
stats[rtpName][statName] + ')');
});
}
for (var prop in stats) {
if (isLocalRtp(stats[prop])) {
if (stats[prop].type === 'inboundrtp') {
verifyIncrease(prop, INCREASING_INBOUND_STAT_NAMES);
} else {
verifyIncrease(prop, INCREASING_OUTBOUND_STAT_NAMES);
}
}
}
}
_lastStats[label] = stats;
}
/**
* Retrieves and performs a series of operations on PeerConnection stats
*
* @param {PeerConnectionWrapper} pc
* PeerConnectionWrapper from which to get stats
* @param {string} label
* Label for the peer connection, passed to each stats callback
* @param {Array} operations
* Array of stats callbacks, each as function (stats, label)
*/
function processPcStats(pc, label, operations) {
pc.getStats(null, function (stats) {
operations.forEach(function (operation) {
operation(stats, label);
});
});
}
/**
* Outputs and verifies the status for local and/or remote PeerConnection as
* appropriate
*
* @param {Object} test
* Test containing the peer connection(s) for verification
*/
function verifyConnectionStatus(test) {
const OPERATIONS = [outputPcStats, verifyPcStats];
if (test.pcLocal) {
processPcStats(test.pcLocal, 'LOCAL', OPERATIONS);
}
if (test.pcRemote) {
processPcStats(test.pcRemote, 'REMOTE', OPERATIONS);
}
}
/**
* Generates a setInterval wrapper command link for use in pc.js command chains
*
* The link will repeatedly call the given callback function every interval ms
* until duration ms have passed, then it will continue the test.
*
* @param {function} callback
* Function to be called on each interval
* @param {number} [interval=1000]
* Frequency in milliseconds with which callback will be called
* @param {number} [duration=3 hours]
* Length of time in milliseconds for which callback will be called
* @param {string} [name='INTERVAL_COMMAND']
* Name of the generated command link
*/
function generateIntervalCommand(callback, interval, duration, name) {
interval = interval || 1000;
duration = duration || 1000 * 3600 * 3;
name = name || 'INTERVAL_COMMAND';
return [
name,
function (test) {
var startTime = Date.now();
var intervalId = setInterval(function () {
if (callback) {
callback(test);
}
var timeElapsed = Date.now() - startTime;
if (timeElapsed >= duration) {
clearInterval(intervalId);
test.next();
}
}, interval);
}
]
}

View File

@ -0,0 +1,11 @@
[DEFAULT]
support-files =
head.js
long.js
mediaStreamPlayback.js
pc.js
templates.js
turnConfig.js
[test_peerConnection_basicAudioVideoCombined_long.html]

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<!-- 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/. -->
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="long.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1014328",
title: "Basic audio/video (combined) peer connection, long running"
});
FAKE_ENABLED = false;
var test;
runTest(function (options) {
options = options || {};
options.commands = commandsPeerConnection.slice(0);
options.commands.push(generateIntervalCommand(verifyConnectionStatus));
test = new PeerConnectionTest(options);
test.setMediaConstraints([{audio: true, video: true}],
[{audio: true, video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -5,8 +5,8 @@
#include "URL.h"
#include "nsDOMFile.h"
#include "nsIDocument.h"
#include "nsIDOMFile.h"
#include "nsIIOService.h"
#include "nsPIDOMWindow.h"
@ -67,18 +67,18 @@ private:
class CreateURLRunnable : public WorkerMainThreadRunnable
{
private:
nsIDOMBlob* mBlob;
DOMFileImpl* mBlobImpl;
nsString& mURL;
public:
CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob,
CreateURLRunnable(WorkerPrivate* aWorkerPrivate, DOMFileImpl* aBlobImpl,
const mozilla::dom::objectURLOptions& aOptions,
nsString& aURL)
: WorkerMainThreadRunnable(aWorkerPrivate),
mBlob(aBlob),
mBlobImpl(aBlobImpl),
mURL(aURL)
{
MOZ_ASSERT(aBlob);
MOZ_ASSERT(aBlobImpl);
}
bool
@ -106,7 +106,7 @@ public:
nsCString url;
nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
NS_LITERAL_CSTRING(BLOBURI_SCHEME),
mBlob, principal, url);
mBlobImpl, principal, url);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add data entry for the blob!");
@ -857,8 +857,10 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject* aBlob,
return;
}
DOMFile* domBlob = static_cast<DOMFile*>(blob.get());
nsRefPtr<CreateURLRunnable> runnable =
new CreateURLRunnable(workerPrivate, blob, aOptions, aResult);
new CreateURLRunnable(workerPrivate, domBlob->Impl(), aOptions, aResult);
if (!runnable->Dispatch(cx)) {
JS_ReportPendingException(cx);

View File

@ -304,23 +304,21 @@ struct WorkerStructuredCloneCallbacks
if (aTag == DOMWORKER_SCTAG_FILE) {
MOZ_ASSERT(!aData);
nsIDOMFile* file;
if (JS_ReadBytes(aReader, &file, sizeof(file))) {
MOZ_ASSERT(file);
DOMFileImpl* fileImpl;
if (JS_ReadBytes(aReader, &fileImpl, sizeof(fileImpl))) {
MOZ_ASSERT(fileImpl);
#ifdef DEBUG
{
// File should not be mutable.
nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
bool isMutable;
NS_ASSERTION(NS_SUCCEEDED(mutableFile->GetMutable(&isMutable)) &&
NS_ASSERTION(NS_SUCCEEDED(fileImpl->GetMutable(&isMutable)) &&
!isMutable,
"Only immutable file should be passed to worker");
}
#endif
// nsIDOMFiles should be threadsafe, thus we will use the same instance
// in the worker.
nsRefPtr<DOMFile> file = new DOMFile(fileImpl);
JSObject* jsFile = file::CreateFile(aCx, file);
return jsFile;
}
@ -329,23 +327,21 @@ struct WorkerStructuredCloneCallbacks
else if (aTag == DOMWORKER_SCTAG_BLOB) {
MOZ_ASSERT(!aData);
nsIDOMBlob* blob;
if (JS_ReadBytes(aReader, &blob, sizeof(blob))) {
MOZ_ASSERT(blob);
DOMFileImpl* blobImpl;
if (JS_ReadBytes(aReader, &blobImpl, sizeof(blobImpl))) {
MOZ_ASSERT(blobImpl);
#ifdef DEBUG
{
// Blob should not be mutable.
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
bool isMutable;
NS_ASSERTION(NS_SUCCEEDED(mutableBlob->GetMutable(&isMutable)) &&
NS_ASSERTION(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)) &&
!isMutable,
"Only immutable blob should be passed to worker");
}
#endif
// nsIDOMBlob should be threadsafe, thus we will use the same instance
// in the worker.
nsRefPtr<DOMFile> blob = new DOMFile(blobImpl);
JSObject* jsBlob = file::CreateBlob(aCx, blob);
return jsBlob;
}
@ -389,9 +385,10 @@ struct WorkerStructuredCloneCallbacks
{
nsIDOMFile* file = file::GetDOMFileFromJSObject(aObj);
if (file) {
DOMFileImpl* fileImpl = static_cast<DOMFile*>(file)->Impl();
if (JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_FILE, 0) &&
JS_WriteBytes(aWriter, &file, sizeof(file))) {
clonedObjects->AppendElement(file);
JS_WriteBytes(aWriter, &fileImpl, sizeof(fileImpl))) {
clonedObjects->AppendElement(fileImpl);
return true;
}
}
@ -401,11 +398,11 @@ struct WorkerStructuredCloneCallbacks
{
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aObj);
if (blob) {
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
if (mutableBlob && NS_SUCCEEDED(mutableBlob->SetMutable(false)) &&
DOMFileImpl* blobImpl = static_cast<DOMFile*>(blob)->Impl();
if (blobImpl && NS_SUCCEEDED(blobImpl->SetMutable(false)) &&
JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0) &&
JS_WriteBytes(aWriter, &blob, sizeof(blob))) {
clonedObjects->AppendElement(blob);
JS_WriteBytes(aWriter, &blobImpl, sizeof(blobImpl))) {
clonedObjects->AppendElement(blobImpl);
return true;
}
}
@ -461,21 +458,22 @@ struct MainThreadWorkerStructuredCloneCallbacks
if (aTag == DOMWORKER_SCTAG_FILE) {
MOZ_ASSERT(!aData);
nsIDOMFile* file;
if (JS_ReadBytes(aReader, &file, sizeof(file))) {
MOZ_ASSERT(file);
DOMFileImpl* fileImpl;
if (JS_ReadBytes(aReader, &fileImpl, sizeof(fileImpl))) {
MOZ_ASSERT(fileImpl);
#ifdef DEBUG
{
// File should not be mutable.
nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
bool isMutable;
NS_ASSERTION(NS_SUCCEEDED(mutableFile->GetMutable(&isMutable)) &&
NS_ASSERTION(NS_SUCCEEDED(fileImpl->GetMutable(&isMutable)) &&
!isMutable,
"Only immutable file should be passed to worker");
}
#endif
nsCOMPtr<nsIDOMFile> file = new DOMFile(fileImpl);
// nsIDOMFiles should be threadsafe, thus we will use the same instance
// on the main thread.
JS::Rooted<JS::Value> wrappedFile(aCx);
@ -494,21 +492,22 @@ struct MainThreadWorkerStructuredCloneCallbacks
else if (aTag == DOMWORKER_SCTAG_BLOB) {
MOZ_ASSERT(!aData);
nsIDOMBlob* blob;
if (JS_ReadBytes(aReader, &blob, sizeof(blob))) {
MOZ_ASSERT(blob);
DOMFileImpl* blobImpl;
if (JS_ReadBytes(aReader, &blobImpl, sizeof(blobImpl))) {
MOZ_ASSERT(blobImpl);
#ifdef DEBUG
{
// Blob should not be mutable.
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
bool isMutable;
NS_ASSERTION(NS_SUCCEEDED(mutableBlob->GetMutable(&isMutable)) &&
NS_ASSERTION(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)) &&
!isMutable,
"Only immutable blob should be passed to worker");
}
#endif
nsCOMPtr<nsIDOMBlob> blob = new DOMFile(blobImpl);
// nsIDOMBlobs should be threadsafe, thus we will use the same instance
// on the main thread.
JS::Rooted<JS::Value> wrappedBlob(aCx);
@ -550,36 +549,40 @@ struct MainThreadWorkerStructuredCloneCallbacks
nsISupports* wrappedObject = wrappedNative->Native();
NS_ASSERTION(wrappedObject, "Null pointer?!");
nsISupports* ccISupports = nullptr;
wrappedObject->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
reinterpret_cast<void**>(&ccISupports));
if (ccISupports) {
NS_WARNING("Cycle collected objects are not supported!");
}
else {
// See if the wrapped native is a nsIDOMFile.
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(wrappedObject);
if (file) {
nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
if (mutableFile && NS_SUCCEEDED(mutableFile->SetMutable(false))) {
nsIDOMFile* filePtr = file;
// See if the wrapped native is a nsIDOMFile.
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(wrappedObject);
if (file) {
nsRefPtr<DOMFileImpl> fileImpl =
static_cast<DOMFile*>(file.get())->Impl();
if (fileImpl->IsCCed()) {
NS_WARNING("Cycle collected file objects are not supported!");
} else {
if (NS_SUCCEEDED(fileImpl->SetMutable(false))) {
DOMFileImpl* fileImplPtr = fileImpl;
if (JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_FILE, 0) &&
JS_WriteBytes(aWriter, &filePtr, sizeof(filePtr))) {
clonedObjects->AppendElement(file);
JS_WriteBytes(aWriter, &fileImplPtr, sizeof(fileImplPtr))) {
clonedObjects->AppendElement(fileImpl);
return true;
}
}
}
}
// See if the wrapped native is a nsIDOMBlob.
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(wrappedObject);
if (blob) {
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
if (mutableBlob && NS_SUCCEEDED(mutableBlob->SetMutable(false))) {
nsIDOMBlob* blobPtr = blob;
// See if the wrapped native is a nsIDOMBlob.
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(wrappedObject);
if (blob) {
nsRefPtr<DOMFileImpl> blobImpl =
static_cast<DOMFile*>(blob.get())->Impl();
if (blobImpl->IsCCed()) {
NS_WARNING("Cycle collected blob objects are not supported!");
} else {
if (NS_SUCCEEDED(blobImpl->SetMutable(false))) {
DOMFileImpl* blobImplPtr = blobImpl;
if (JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0) &&
JS_WriteBytes(aWriter, &blobPtr, sizeof(blobPtr))) {
clonedObjects->AppendElement(blob);
JS_WriteBytes(aWriter, &blobImplPtr, sizeof(blobImplPtr))) {
clonedObjects->AppendElement(blobImpl);
return true;
}
}

View File

@ -517,10 +517,12 @@ gfxPlatform::InitLayersIPC()
XRE_GetProcessType() == GeckoProcessType_Default)
{
mozilla::layers::CompositorParent::StartUp();
#ifndef MOZ_WIDGET_GONK
if (gfxPrefs::AsyncVideoEnabled()) {
mozilla::layers::ImageBridgeChild::StartUp();
}
#ifdef MOZ_WIDGET_GONK
#else
mozilla::layers::ImageBridgeChild::StartUp();
SharedBufferManagerChild::StartUp();
#endif
}

View File

@ -1076,7 +1076,7 @@ imgLoader::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aD
{
// We listen for pref change notifications...
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "image.http.accept")) {
if (!NS_strcmp(aData, MOZ_UTF16("image.http.accept"))) {
ReadAcceptHeaderPref();
}

View File

@ -306,6 +306,7 @@ typedef union jsval_layout
uint32_t u32;
uint32_t boo; // Don't use |bool| -- it must be four bytes.
JSString *str;
JS::Symbol *sym;
JSObject *obj;
js::gc::Cell *cell;
void *ptr;

View File

@ -477,7 +477,9 @@ BacktrackingAllocator::tryAllocateNonFixed(LiveInterval *interval, bool *success
}
// Spill intervals which have no hint or register requirement.
if (interval->requirement()->kind() == Requirement::NONE) {
if (interval->requirement()->kind() == Requirement::NONE &&
interval->hint()->kind() != Requirement::REGISTER)
{
spill(interval);
*success = true;
return true;
@ -494,6 +496,14 @@ BacktrackingAllocator::tryAllocateNonFixed(LiveInterval *interval, bool *success
}
}
// Spill intervals which have no register requirement if they didn't get
// allocated.
if (interval->requirement()->kind() == Requirement::NONE) {
spill(interval);
*success = true;
return true;
}
// We failed to allocate this interval.
JS_ASSERT(!*success);
return true;
@ -688,6 +698,9 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
} else if (policy == LUse::REGISTER) {
if (!interval->addRequirement(Requirement(Requirement::REGISTER)))
return false;
} else if (policy == LUse::ANY) {
// ANY differs from KEEPALIVE by actively preferring a register.
interval->addHint(Requirement(Requirement::REGISTER));
}
}
@ -916,6 +929,14 @@ BacktrackingAllocator::spill(LiveInterval *interval)
BacktrackingVirtualRegister *reg = &vregs[interval->vreg()];
if (LiveInterval *spillInterval = interval->spillInterval()) {
IonSpew(IonSpew_RegAlloc, " Spilling to existing spill interval");
while (!interval->usesEmpty())
spillInterval->addUse(interval->popUse());
reg->removeInterval(interval);
return;
}
bool useCanonical = !reg->hasCanonicalSpillExclude()
|| interval->start() < reg->canonicalSpillExclude();
@ -1612,6 +1633,55 @@ BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, Live
return splitAt(interval, splitPositions);
}
bool
BacktrackingAllocator::trySplitBeforeFirstRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success)
{
// If this interval's earlier uses do not require it to be in a register,
// split it before the first use which does require a register. If conflict
// is specified, only consider register uses after the conflict ends.
if (isRegisterDefinition(interval)) {
IonSpew(IonSpew_RegAlloc, " interval is defined by a register");
return true;
}
if (interval->index() != 0) {
IonSpew(IonSpew_RegAlloc, " interval is not defined in memory");
return true;
}
CodePosition firstRegisterFrom;
for (UsePositionIterator iter(interval->usesBegin());
iter != interval->usesEnd();
iter++)
{
LUse *use = iter->use;
LInstruction *ins = insData[iter->pos].ins();
if (!conflict || outputOf(ins) >= conflict->end()) {
if (isRegisterUse(use, ins, /* considerCopy = */ true)) {
firstRegisterFrom = inputOf(ins);
break;
}
}
}
if (!firstRegisterFrom.bits()) {
// Can't trim non-register uses off the beginning by splitting.
IonSpew(IonSpew_RegAlloc, " interval has no register uses");
return true;
}
IonSpew(IonSpew_RegAlloc, " split before first register use at %u",
firstRegisterFrom.bits());
SplitPositions splitPositions;
if (!splitPositions.append(firstRegisterFrom))
return false;
*success = true;
return splitAt(interval, splitPositions);
}
bool
BacktrackingAllocator::splitAtAllRegisterUses(LiveInterval *interval)
{
@ -1829,6 +1899,11 @@ BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval, LiveInterval
if (success)
return true;
if (!trySplitBeforeFirstRegisterUse(interval, conflict, &success))
return false;
if (success)
return true;
if (!trySplitAfterLastRegisterUse(interval, conflict, &success))
return false;
if (success)

View File

@ -264,6 +264,7 @@ class BacktrackingAllocator
bool splitAt(LiveInterval *interval, const SplitPositions &splitPositions);
bool trySplitAcrossHotcode(LiveInterval *interval, bool *success);
bool trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
bool trySplitBeforeFirstRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
bool splitAtAllRegisterUses(LiveInterval *interval);
bool splitAcrossCalls(LiveInterval *interval);
};

View File

@ -1192,7 +1192,9 @@ jit::BuildDominatorTree(MIRGraph &graph)
{
ComputeImmediateDominators(graph);
// Traversing through the graph in post-order means that every use
Vector<MBasicBlock *, 4, IonAllocPolicy> worklist(graph.alloc());
// Traversing through the graph in post-order means that every non-phi use
// of a definition is visited before the def itself. Since a def
// dominates its uses, by the time we reach a particular
// block, we have processed all of its dominated children, so
@ -1205,8 +1207,13 @@ jit::BuildDominatorTree(MIRGraph &graph)
child->addNumDominated(1);
// If the block only self-dominates, it has no definite parent.
if (child == parent)
// Add it to the worklist as a root for pre-order traversal.
// This includes all roots. Order does not matter.
if (child == parent) {
if (!worklist.append(child))
return false;
continue;
}
if (!parent->addImmediatelyDominatedBlock(child))
return false;
@ -1220,24 +1227,9 @@ jit::BuildDominatorTree(MIRGraph &graph)
if (!graph.osrBlock())
JS_ASSERT(graph.entryBlock()->numDominated() == graph.numBlocks());
#endif
// Now, iterate through the dominator tree and annotate every
// block with its index in the pre-order traversal of the
// dominator tree.
Vector<MBasicBlock *, 1, IonAllocPolicy> worklist(graph.alloc());
// The index of the current block in the CFG traversal.
// Now, iterate through the dominator tree in pre-order and annotate every
// block with its index in the traversal.
size_t index = 0;
// Add all self-dominating blocks to the worklist.
// This includes all roots. Order does not matter.
for (MBasicBlockIterator i(graph.begin()); i != graph.end(); i++) {
MBasicBlock *block = *i;
if (block->immediateDominator() == block) {
if (!worklist.append(block))
return false;
}
}
// Starting from each self-dominating block, traverse the CFG in pre-order.
while (!worklist.empty()) {
MBasicBlock *block = worklist.popCopy();
block->setDomIndex(index);
@ -1433,6 +1425,13 @@ static void
AssertDominatorTree(MIRGraph &graph)
{
// Check dominators.
JS_ASSERT(graph.entryBlock()->immediateDominator() == graph.entryBlock());
if (MBasicBlock *osrBlock = graph.osrBlock())
JS_ASSERT(osrBlock->immediateDominator() == osrBlock);
else
JS_ASSERT(graph.entryBlock()->numDominated() == graph.numBlocks());
size_t i = graph.numBlocks();
size_t totalNumDominated = 0;
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {

View File

@ -1870,7 +1870,7 @@ GetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex,
if (cache.canAttachStub()) {
bool alreadyStubbed;
if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
if (alreadyStubbed)
return true;
@ -1887,13 +1887,13 @@ GetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex,
if (canCache == GetPropertyIC::CanAttachReadSlot) {
if (!cache.attachReadSlot(ncx, ion, obj, holder, shape))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
if (!attachedStub && canCache == GetPropertyIC::CanAttachArrayLength) {
if (!cache.attachArrayLength(ncx, ion, obj))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
}
@ -1903,7 +1903,7 @@ GetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex,
(cache.output().type() == MIRType_Value || cache.output().type() == MIRType_Int32))
{
if (!cache.attachTypedArrayLength(ncx, ion, obj))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
}
@ -2869,7 +2869,7 @@ SetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject ob
if (cache.canAttachStub()) {
bool alreadyStubbed;
if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
if (alreadyStubbed) {
return baseops::SetPropertyHelper<ParallelExecution>(
cx, obj, obj, id, baseops::Qualified, &v, cache.strict());
@ -2889,7 +2889,7 @@ SetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject ob
if (canCache == SetPropertyIC::CanAttachSetSlot) {
if (!cache.attachSetSlot(ncx, ion, obj, shape, checkTypeset))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
}
@ -2912,7 +2912,7 @@ SetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject ob
{
LockedJSContext ncx(cx);
if (cache.canAttachStub() && !cache.attachAddSlot(ncx, ion, obj, oldShape, checkTypeset))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
}
return true;
@ -3890,20 +3890,20 @@ SetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
if (cache.canAttachStub()) {
bool alreadyStubbed;
if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
if (alreadyStubbed)
return SetElementPar(cx, obj, idval, value, cache.strict());
bool attachedStub = false;
if (IsDenseElementSetInlineable(obj, idval)) {
if (!cache.attachDenseElement(ncx, ion, obj, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) {
RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
if (!cache.attachTypedArrayElement(ncx, ion, tarr))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
}
}
}
@ -3976,7 +3976,7 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
if (cache.canAttachStub()) {
bool alreadyStubbed;
if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
if (alreadyStubbed)
return true;
@ -3998,7 +3998,7 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
if (canCache == GetPropertyIC::CanAttachReadSlot)
{
if (!cache.attachReadSlot(ncx, ion, obj, idval, name, holder, shape))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
}
@ -4006,7 +4006,7 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
GetElementIC::canAttachDenseElement(obj, idval))
{
if (!cache.attachDenseElement(ncx, ion, obj, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
if (!attachedStub &&
@ -4014,7 +4014,7 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
{
RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
if (!cache.attachTypedArrayElement(ncx, ion, tarr, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory);
attachedStub = true;
}
}

View File

@ -761,7 +761,12 @@ HandleParallelFailure(ResumeFromException *rfe)
ForkJoinContext *cx = ForkJoinContext::current();
JitFrameIterator frameIter(cx);
cx->bailoutRecord->joinCause(ParallelBailoutUnsupportedVM);
// Advance to the first Ion frame so we can pull out the BailoutKind.
while (!frameIter.isIonJS())
++frameIter;
SnapshotIterator snapIter(frameIter);
cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind());
cx->bailoutRecord->rematerializeFrames(cx, frameIter);
rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME;

View File

@ -100,8 +100,12 @@ enum BailoutKind
Bailout_NonStringInput,
Bailout_NonSymbolInput,
// PJS bailout when writing to a non-thread local object.
Bailout_GuardThreadExclusive,
// PJS bailout when encountering MIR unsafe for parallel execution.
Bailout_ParallelUnsafe,
// For the initial snapshot when entering a function.
Bailout_InitialState,

View File

@ -393,13 +393,13 @@ class SnapshotIterator
Value read() {
return allocationValue(readAllocation());
}
Value maybeRead(bool silentFailure = false) {
Value maybeRead(const Value &placeholder = UndefinedValue(), bool silentFailure = false) {
RValueAllocation a = readAllocation();
if (allocationReadable(a))
return allocationValue(a);
if (!silentFailure)
warnUnreadableAllocation();
return UndefinedValue();
return placeholder;
}
void readCommonFrameSlots(Value *scopeChain, Value *rval) {
@ -416,7 +416,8 @@ class SnapshotIterator
template <class Op>
void readFunctionFrameArgs(Op &op, ArgumentsObject **argsObj, Value *thisv,
unsigned start, unsigned end, JSScript *script)
unsigned start, unsigned end, JSScript *script,
const Value &unreadablePlaceholder = UndefinedValue())
{
// Assumes that the common frame arguments have already been read.
if (script->argumentsHasVarBinding()) {
@ -444,7 +445,7 @@ class SnapshotIterator
// We are not always able to read values from the snapshots, some values
// such as non-gc things may still be live in registers and cause an
// error while reading the machine state.
Value v = maybeRead();
Value v = maybeRead(unreadablePlaceholder);
op(v);
}
}
@ -455,7 +456,7 @@ class SnapshotIterator
skip();
}
Value s = maybeRead(true);
Value s = maybeRead(/* placeholder = */ UndefinedValue(), true);
while (moreAllocations())
skip();
@ -531,7 +532,8 @@ class InlineFrameIterator
void readFrameArgsAndLocals(ThreadSafeContext *cx, ArgOp &argOp, LocalOp &localOp,
JSObject **scopeChain, Value *rval,
ArgumentsObject **argsObj, Value *thisv,
ReadFrameArgsBehavior behavior) const
ReadFrameArgsBehavior behavior,
const Value &unreadablePlaceholder = UndefinedValue()) const
{
SnapshotIterator s(si_);
@ -550,8 +552,10 @@ class InlineFrameIterator
// Get the non overflown arguments, which are taken from the inlined
// frame, because it will have the updated value when JSOP_SETARG is
// done.
if (behavior != ReadFrame_Overflown)
s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script());
if (behavior != ReadFrame_Overflown) {
s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script(),
unreadablePlaceholder);
}
if (behavior != ReadFrame_Formals) {
if (more()) {
@ -579,7 +583,8 @@ class InlineFrameIterator
// Get the overflown arguments
parent_s.readCommonFrameSlots(nullptr, nullptr);
parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr,
nformal, nactual, it.script());
nformal, nactual, it.script(),
unreadablePlaceholder);
} else {
// There is no parent frame to this inlined frame, we can read
// from the frame's Value vector directly.
@ -592,8 +597,14 @@ class InlineFrameIterator
// At this point we've read all the formals in s, and can read the
// locals.
for (unsigned i = 0; i < script()->nfixed(); i++)
localOp(s.read());
for (unsigned i = 0; i < script()->nfixed(); i++) {
// We have to use maybeRead here, some of these might be recover
// instructions, and currently InlineFrameIter does not support
// recovering slots.
//
// FIXME bug 1029963.
localOp(s.maybeRead(unreadablePlaceholder));
}
}
template <class Op>

View File

@ -390,6 +390,12 @@ LiveInterval::nextUseAfter(CodePosition after)
return nullptr;
}
UsePosition *
LiveInterval::popUse()
{
return uses_.popFront();
}
/*
* This function locates the first "real" use of this interval that follows
* the given code position. Non-"real" uses are currently just snapshots,

View File

@ -360,6 +360,11 @@ class LiveInterval
bool addRequirement(const Requirement &newRequirement) {
return requirement_.mergeRequirement(newRequirement);
}
void addHint(const Requirement &newHint) {
// Unlike addRequirement, here in addHint we ignore merge failures,
// because these are just hints.
hint_.mergeRequirement(newHint);
}
const Requirement *hint() const {
return &hint_;
}
@ -373,6 +378,7 @@ class LiveInterval
void addUse(UsePosition *use);
void addUseAtEnd(UsePosition *use);
UsePosition *popUse();
UsePosition *nextUseAfter(CodePosition pos);
CodePosition nextUsePosAfter(CodePosition pos);
CodePosition firstIncompatibleUse(LAllocation alloc);
@ -491,6 +497,12 @@ class VirtualRegister
interval->setIndex(found - intervals_.begin());
return intervals_.insert(found, interval);
}
void removeInterval(LiveInterval *interval) {
intervals_.erase(intervals_.begin() + interval->index());
for (size_t i = interval->index(), e = intervals_.length(); i < e; ++i)
intervals_[i]->setIndex(i);
interval->setIndex(-1);
}
bool isFloatReg() const {
return def_->isFloatReg();
}

View File

@ -941,14 +941,6 @@ MBasicBlock::assertUsesAreNotWithin(MUseIterator use, MUseIterator end)
#endif
}
bool
MBasicBlock::dominates(const MBasicBlock *other) const
{
uint32_t high = domIndex() + numDominated();
uint32_t low = domIndex();
return other->domIndex() >= low && other->domIndex() < high;
}
AbortReason
MBasicBlock::setBackedge(MBasicBlock *pred)
{

View File

@ -82,7 +82,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info,
MBasicBlock *pred, Kind kind);
bool dominates(const MBasicBlock *other) const;
bool dominates(const MBasicBlock *other) const {
return other->domIndex() - domIndex() < numDominated();
}
void setId(uint32_t id) {
id_ = id;

View File

@ -531,7 +531,9 @@ jit::BailoutPar(BailoutStack *sp, uint8_t **entryFramePointer)
JitActivationIterator jitActivations(cx->perThreadData);
IonBailoutIterator frameIter(jitActivations, sp);
cx->bailoutRecord->joinCause(ParallelBailoutUnsupported);
SnapshotIterator snapIter(frameIter);
cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind());
cx->bailoutRecord->rematerializeFrames(cx, frameIter);
MOZ_ASSERT(frameIter.done());

View File

@ -439,7 +439,7 @@ ParallelSafetyVisitor::convertToBailout(MInstructionIterator &iter)
block->discardAllInstructionsStartingAt(iter);
// End the block in a bail.
MBail *bail = MBail::New(graph_.alloc());
MBail *bail = MBail::New(graph_.alloc(), Bailout_ParallelUnsafe);
TransplantResumePoint(ins, bail);
block->add(bail);
block->end(MUnreachable::New(alloc()));
@ -755,7 +755,7 @@ ParallelSafetyVisitor::visitThrow(MThrow *thr)
{
MBasicBlock *block = thr->block();
JS_ASSERT(block->lastIns() == thr);
MBail *bail = MBail::New(alloc());
MBail *bail = MBail::New(alloc(), Bailout_ParallelUnsafe);
TransplantResumePoint(thr, bail);
block->discardLastIns();
block->end(MUnreachable::New(alloc()));

View File

@ -39,7 +39,8 @@ RematerializedFrame::RematerializedFrame(ThreadSafeContext *cx, uint8_t *top,
{
CopyValueToRematerializedFrame op(slots_);
iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_,
&argsObj_, &thisValue_, ReadFrame_Actuals);
&argsObj_, &thisValue_, ReadFrame_Actuals,
MagicValue(JS_OPTIMIZED_OUT));
}
/* static */ RematerializedFrame *

View File

@ -770,7 +770,7 @@ js::WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
// Error in strict mode code or warn with strict option.
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
if (cx->isForkJoinContext())
return cx->asForkJoinContext()->reportError(ParallelBailoutUnsupportedVM, flags);
return cx->asForkJoinContext()->reportError(flags);
if (!cx->isJSContext())
return true;

View File

@ -4905,7 +4905,7 @@ bool
JSObject::reportReadOnly(ThreadSafeContext *cxArg, jsid id, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(ParallelBailoutUnsupportedVM, report);
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;
@ -4921,7 +4921,7 @@ bool
JSObject::reportNotConfigurable(ThreadSafeContext *cxArg, jsid id, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(ParallelBailoutUnsupportedVM, report);
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;
@ -4937,7 +4937,7 @@ bool
JSObject::reportNotExtensible(ThreadSafeContext *cxArg, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(ParallelBailoutUnsupportedVM, report);
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;

View File

@ -236,6 +236,10 @@ EqualChars(JSLinearString *str1, JSLinearString *str2);
extern bool
CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result);
/*
* Same as CompareStrings but for atoms. Don't use this to just test
* for equality; use this when you need an ordering on atoms.
*/
extern int32_t
CompareAtoms(JSAtom *atom1, JSAtom *atom2);

View File

@ -318,8 +318,6 @@ class ForkJoinOperation
TrafficLight recoverFromBailout(ExecutionStatus *status);
TrafficLight fatalError(ExecutionStatus *status);
bool isInitialScript(HandleScript script);
void getBailoutScriptAndPc(MutableHandleScript bailoutScript, jsbytecode **bailoutPc,
ParallelBailoutCause *bailoutCause);
bool reportBailoutWarnings();
bool invalidateBailedOutScripts();
ExecutionStatus sequentialExecution(bool disqualified);
@ -615,8 +613,8 @@ ForkJoinOperation::apply()
// - Re-enqueue main script and any uncompiled scripts that were called
// - Too many bailouts: Fallback to sequential
JS_ASSERT_IF(!jit::IsBaselineEnabled(cx_), !jit::IsIonEnabled(cx_));
if (!jit::IsBaselineEnabled(cx_) || !jit::IsIonEnabled(cx_))
JS_ASSERT_IF(!IsBaselineEnabled(cx_), !IsIonEnabled(cx_));
if (!IsBaselineEnabled(cx_) || !IsIonEnabled(cx_))
return sequentialExecution(true);
SpewBeginOp(cx_, "ForkJoinOperation");
@ -796,7 +794,7 @@ ForkJoinOperation::compileForParallelExecution(ExecutionStatus *status)
if (!script->hasParallelIonScript()) {
// Script has not yet been compiled. Attempt to compile it.
SpewBeginCompile(script);
MethodStatus mstatus = jit::CanEnterInParallel(cx_, script);
MethodStatus mstatus = CanEnterInParallel(cx_, script);
SpewEndCompile(mstatus);
switch (mstatus) {
@ -1042,41 +1040,100 @@ BailoutExplanation(ParallelBailoutCause cause)
{
switch (cause) {
case ParallelBailoutNone:
return "no particular reason";
return "no bailout";
case ParallelBailoutInterrupt:
return "interrupted";
case ParallelBailoutExecution:
return "";
case ParallelBailoutCompilationSkipped:
return "compilation failed (method skipped)";
case ParallelBailoutCompilationFailure:
return "compilation failed";
case ParallelBailoutInterrupt:
return "interrupted";
case ParallelBailoutFailedIC:
return "failed to attach stub to IC";
case ParallelBailoutHeapBusy:
return "heap busy flag set during interrupt";
case ParallelBailoutMainScriptNotPresent:
return "main script not present";
case ParallelBailoutCalledToUncompiledScript:
return "called to uncompiled script";
case ParallelBailoutIllegalWrite:
return "illegal write";
case ParallelBailoutAccessToIntrinsic:
return "access to intrinsic";
return "main script JIT code was collected";
case ParallelBailoutOverRecursed:
return "over recursed";
return "stack limit exceeded";
case ParallelBailoutOutOfMemory:
return "out of memory";
case ParallelBailoutUnsupported:
return "unsupported";
case ParallelBailoutUnsupportedVM:
return "unsupported operation in VM call";
case ParallelBailoutUnsupportedStringComparison:
return "unsupported string comparison";
case ParallelBailoutRequestedGC:
return "requested GC";
return "requested GC of common heap";
case ParallelBailoutRequestedZoneGC:
return "requested zone GC";
return "requested zone GC of common heap";
default:
return "no known reason";
MOZ_ASSUME_UNREACHABLE("Invalid ParallelBailoutCause");
}
}
static const char *
IonBailoutKindExplanation(ParallelBailoutCause cause, BailoutKind kind)
{
if (cause != ParallelBailoutExecution)
return "";
switch (kind) {
// Normal bailouts.
case Bailout_Inevitable:
return "inevitable";
case Bailout_DuringVMCall:
return "on vm reentry";
case Bailout_NonJSFunctionCallee:
return "non-scripted callee";
case Bailout_DynamicNameNotFound:
return "dynamic name not found";
case Bailout_StringArgumentsEval:
return "string contains 'arguments' or 'eval'";
case Bailout_Overflow:
case Bailout_OverflowInvalidate:
return "integer overflow";
case Bailout_Round:
return "unhandled input to rounding function";
case Bailout_NonPrimitiveInput:
return "trying to convert non-primitive input to number or string";
case Bailout_PrecisionLoss:
return "precision loss when converting to int32";
case Bailout_TypeBarrierO:
return "tripped type barrier: unexpected object";
case Bailout_TypeBarrierV:
return "tripped type barrier: unexpected value";
case Bailout_MonitorTypes:
return "wrote value of unexpected type to property";
case Bailout_Hole:
return "saw unexpected array hole";
case Bailout_NegativeIndex:
return "negative array index";
case Bailout_ObjectIdentityOrTypeGuard:
return "saw unexpected object type barrier";
case Bailout_NonInt32Input:
return "can't unbox: expected int32";
case Bailout_NonNumericInput:
return "can't unbox: expected number";
case Bailout_NonBooleanInput:
return "can't unbox: expected boolean";
case Bailout_NonObjectInput:
return "can't unbox: expected object";
case Bailout_NonStringInput:
case Bailout_NonStringInputInvalidate:
return "can't unbox: expected string";
case Bailout_GuardThreadExclusive:
return "tried to write to non-thread local value";
case Bailout_ParallelUnsafe:
return "unsafe";
case Bailout_InitialState:
return "during function prologue";
case Bailout_DoubleOutput:
return "integer arithmetic overflowed to double";
case Bailout_ArgumentCheck:
return "unexpected argument type";
case Bailout_BoundsCheck:
return "out of bounds element access";
case Bailout_Neutered:
return "neutered typed object access";
case Bailout_ShapeGuard:
return "saw unexpected shape";
case Bailout_IonExceptionDebugMode:
// Fallthrough. This case cannot occur in parallel execution.
default:
MOZ_ASSUME_UNREACHABLE("Invalid BailoutKind");
}
}
@ -1086,29 +1143,6 @@ ForkJoinOperation::isInitialScript(HandleScript script)
return fun_->is<JSFunction>() && (fun_->as<JSFunction>().nonLazyScript() == script);
}
void
ForkJoinOperation::getBailoutScriptAndPc(MutableHandleScript bailoutScript, jsbytecode **bailoutPc,
ParallelBailoutCause *bailoutCause)
{
for (uint32_t i = 0; i < bailoutRecords_.length(); i++) {
switch (bailoutRecords_[i].cause) {
case ParallelBailoutNone:
case ParallelBailoutInterrupt:
continue;
default:
break;
}
if (bailoutRecords_[i].hasFrames()) {
RematerializedFrame *frame = bailoutRecords_[i].frames()[0];
bailoutScript.set(frame->script());
*bailoutPc = frame->pc();
*bailoutCause = bailoutRecords_[i].cause;
return;
}
}
}
static const char *
ValueToChar(JSContext *cx, HandleValue val, JSAutoByteString &bytes)
{
@ -1135,24 +1169,30 @@ ForkJoinOperation::reportBailoutWarnings()
}
for (uint32_t threadId = 0; threadId < bailoutRecords_.length(); threadId++) {
ParallelBailoutCause cause = bailoutRecords_[threadId].cause;
ParallelBailoutRecord &record = bailoutRecords_[threadId];
ParallelBailoutCause cause = record.cause;
BailoutKind ionBailoutKind = record.ionBailoutKind;
if (cause == ParallelBailoutNone)
continue;
if (bailoutRecords_[threadId].hasFrames()) {
Vector<RematerializedFrame *> &frames = bailoutRecords_[threadId].frames();
if (record.hasFrames()) {
Vector<RematerializedFrame *> &frames = record.frames();
if (!SpewEnabled(SpewBailouts)) {
RematerializedFrame *frame = frames[0];
RootedScript bailoutScript(cx_, frame->script());
SpewBailout(bailouts, bailoutScript, frame->pc(), cause);
JS_ReportWarning(cx_, "Bailed out of parallel operation: %s at %s:%u",
BailoutExplanation(cause), bailoutScript->filename(),
JS_ReportWarning(cx_, "Bailed out of parallel operation: %s%s at %s:%u",
BailoutExplanation(cause),
IonBailoutKindExplanation(cause, ionBailoutKind),
bailoutScript->filename(),
PCToLineNumber(bailoutScript, frame->pc()));
return true;
}
sp.printf("\n in thread %d due to %s", threadId, BailoutExplanation(cause));
sp.printf("\n in thread %u: %s%s",
threadId, BailoutExplanation(cause),
IonBailoutKindExplanation(cause, ionBailoutKind));
for (uint32_t frameIndex = 0; frameIndex < frames.length(); frameIndex++) {
RematerializedFrame *frame = frames[frameIndex];
@ -1237,10 +1277,6 @@ ForkJoinOperation::invalidateBailedOutScripts()
case ParallelBailoutInterrupt:
continue;
// An illegal write will not be made legal by invalidation.
case ParallelBailoutIllegalWrite:
continue;
// For other cases, consider invalidation.
default:
break;
@ -2354,10 +2390,10 @@ js::InExclusiveParallelSection()
bool
js::ParallelTestsShouldPass(JSContext *cx)
{
return jit::IsIonEnabled(cx) &&
jit::IsBaselineEnabled(cx) &&
!jit::js_JitOptions.eagerCompilation &&
jit::js_JitOptions.baselineUsesBeforeCompile != 0 &&
return IsIonEnabled(cx) &&
IsBaselineEnabled(cx) &&
!js_JitOptions.eagerCompilation &&
js_JitOptions.baselineUsesBeforeCompile != 0 &&
cx->runtime()->gcZeal() == 0;
}

View File

@ -17,6 +17,7 @@
#include "gc/GCInternals.h"
#include "jit/Ion.h"
#include "jit/IonTypes.h"
#ifdef DEBUG
#define FORKJOIN_SPEW
@ -281,44 +282,39 @@ bool ForkJoin(JSContext *cx, CallArgs &args);
// { everything else }
// |
// Interrupt
// / |
// Unsupported UnsupportedVM
// \ /
// |
// Execution
// |
// None
//
enum ParallelBailoutCause {
ParallelBailoutNone = 0,
ParallelBailoutUnsupported,
ParallelBailoutUnsupportedVM,
// Bailed out of JIT code during execution. The specific reason is found
// in the ionBailoutKind field in ParallelBailoutRecord below.
ParallelBailoutExecution,
// The periodic interrupt failed, which can mean that either
// another thread canceled, the user interrupted us, etc
// another thread canceled, the user interrupted us, etc.
ParallelBailoutInterrupt,
// Compiler returned Method_Skipped
// Compiler returned Method_Skipped.
ParallelBailoutCompilationSkipped,
// Compiler returned Method_CantCompile
// Compiler returned Method_CantCompile.
ParallelBailoutCompilationFailure,
// Propagating a failure, i.e., another thread requested the computation
// be aborted.
ParallelBailoutPropagate,
// An IC update failed
ParallelBailoutFailedIC,
// Heap busy flag was set during interrupt
ParallelBailoutHeapBusy,
// The main script was GCed before we could start executing.
ParallelBailoutMainScriptNotPresent,
ParallelBailoutCalledToUncompiledScript,
ParallelBailoutIllegalWrite,
ParallelBailoutAccessToIntrinsic,
// Went over the stack limit.
ParallelBailoutOverRecursed,
// True memory exhaustion. See js_ReportOutOfMemory.
ParallelBailoutOutOfMemory,
ParallelBailoutUnsupportedStringComparison,
// GC was requested on the tenured heap, which we cannot comply with in
// parallel.
ParallelBailoutRequestedGC,
ParallelBailoutRequestedZoneGC
};
@ -336,11 +332,18 @@ struct ParallelBailoutRecord
// Captured Ion frames at the point of bailout. Stored younger-to-older,
// i.e., the 0th frame is the youngest frame.
Vector<jit::RematerializedFrame *> *frames_;
// The reason for unsuccessful parallel execution.
ParallelBailoutCause cause;
// The more specific bailout reason if cause above is
// ParallelBailoutExecution.
jit::BailoutKind ionBailoutKind;
ParallelBailoutRecord()
: frames_(nullptr),
cause(ParallelBailoutNone)
cause(ParallelBailoutNone),
ionBailoutKind(jit::Bailout_Inevitable)
{ }
~ParallelBailoutRecord();
@ -360,6 +363,11 @@ struct ParallelBailoutRecord
}
}
void setIonBailoutKind(jit::BailoutKind kind) {
joinCause(ParallelBailoutExecution);
ionBailoutKind = kind;
}
void rematerializeFrames(ForkJoinContext *cx, jit::JitFrameIterator &frameIter);
void rematerializeFrames(ForkJoinContext *cx, jit::IonBailoutIterator &frameIter);
};
@ -427,9 +435,9 @@ class ForkJoinContext : public ThreadSafeContext
// Reports an unsupported operation, returning false if we are reporting
// an error. Otherwise drop the warning on the floor.
bool reportError(ParallelBailoutCause cause, unsigned report) {
bool reportError(unsigned report) {
if (report & JSREPORT_ERROR)
return setPendingAbortFatal(cause);
return setPendingAbortFatal(ParallelBailoutExecution);
return true;
}

View File

@ -70,14 +70,13 @@ class SavedFrame::AutoLookupRooter : public JS::CustomAutoRooter
/* static */ HashNumber
SavedFrame::HashPolicy::hash(const Lookup &lookup)
{
JSAtom *source = lookup.source;
JS::AutoCheckCannotGC nogc;
uint32_t hash = source->hasLatin1Chars()
? HashString(source->latin1Chars(nogc), source->length())
: HashString(source->twoByteChars(nogc), source->length());
return AddToHash(hash,
lookup.line,
// Assume that we can take line mod 2^32 without losing anything of
// interest. If that assumption changes, we'll just need to start with 0
// and add another overload of AddToHash with more arguments.
return AddToHash(lookup.line,
lookup.column,
lookup.source,
lookup.functionDisplayName,
SavedFramePtrHasher::hash(lookup.parent),
JSPrincipalsPtrHasher::hash(lookup.principals));
@ -99,22 +98,12 @@ SavedFrame::HashPolicy::match(SavedFrame *existing, const Lookup &lookup)
return false;
JSAtom *source = existing->getSource();
if (source->length() != lookup.source->length())
return false;
if (source != lookup.source)
return false;
JSAtom *functionDisplayName = existing->getFunctionDisplayName();
if (functionDisplayName) {
if (!lookup.functionDisplayName)
return false;
if (functionDisplayName->length() != lookup.functionDisplayName->length())
return false;
if (0 != CompareAtoms(functionDisplayName, lookup.functionDisplayName))
return false;
} else if (lookup.functionDisplayName) {
if (functionDisplayName != lookup.functionDisplayName)
return false;
}
return true;
}
@ -488,23 +477,26 @@ SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandleSav
// in js/src/jit-test/tests/saved-stacks/bug-1006876-too-much-recursion.js).
JS_CHECK_RECURSION_DONT_REPORT(cx, return false);
ScriptFrameIter thisFrame(iter);
RootedScript script(cx, iter.script());
jsbytecode *pc = iter.pc();
RootedFunction callee(cx, iter.maybeCallee());
// script and callee should keep compartment alive.
JSCompartment *compartment = iter.compartment();
RootedSavedFrame parentFrame(cx);
if (!insertFrames(cx, ++iter, &parentFrame))
return false;
LocationValue location;
if (!getLocation(cx, thisFrame.script(), thisFrame.pc(), &location))
if (!getLocation(cx, script, pc, &location))
return false;
JSFunction *callee = thisFrame.maybeCallee();
SavedFrame::AutoLookupRooter lookup(cx,
location.source,
location.line,
location.column,
callee ? callee->displayAtom() : nullptr,
parentFrame,
thisFrame.compartment()->principals);
compartment->principals);
frame.set(getOrCreateSavedFrame(cx, lookup));
return frame.get() != nullptr;

View File

@ -60,7 +60,6 @@
#include <algorithm>
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::layers;
using namespace mozilla::dom;
using namespace mozilla::layout;
@ -416,12 +415,12 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
if (!content) {
return;
}
CommonElementAnimationData* et =
ElementAnimationCollection* transitions =
nsTransitionManager::GetAnimationsForCompositor(content, aProperty);
CommonElementAnimationData* ea =
ElementAnimationCollection* animations =
nsAnimationManager::GetAnimationsForCompositor(content, aProperty);
if (!ea && !et) {
if (!animations && !transitions) {
return;
}
@ -476,16 +475,16 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
data = null_t();
}
if (et) {
AddAnimationsForProperty(aFrame, aProperty, et->mAnimations,
if (transitions) {
AddAnimationsForProperty(aFrame, aProperty, transitions->mAnimations,
aLayer, data, pending);
aLayer->SetAnimationGeneration(et->mAnimationGeneration);
aLayer->SetAnimationGeneration(transitions->mAnimationGeneration);
}
if (ea) {
AddAnimationsForProperty(aFrame, aProperty, ea->mAnimations,
if (animations) {
AddAnimationsForProperty(aFrame, aProperty, animations->mAnimations,
aLayer, data, pending);
aLayer->SetAnimationGeneration(ea->mAnimationGeneration);
aLayer->SetAnimationGeneration(animations->mAnimationGeneration);
}
}
@ -4702,7 +4701,7 @@ nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
nsCString message;
message.AppendLiteral("Performance warning: Async animation disabled because frame was not marked active for opacity animation");
CommonElementAnimationData::LogAsyncAnimationFailure(message,
ElementAnimationCollection::LogAsyncAnimationFailure(message,
Frame()->GetContent());
}
return false;
@ -4732,7 +4731,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
if (aLogAnimations) {
nsCString message;
message.AppendLiteral("Performance warning: Async animation disabled because frame was not marked active for transform animation");
CommonElementAnimationData::LogAsyncAnimationFailure(message,
ElementAnimationCollection::LogAsyncAnimationFailure(message,
aFrame->GetContent());
}
return false;
@ -4764,7 +4763,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
message.AppendLiteral(", ");
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.height));
message.Append(')');
CommonElementAnimationData::LogAsyncAnimationFailure(message,
ElementAnimationCollection::LogAsyncAnimationFailure(message,
aFrame->GetContent());
}
return false;

View File

@ -98,7 +98,6 @@
#endif
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::layout;
@ -257,20 +256,20 @@ TextAlignTrueEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
isTextAlignTrueEnabled ? eCSSKeyword_true : eCSSKeyword_UNKNOWN;
}
static CommonElementAnimationData*
static ElementAnimationCollection*
GetAnimationsOrTransitionsForCompositor(nsIContent* aContent,
nsIAtom* aAnimationProperty,
nsCSSProperty aProperty)
{
CommonElementAnimationData* animations =
static_cast<CommonElementAnimationData*>(
ElementAnimationCollection* collection =
static_cast<ElementAnimationCollection*>(
aContent->GetProperty(aAnimationProperty));
if (animations) {
bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
if (collection) {
bool propertyMatches = collection->HasAnimationOfProperty(aProperty);
if (propertyMatches &&
animations->CanPerformOnCompositorThread(
CommonElementAnimationData::CanAnimate_AllowPartial)) {
return animations;
collection->CanPerformOnCompositorThread(
ElementAnimationCollection::CanAnimate_AllowPartial)) {
return collection;
}
}
@ -289,18 +288,18 @@ nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
aContent, nsGkAtoms::transitionsProperty, aProperty);
}
static CommonElementAnimationData*
static ElementAnimationCollection*
GetAnimationsOrTransitions(nsIContent* aContent,
nsIAtom* aAnimationProperty,
nsCSSProperty aProperty)
{
CommonElementAnimationData* animations =
static_cast<CommonElementAnimationData*>(aContent->GetProperty(
ElementAnimationCollection* collection =
static_cast<ElementAnimationCollection*>(aContent->GetProperty(
aAnimationProperty));
if (animations) {
bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
if (collection) {
bool propertyMatches = collection->HasAnimationOfProperty(aProperty);
if (propertyMatches) {
return animations;
return collection;
}
}
return nullptr;
@ -328,10 +327,10 @@ nsLayoutUtils::HasCurrentAnimations(nsIContent* aContent,
TimeStamp now = aPresContext->RefreshDriver()->MostRecentRefresh();
CommonElementAnimationData* animations =
static_cast<CommonElementAnimationData*>(
ElementAnimationCollection* collection =
static_cast<ElementAnimationCollection*>(
aContent->GetProperty(aAnimationProperty));
return (animations && animations->HasCurrentAnimationsAt(now));
return (collection && collection->HasCurrentAnimationsAt(now));
}
static gfxSize
@ -392,14 +391,14 @@ GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
gfxSize& aMaxScale,
gfxSize& aMinScale)
{
CommonElementAnimationData* animations =
ElementAnimationCollection* collection =
GetAnimationsOrTransitionsForCompositor(aContent, aAnimationProperty,
eCSSProperty_transform);
if (!animations)
if (!collection)
return;
for (uint32_t animIdx = animations->mAnimations.Length(); animIdx-- != 0; ) {
mozilla::ElementAnimation* anim = animations->mAnimations[animIdx];
for (uint32_t animIdx = collection->mAnimations.Length(); animIdx-- != 0; ) {
mozilla::ElementAnimation* anim = collection->mAnimations[animIdx];
if (anim->IsFinishedTransition()) {
continue;
}

View File

@ -1010,10 +1010,10 @@ nsBlockReflowState::ClearFloats(nscoord aBCoord, uint8_t aBreakType,
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
aReplacedBlock);
if (std::max(floatAvailableSpace.mRect.x - ContentIStart(),
replacedWidth.marginLeft) +
replacedWidth.marginLeft) +
replacedWidth.borderBoxWidth +
std::max(ContentIEnd() - floatAvailableSpace.mRect.XMost(),
replacedWidth.marginRight) <=
std::max(ContentIEnd() - floatAvailableSpace.mRect.XMost(),
replacedWidth.marginRight) <=
ContentISize()) {
break;
}

View File

@ -580,6 +580,125 @@ static void GetOtherValuesForProperty(const uint32_t aParserVariant,
}
}
NS_IMETHODIMP
inDOMUtils::GetSubpropertiesForCSSProperty(const nsAString& aProperty,
uint32_t* aLength,
char16_t*** aValues)
{
nsCSSProperty propertyID =
nsCSSProps::LookupProperty(aProperty, nsCSSProps::eEnabledForAllContent);
if (propertyID == eCSSProperty_UNKNOWN) {
return NS_ERROR_FAILURE;
}
nsTArray<nsString> array;
if (!nsCSSProps::IsShorthand(propertyID)) {
*aValues = static_cast<char16_t**>(nsMemory::Alloc(sizeof(char16_t*)));
(*aValues)[0] = ToNewUnicode(nsCSSProps::GetStringValue(propertyID));
*aLength = 1;
return NS_OK;
}
// Count up how many subproperties we have.
size_t subpropCount = 0;
for (const nsCSSProperty *props = nsCSSProps::SubpropertyEntryFor(propertyID);
*props != eCSSProperty_UNKNOWN; ++props) {
++subpropCount;
}
*aValues =
static_cast<char16_t**>(nsMemory::Alloc(subpropCount * sizeof(char16_t*)));
*aLength = subpropCount;
for (const nsCSSProperty *props = nsCSSProps::SubpropertyEntryFor(propertyID),
*props_start = props;
*props != eCSSProperty_UNKNOWN; ++props) {
(*aValues)[props-props_start] = ToNewUnicode(nsCSSProps::GetStringValue(*props));
}
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::CssPropertyIsShorthand(const nsAString& aProperty, bool *_retval)
{
nsCSSProperty propertyID =
nsCSSProps::LookupProperty(aProperty, nsCSSProps::eEnabledForAllContent);
if (propertyID == eCSSProperty_UNKNOWN) {
return NS_ERROR_FAILURE;
}
*_retval = nsCSSProps::IsShorthand(propertyID);
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::CssPropertySupportsType(const nsAString& aProperty, uint32_t aType,
bool *_retval)
{
nsCSSProperty propertyID =
nsCSSProps::LookupProperty(aProperty, nsCSSProps::eEnabledForAllContent);
if (propertyID == eCSSProperty_UNKNOWN) {
return NS_ERROR_FAILURE;
}
uint32_t variant;
switch (aType) {
case TYPE_LENGTH:
variant = VARIANT_LENGTH;
break;
case TYPE_PERCENTAGE:
variant = VARIANT_PERCENT;
break;
case TYPE_COLOR:
variant = VARIANT_COLOR;
break;
case TYPE_URL:
variant = VARIANT_URL;
break;
case TYPE_ANGLE:
variant = VARIANT_ANGLE;
break;
case TYPE_FREQUENCY:
variant = VARIANT_FREQUENCY;
break;
case TYPE_TIME:
variant = VARIANT_TIME;
break;
case TYPE_GRADIENT:
variant = VARIANT_GRADIENT;
break;
case TYPE_TIMING_FUNCTION:
variant = VARIANT_TIMING_FUNCTION;
break;
case TYPE_IMAGE_RECT:
variant = VARIANT_IMAGE_RECT;
break;
case TYPE_NUMBER:
// Include integers under "number"?
variant = VARIANT_NUMBER | VARIANT_INTEGER;
break;
default:
// Unknown type
return NS_ERROR_NOT_AVAILABLE;
}
if (!nsCSSProps::IsShorthand(propertyID)) {
*_retval = nsCSSProps::ParserVariant(propertyID) & variant;
return NS_OK;
}
for (const nsCSSProperty* props = nsCSSProps::SubpropertyEntryFor(propertyID);
*props != eCSSProperty_UNKNOWN; ++props) {
if (nsCSSProps::ParserVariant(*props) & variant) {
*_retval = true;
return NS_OK;
}
}
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::GetCSSValuesForProperty(const nsAString& aProperty,
uint32_t* aLength,

View File

@ -16,7 +16,7 @@ interface nsIDOMFontFaceList;
interface nsIDOMRange;
interface nsIDOMCSSStyleSheet;
[scriptable, uuid(948792a7-b786-4a2c-910d-f55b0773c2ca)]
[scriptable, uuid(5d8a1458-4b76-4aee-bf46-4eca223a01b2)]
interface inIDOMUtils : nsISupports
{
// CSS utilities
@ -68,6 +68,38 @@ interface inIDOMUtils : nsISupports
jsval colorNameToRGB(in DOMString aColorName);
AString rgbToColorName(in octet aR, in octet aG, in octet aB);
// Utilities for obtaining information about a CSS property.
// Get a list of the longhands corresponding to the given CSS property. If
// the property is a longhand already, just returns the property itself.
// Throws on unsupported property names.
void getSubpropertiesForCSSProperty(in AString aProperty,
[optional] out unsigned long aLength,
[array, size_is(aLength), retval] out wstring aValues);
// Check whether a given CSS property is a shorthand. Throws on unsupported
// property names.
bool cssPropertyIsShorthand(in AString aProperty);
// Check whether values of the given type are valid values for the property.
// For shorthands, checks whether there's a corresponding longhand property
// that accepts values of this type. Throws on unsupported properties or
// unknown types.
//
// This function may incorrectly return false for properties that use custom
// parsing functions instead of table-driven parsing.
const unsigned long TYPE_LENGTH = 0;
const unsigned long TYPE_PERCENTAGE = 1;
const unsigned long TYPE_COLOR = 2;
const unsigned long TYPE_URL = 3;
const unsigned long TYPE_ANGLE = 4;
const unsigned long TYPE_FREQUENCY = 5;
const unsigned long TYPE_TIME = 6;
const unsigned long TYPE_GRADIENT = 7;
const unsigned long TYPE_TIMING_FUNCTION = 8;
const unsigned long TYPE_IMAGE_RECT = 9;
const unsigned long TYPE_NUMBER = 10;
bool cssPropertySupportsType(in AString aProperty, in unsigned long type);
// DOM Node utilities
boolean isIgnorableWhitespace(in nsIDOMCharacterData aDataNode);
// Returns the "parent" of a node. The parent of a document node is the

View File

@ -11,5 +11,6 @@ support-files = bug856317.css
[test_bug806192.html]
[test_bug856317.html]
[test_bug877690.html]
[test_bug1006595.html]
[test_get_all_style_sheets.html]
[test_isinheritableproperty.html]

View File

@ -0,0 +1,117 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1006595
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1006595</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1006595 **/
function arraysEqual(arr1, arr2, message) {
is(arr1.length, arr2.length, message + " length");
for (var i = 0; i < arr1.length; ++i) {
is(arr1[i], arr2[i], message + " element at index " + i);
}
}
var utils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"]
.getService(SpecialPowers.Ci.inIDOMUtils);
var paddingSubProps = utils.getSubpropertiesForCSSProperty("padding");
arraysEqual(paddingSubProps,
[ "padding-top",
"padding-right-value",
"padding-bottom",
"padding-left-value",
"padding-left-ltr-source", "padding-left-rtl-source",
"padding-right-ltr-source", "padding-right-rtl-source" ],
"'padding' subproperties");
var displaySubProps = utils.getSubpropertiesForCSSProperty("color");
arraysEqual(displaySubProps, [ "color" ],
"'color' subproperties");
ok(utils.cssPropertyIsShorthand("padding"), "'padding' is a shorthand")
ok(!utils.cssPropertyIsShorthand("color"), "'color' is not a shorthand")
ok(utils.cssPropertySupportsType("padding", utils.TYPE_LENGTH),
"'padding' can be a length");
ok(!utils.cssPropertySupportsType("padding", utils.TYPE_COLOR),
"'padding' can't be a color");
ok(utils.cssPropertySupportsType("padding", utils.TYPE_PERCENTAGE),
"'padding' can be a percentage");
ok(!utils.cssPropertySupportsType("color", utils.TYPE_PERCENTAGE),
"'color' can't be a percentage");
ok(utils.cssPropertySupportsType("color", utils.TYPE_COLOR),
"'color' can be a color");
ok(utils.cssPropertySupportsType("background", utils.TYPE_COLOR),
"'background' can be a color");
ok(!utils.cssPropertySupportsType("background-image", utils.TYPE_COLOR),
"'background-image' can't be a color");
ok(utils.cssPropertySupportsType("background-image", utils.TYPE_URL),
"'background-image' can be a URL");
ok(utils.cssPropertySupportsType("background", utils.TYPE_URL),
"'background' can be a URL");
ok(!utils.cssPropertySupportsType("background-color", utils.TYPE_URL),
"'background-color' can't be a URL");
// There are no properties claiming to be of TYPE_ANGLE. image-orientation
// would be, but it doesn't use table-driven parsing.
// There are no properties claiming to be of TYPE_FREQUENCY
ok(utils.cssPropertySupportsType("transition", utils.TYPE_TIME),
"'transition' can be a time");
ok(utils.cssPropertySupportsType("transition-duration", utils.TYPE_TIME),
"'transition-duration' can be a time");
ok(!utils.cssPropertySupportsType("background-color", utils.TYPE_TIME),
"'background-color' can't be a time");
ok(utils.cssPropertySupportsType("background-image", utils.TYPE_GRADIENT),
"'background-image' can be a gradient");
ok(utils.cssPropertySupportsType("background", utils.TYPE_GRADIENT),
"'background' can be a gradient");
ok(!utils.cssPropertySupportsType("background-color", utils.TYPE_GRADIENT),
"'background-color' can't be a gradient");
ok(utils.cssPropertySupportsType("transition", utils.TYPE_TIMING_FUNCTION),
"'transition' can be a timing function");
ok(utils.cssPropertySupportsType("transition-timing-function",
utils.TYPE_TIMING_FUNCTION),
"'transition-duration' can be a timing function");
ok(!utils.cssPropertySupportsType("background-color",
utils.TYPE_TIMING_FUNCTION),
"'background-color' can't be a timing function");
ok(utils.cssPropertySupportsType("background-image", utils.TYPE_IMAGE_RECT),
"'background-image' can be an image rect");
ok(utils.cssPropertySupportsType("background", utils.TYPE_IMAGE_RECT),
"'background' can be an image rect");
ok(!utils.cssPropertySupportsType("background-color", utils.TYPE_IMAGE_RECT),
"'background-color' can't be an image rect");
ok(utils.cssPropertySupportsType("z-index", utils.TYPE_NUMBER),
"'z-index' can be a number");
ok(utils.cssPropertySupportsType("line-height", utils.TYPE_NUMBER),
"'line-height' can be a number");
ok(!utils.cssPropertySupportsType("background-color", utils.TYPE_NUMBER),
"'background-color' can't be a number");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1006595">Mozilla Bug 1006595</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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