mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
7fdfacf9ee
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
BIN
browser/components/loop/content/shared/sounds/Firefox-Long.ogg
Normal file
BIN
browser/components/loop/content/shared/sounds/Firefox-Long.ogg
Normal file
Binary file not shown.
@ -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)
|
||||
|
@ -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()});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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", "");
|
||||
},
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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]
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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]
|
||||
|
||||
|
||||
|
6
content/media/test/parser.vtt
Normal file
6
content/media/test/parser.vtt
Normal file
@ -0,0 +1,6 @@
|
||||
WEBVTT
|
||||
|
||||
00:00.500 --> 00:00.700
|
||||
Test
|
||||
00:00.500 --> 00:00.700
|
||||
Stuff
|
@ -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) {
|
||||
|
44
content/media/test/test_vttparser.html
Normal file
44
content/media/test/test_vttparser.html
Normal 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>
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
187
dom/media/tests/mochitest/long.js
Normal file
187
dom/media/tests/mochitest/long.js
Normal 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);
|
||||
}
|
||||
]
|
||||
}
|
||||
|
11
dom/media/tests/mochitest/steeplechase_long.ini
Normal file
11
dom/media/tests/mochitest/steeplechase_long.ini
Normal 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]
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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()));
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
117
layout/inspector/tests/test_bug1006595.html
Normal file
117
layout/inspector/tests/test_bug1006595.html
Normal 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
Loading…
Reference in New Issue
Block a user