Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-01-21 15:15:33 +01:00
commit 49efc42e97
663 changed files with 44658 additions and 30516 deletions

View File

@ -22,4 +22,5 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1121297 - Converted VolatileBuffer's CPP tests to GTests
Bug 1100184 - Lots of file moves from the /netwerk flattening and zero faith
in the build system to properly handle them.

View File

@ -117,7 +117,7 @@ function checkDebuggerPort() {
function initResponsiveDesign() {
Cu.import('resource:///modules/devtools/responsivedesign.jsm');
ResponsiveUIManager.on('on', function(event, {tab:tab}) {
let responsive = tab.__responsiveUI;
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
let document = tab.ownerDocument;
// Only tweak reponsive mode for shell.html tabs.
@ -137,7 +137,7 @@ function initResponsiveDesign() {
}, true);
// Enable touch events
browserWindow.gBrowser.selectedTab.__responsiveUI.enableTouch();
responsive.enableTouch();
});
// Automatically toggle responsive design mode

View File

@ -148,7 +148,8 @@ window.addEventListener('ContentStart', function() {
let chromewidth = window.outerWidth - window.innerWidth;
let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
if (isMulet) {
let responsive = browserWindow.gBrowser.selectedTab.__responsiveUI;
let tab = browserWindow.gBrowser.selectedTab;
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
responsive.setSize((Math.round(width * scale) + 16*2),
(Math.round(height * scale) + controlsHeight + 61));
} else {

View File

@ -29,6 +29,7 @@ int main(int argc, char* argv[], char* envp[]){
}
full_profile_path = (char*) malloc(strlen(cwd) + strlen(GAIA_PATH) + 2);
if (!full_profile_path) {
free(full_path);
error(NOMEM);
return -2;
}

View File

@ -260,6 +260,7 @@ let MozLoopServiceInternal = {
*/
setError: function(errorType, error, actionCallback = null) {
log.debug("setError", errorType, error);
log.trace();
let messageString, detailsString, detailsButtonLabelString, detailsButtonCallback;
const NETWORK_ERRORS = [
Cr.NS_ERROR_CONNECTION_REFUSED,
@ -300,15 +301,24 @@ let MozLoopServiceInternal = {
}
error.friendlyMessage = this.localizedStrings.get(messageString);
error.friendlyDetails = detailsString ?
this.localizedStrings.get(detailsString) :
null;
// Default to the generic "retry_button" text even though the button won't be shown if
// error.friendlyDetails is null.
error.friendlyDetailsButtonLabel = detailsButtonLabelString ?
this.localizedStrings.get(detailsButtonLabelString) :
null;
this.localizedStrings.get("retry_button");
error.friendlyDetailsButtonCallback = actionCallback || detailsButtonCallback || null;
if (detailsString) {
error.friendlyDetails = this.localizedStrings.get(detailsString);
} else if (error.friendlyDetailsButtonCallback) {
// If we have a retry callback but no details use the generic try again string.
error.friendlyDetails = this.localizedStrings.get("generic_failure_no_reason2");
} else {
error.friendlyDetails = null;
}
gErrors.set(errorType, error);
this.notifyStatusChanged();
},
@ -1219,7 +1229,8 @@ this.MozLoopService = {
deferredInitialization.resolve("initialized to logged-in status");
}, error => {
log.debug("MozLoopService: error logging in using cached auth token");
MozLoopServiceInternal.setError("login", error);
let retryFunc = () => MozLoopServiceInternal.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA);
MozLoopServiceInternal.setError("login", error, retryFunc);
deferredInitialization.reject("error logging in using cached auth token");
});
yield completedPromise;
@ -1421,27 +1432,17 @@ this.MozLoopService = {
MozLoopServiceInternal.clearError("profile");
return MozLoopServiceInternal.fxAOAuthTokenData;
});
}).then(tokenData => {
let client = new FxAccountsProfileClient({
serverURL: gFxAOAuthClient.parameters.profile_uri,
token: tokenData.access_token
});
client.fetchProfile().then(result => {
MozLoopServiceInternal.fxAOAuthProfile = result;
}, error => {
log.error("Failed to retrieve profile", error);
this.setError("profile", error);
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.notifyStatusChanged();
});
}).then(Task.async(function* fetchProfile(tokenData) {
yield MozLoopService.fetchFxAProfile(tokenData);
return tokenData;
}).catch(error => {
})).catch(error => {
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.deferredRegistrations.delete(LOOP_SESSION_TYPE.FXA);
throw error;
}).catch((error) => {
MozLoopServiceInternal.setError("login", error);
MozLoopServiceInternal.setError("login", error,
() => MozLoopService.logInToFxA());
// Re-throw for testing
throw error;
});
@ -1485,6 +1486,30 @@ this.MozLoopService = {
}
}),
/**
* Fetch/update the FxA Profile for the logged in user.
*
* @return {Promise} resolving if the profile information was succesfully retrieved
* rejecting if the profile information couldn't be retrieved.
* A profile error is registered.
**/
fetchFxAProfile: function() {
log.debug("fetchFxAProfile");
let client = new FxAccountsProfileClient({
serverURL: gFxAOAuthClient.parameters.profile_uri,
token: MozLoopServiceInternal.fxAOAuthTokenData.access_token
});
return client.fetchProfile().then(result => {
MozLoopServiceInternal.fxAOAuthProfile = result;
MozLoopServiceInternal.clearError("profile");
}, error => {
log.error("Failed to retrieve profile", error, this.fetchFxAProfile.bind(this));
MozLoopServiceInternal.setError("profile", error);
MozLoopServiceInternal.fxAOAuthProfile = null;
MozLoopServiceInternal.notifyStatusChanged();
});
},
openFxASettings: Task.async(function() {
try {
let fxAOAuthClient = yield MozLoopServiceInternal.promiseFxAOAuthClient();

View File

@ -296,8 +296,9 @@ add_task(function* basicAuthorizationAndRegistration() {
is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in");
info("Login");
statusChangedPromise = promiseObserverNotified("loop-status-changed", "login");
let tokenData = yield MozLoopService.logInToFxA();
yield promiseObserverNotified("loop-status-changed", "login");
yield statusChangedPromise;
ise(tokenData.access_token, "code1_access_token", "Check access_token");
ise(tokenData.scope, "profile", "Check scope");
ise(tokenData.token_type, "bearer", "Check token_type");

View File

@ -74,7 +74,6 @@ add_task(function* guest_401() {
Assert.strictEqual(err.code, 401);
Assert.strictEqual(err.friendlyMessage, getLoopString("session_expired_error_description"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});
@ -115,7 +114,6 @@ add_task(function* error_404() {
Assert.strictEqual(err.code, 404);
Assert.strictEqual(err.friendlyMessage, getLoopString("generic_failure_title"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});
@ -149,7 +147,6 @@ add_task(function* profile_500() {
Assert.strictEqual(err.code, 500);
Assert.strictEqual(err.friendlyMessage, getLoopString("problem_accessing_account"));
Assert.equal(err.friendlyDetails, null);
Assert.equal(err.friendlyDetailsButtonLabel, null);
});
});

View File

@ -77,6 +77,9 @@ add_task(function test_initialize_with_invalid_fxa_token() {
"FXA profile pref should be cleared if token was invalid");
Assert.ok(MozLoopServiceInternal.errors.has("login"),
"Initialization error should have been reported to UI");
Assert.ok(MozLoopServiceInternal.errors.has("login"));
Assert.ok(MozLoopServiceInternal.errors.get("login").friendlyDetailsButtonCallback,
"Check that there is a retry callback");
});
});

View File

@ -1038,7 +1038,7 @@ PlacesToolbar.prototype = {
else {
button = document.createElement("toolbarbutton");
button.className = "bookmark-item";
button.setAttribute("label", aChild.title);
button.setAttribute("label", aChild.title || "");
let icon = aChild.icon;
if (icon)
button.setAttribute("image",
@ -1866,7 +1866,7 @@ PlacesPanelMenuView.prototype = {
button.className = "bookmark-item";
if (typeof this.options.extraClasses.entry == "string")
button.classList.add(this.options.extraClasses.entry);
button.setAttribute("label", aChild.title);
button.setAttribute("label", aChild.title || "");
let icon = aChild.icon;
if (icon)
button.setAttribute("image",

View File

@ -4,7 +4,8 @@
EXTRA_JS_MODULES.devtools += [
'resize-commands.js',
'responsivedesign.jsm',
'responsivedesign-child.js',
'responsivedesign.jsm'
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -0,0 +1,129 @@
/* 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/. */
const Ci = Components.interfaces;
const gDeviceSizeWasPageSize = docShell.deviceSizeIsPageSize;
const gFloatingScrollbarsStylesheet = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
let gRequiresFloatingScrollbars;
let active = false;
addMessageListener("ResponsiveMode:Start", startResponsiveMode);
addMessageListener("ResponsiveMode:Stop", stopResponsiveMode);
function startResponsiveMode({data:data}) {
if (active) {
return;
}
addMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
addMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_ALL);
docShell.deviceSizeIsPageSize = true;
gRequiresFloatingScrollbars = data.requiresFloatingScrollbars;
// At this point, a content viewer might not be loaded for this
// docshell. makeScrollbarsFloating will be triggered by onLocationChange.
if (docShell.contentViewer) {
makeScrollbarsFloating();
}
active = true;
sendAsyncMessage("ResponsiveMode:Start:Done");
}
function notifiyOnResize() {
content.addEventListener("resize", () => {
sendAsyncMessage("ResponsiveMode:OnContentResize");
}, false);
sendAsyncMessage("ResponsiveMode:NotifyOnResize:Done");
}
function stopResponsiveMode() {
if (!active) {
return;
}
active = false;
removeMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
removeMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
webProgress.removeProgressListener(WebProgressListener);
docShell.deviceSizeIsPageSize = gDeviceSizeWasPageSize;
restoreScrollbars();
sendAsyncMessage("ResponsiveMode:Stop:Done");
}
function makeScrollbarsFloating() {
if (!gRequiresFloatingScrollbars) {
return;
}
let allDocShells = [docShell];
for (let i = 0; i < docShell.childCount; i++) {
let child = docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell);
allDocShells.push(child);
}
for (let d of allDocShells) {
let win = d.contentViewer.DOMDocument.defaultView;
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.loadSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
} catch(e) { }
}
flushStyle();
}
function restoreScrollbars() {
let allDocShells = [docShell];
for (let i = 0; i < docShell.childCount; i++) {
allDocShells.push(docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell));
}
for (let d of allDocShells) {
let win = d.contentViewer.DOMDocument.defaultView;
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.removeSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
} catch(e) { }
}
flushStyle();
}
function flushStyle() {
// Force presContext destruction
let isSticky = docShell.contentViewer.sticky;
docShell.contentViewer.sticky = false;
docShell.contentViewer.hide();
docShell.contentViewer.show();
docShell.contentViewer.sticky = isSticky;
}
function screenshot() {
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let width = content.innerWidth;
let height = content.innerHeight;
canvas.mozOpaque = true;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawWindow(content, content.scrollX, content.scrollY, width, height, "#fff");
sendAsyncMessage("ResponsiveMode:RequestScreenshot:Done", canvas.toDataURL());
}
let WebProgressListener = {
onLocationChange: function onLocationChange(aWebProgress) {
makeScrollbarsFloating();
},
QueryInterface: function QueryInterface(aIID) {
if (aIID.equals(Ci.nsIWebProgressListener) ||
aIID.equals(Ci.nsISupportsWeakReference) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
sendAsyncMessage("ResponsiveMode:ChildScriptReady");

View File

@ -10,8 +10,8 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/FloatingScrollbars.jsm");
Cu.import("resource://gre/modules/devtools/event-emitter.js");
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
@ -33,6 +33,8 @@ const ROUND_RATIO = 10;
const INPUT_PARSER = /(\d+)[^\d]+(\d+)/;
let ActiveTabs = new Map();
this.ResponsiveUIManager = {
/**
* Check if the a tab is in a responsive mode.
@ -43,8 +45,8 @@ this.ResponsiveUIManager = {
* @param aTab the tab targeted.
*/
toggle: function(aWindow, aTab) {
if (aTab.__responsiveUI) {
aTab.__responsiveUI.close();
if (this.isActiveForTab(aTab)) {
ActiveTabs.get(aTab).close();
} else {
new ResponsiveUI(aWindow, aTab);
}
@ -56,7 +58,14 @@ this.ResponsiveUIManager = {
* @param aTab the tab targeted.
*/
isActiveForTab: function(aTab) {
return !!aTab.__responsiveUI;
return ActiveTabs.has(aTab);
},
/**
* Return the responsive UI controller for a tab.
*/
getResponsiveUIForTab: function(aTab) {
return ActiveTabs.get(aTab);
},
/**
@ -70,19 +79,19 @@ this.ResponsiveUIManager = {
handleGcliCommand: function(aWindow, aTab, aCommand, aArgs) {
switch (aCommand) {
case "resize to":
if (!aTab.__responsiveUI) {
if (!this.isActiveForTab(aTab)) {
new ResponsiveUI(aWindow, aTab);
}
aTab.__responsiveUI.setSize(aArgs.width, aArgs.height);
ActiveTabs.get(aTab).setSize(aArgs.width, aArgs.height);
break;
case "resize on":
if (!aTab.__responsiveUI) {
if (!this.isActiveForTab(aTab)) {
new ResponsiveUI(aWindow, aTab);
}
break;
case "resize off":
if (aTab.__responsiveUI) {
aTab.__responsiveUI.close();
if (this.isActiveForTab(aTab)) {
ActiveTabs.get(aTab).close();
}
break;
case "resize toggle":
@ -115,13 +124,28 @@ function ResponsiveUI(aWindow, aTab)
{
this.mainWindow = aWindow;
this.tab = aTab;
this.mm = this.tab.linkedBrowser.messageManager;
this.tabContainer = aWindow.gBrowser.tabContainer;
this.browser = aTab.linkedBrowser;
this.chromeDoc = aWindow.document;
this.container = aWindow.gBrowser.getBrowserContainer(this.browser);
this.stack = this.container.querySelector(".browserStack");
this._telemetry = new Telemetry();
this._floatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
this.e10s = !this.browser.contentWindow;
let childOn = () => {
this.mm.removeMessageListener("ResponsiveMode:Start:Done", childOn);
ResponsiveUIManager.emit("on", { tab: this.tab });
}
this.mm.addMessageListener("ResponsiveMode:Start:Done", childOn);
let requiresFloatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
this.mm.loadFrameScript("resource:///modules/devtools/responsivedesign-child.js", true);
this.mm.addMessageListener("ResponsiveMode:ChildScriptReady", () => {
this.mm.sendAsyncMessage("ResponsiveMode:Start", {
requiresFloatingScrollbars: requiresFloatingScrollbars
});
});
// Try to load presets from prefs
if (Services.prefs.prefHasUserValue("devtools.responsiveUI.presets")) {
@ -163,8 +187,6 @@ function ResponsiveUI(aWindow, aTab)
this.stack.setAttribute("responsivemode", "true");
// Let's bind some callbacks.
this.bound_onPageLoad = this.onPageLoad.bind(this);
this.bound_onPageUnload = this.onPageUnload.bind(this);
this.bound_presetSelected = this.presetSelected.bind(this);
this.bound_handleManualInput = this.handleManualInput.bind(this);
this.bound_addPreset = this.addPreset.bind(this);
@ -184,41 +206,22 @@ function ResponsiveUI(aWindow, aTab)
this.buildUI();
this.checkMenus();
this.docShell = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
this._deviceSizeWasPageSize = this.docShell.deviceSizeIsPageSize;
this.docShell.deviceSizeIsPageSize = true;
try {
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
this.rotate();
}
} catch(e) {}
if (this._floatingScrollbars)
switchToFloatingScrollbars(this.tab);
this.tab.__responsiveUI = this;
ActiveTabs.set(aTab, this);
this._telemetry.toolOpened("responsive");
// Touch events support
this.touchEnableBefore = false;
this.touchEventHandler = new TouchEventHandler(this.browser);
this.browser.addEventListener("load", this.bound_onPageLoad, true);
this.browser.addEventListener("unload", this.bound_onPageUnload, true);
if (this.browser.contentWindow.document &&
this.browser.contentWindow.document.readyState == "complete") {
this.onPageLoad();
if (!this.e10s) {
// Touch events support
this.touchEnableBefore = false;
this.touchEventHandler = new TouchEventHandler(this.browser);
}
// E10S: We should be using target here. See bug 1028234
ResponsiveUIManager.emit("on", { tab: this.tab });
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
showDoorhanger({
window: this.mainWindow,
@ -239,45 +242,14 @@ ResponsiveUI.prototype = {
}
},
/**
* Window onload / onunload
*/
onPageLoad: function() {
this.touchEventHandler = new TouchEventHandler(this.browser);
if (this.touchEnableBefore) {
this.enableTouch();
}
},
onPageUnload: function(evt) {
// Ignore sub frames unload events
if (evt.target != this.browser.contentDocument)
return;
if (this.closing)
return;
if (this.touchEventHandler) {
this.touchEnableBefore = this.touchEventHandler.enabled;
this.disableTouch();
delete this.touchEventHandler;
}
},
/**
* Destroy the nodes. Remove listeners. Reset the style.
*/
close: function RUI_unload() {
close: function RUI_close() {
if (this.closing)
return;
this.closing = true;
this.docShell.deviceSizeIsPageSize = this._deviceSizeWasPageSize;
this.browser.removeEventListener("load", this.bound_onPageLoad, true);
this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
if (this._floatingScrollbars)
switchToNativeScrollbars(this.tab);
this.unCheckMenus();
// Reset style of the stack.
let style = "max-width: none;" +
@ -296,10 +268,12 @@ ResponsiveUI.prototype = {
this.tabContainer.removeEventListener("TabSelect", this);
this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true);
this.touchbutton.removeEventListener("command", this.bound_touch, true);
this.closebutton.removeEventListener("command", this.bound_close, true);
this.addbutton.removeEventListener("command", this.bound_addPreset, true);
this.removebutton.removeEventListener("command", this.bound_removePreset, true);
if (!this.e10s) {
this.touchbutton.removeEventListener("command", this.bound_touch, true);
}
// Removed elements.
this.container.removeChild(this.toolbar);
@ -317,13 +291,40 @@ ResponsiveUI.prototype = {
this.container.removeAttribute("responsivemode");
this.stack.removeAttribute("responsivemode");
delete this.docShell;
delete this.tab.__responsiveUI;
if (this.touchEventHandler)
ActiveTabs.delete(this.tab);
if (!this.e10s && this.touchEventHandler) {
this.touchEventHandler.stop();
}
this._telemetry.toolClosed("responsive");
// E10S: We should be using target here. See bug 1028234
ResponsiveUIManager.emit("off", { tab: this.tab });
let childOff = () => {
this.mm.removeMessageListener("ResponsiveMode:Stop:Done", childOff);
ResponsiveUIManager.emit("off", { tab: this.tab });
}
this.mm.addMessageListener("ResponsiveMode:Stop:Done", childOff);
this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
},
/**
* Notify when the content has been resized. Only used in tests.
*/
_test_notifyOnResize: function() {
let deferred = promise.defer();
let mm = this.mm;
this.bound_onContentResize = this.onContentResize.bind(this);
mm.addMessageListener("ResponsiveMode:OnContentResize", this.bound_onContentResize);
mm.sendAsyncMessage("ResponsiveMode:NotifyOnResize");
mm.addMessageListener("ResponsiveMode:NotifyOnResize:Done", function onListeningResize() {
mm.removeMessageListener("ResponsiveMode:NotifyOnResize:Done", onListeningResize);
deferred.resolve();
});
return deferred.promise;
},
onContentResize: function() {
ResponsiveUIManager.emit("contentResize", { tab: this.tab });
},
/**
@ -427,12 +428,6 @@ ResponsiveUI.prototype = {
this.screenshotbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-screenshot";
this.screenshotbutton.addEventListener("command", this.bound_screenshot, true);
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
this.touchbutton.setAttribute("tabindex", "0");
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
this.touchbutton.addEventListener("command", this.bound_touch, true);
this.closebutton = this.chromeDoc.createElement("toolbarbutton");
this.closebutton.setAttribute("tabindex", "0");
this.closebutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-close";
@ -442,7 +437,16 @@ ResponsiveUI.prototype = {
this.toolbar.appendChild(this.closebutton);
this.toolbar.appendChild(this.menulist);
this.toolbar.appendChild(this.rotatebutton);
this.toolbar.appendChild(this.touchbutton);
if (!this.e10s) {
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
this.touchbutton.setAttribute("tabindex", "0");
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
this.touchbutton.addEventListener("command", this.bound_touch, true);
this.toolbar.appendChild(this.touchbutton);
}
this.toolbar.appendChild(this.screenshotbutton);
// Resizers
@ -583,8 +587,9 @@ ResponsiveUI.prototype = {
this.selectedItem = menuitem;
}
if (preset.custom)
if (preset.custom) {
this.customMenuitem = menuitem;
}
this.setMenuLabel(menuitem, preset);
fragment.appendChild(menuitem);
@ -662,9 +667,7 @@ ResponsiveUI.prototype = {
if (!promptOk) {
// Prompt has been cancelled
let menuitem = this.customMenuitem;
this.menulist.selectedItem = menuitem;
this.currentPresetKey = this.customPreset.key;
this.menulist.selectedItem = this.selectedItem;
return;
}
@ -762,21 +765,7 @@ ResponsiveUI.prototype = {
* @param aFileName name of the screenshot file (used for tests).
*/
screenshot: function RUI_screenshot(aFileName) {
let window = this.browser.contentWindow;
let document = window.document;
let canvas = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let width = window.innerWidth;
let height = window.innerHeight;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawWindow(window, window.scrollX, window.scrollY, width, height, "#fff");
let filename = aFileName;
if (!filename) {
let date = new Date();
let month = ("0" + (date.getMonth() + 1)).substr(-2, 2);
@ -785,12 +774,15 @@ ResponsiveUI.prototype = {
let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
filename = this.strings.formatStringFromName("responsiveUI.screenshotGeneratedFilename", [dateString, timeString], 2);
}
canvas.toBlob(blob => {
let chromeWindow = this.chromeDoc.defaultView;
let url = chromeWindow.URL.createObjectURL(blob);
chromeWindow.saveURL(url, filename + ".png", null, true, true, document.documentURIObject, document);
});
let mm = this.tab.linkedBrowser.messageManager;
let chromeWindow = this.chromeDoc.defaultView;
let doc = chromeWindow.document;
function onScreenshot(aMessage) {
mm.removeMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
chromeWindow.saveURL(aMessage.data, filename + ".png", null, true, true, doc.documentURIObject, doc);
}
mm.addMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
mm.sendAsyncMessage("ResponsiveMode:RequestScreenshot");
},
/**

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
subsuite = devtools
support-files =
head.js
@ -7,8 +6,11 @@ support-files =
[browser_responsive_cmd.js]
[browser_responsivecomputedview.js]
skip-if = e10s # Bug ??????
[browser_responsiveruleview.js]
skip-if = e10s # Bug ??????
[browser_responsiveui.js]
[browser_responsiveui_touch.js]
skip-if = e10s # Bug ?????? - [e10s] re-introduce touch feature in responsive mode
[browser_responsiveuiaddcustompreset.js]
[browser_responsive_devicewidth.js]

View File

@ -10,10 +10,11 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
function test() {
function isOpen() {
return !!gBrowser.selectedTab.__responsiveUI;
return gBrowser.getBrowserContainer(gBrowser.selectedTab.linkedBrowser)
.hasAttribute("responsivemode");
}
helpers.addTabWithToolbar("about:blank", function(options) {
helpers.addTabWithToolbar("data:text/html;charset=utf-8,hi", function(options) {
return helpers.audit(options, [
{
setup: "resize toggle",

View File

@ -7,21 +7,19 @@ function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedTab = gBrowser.addTab("about:logo");
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
startTest();
}, true);
content.location = "data:text/html,mop";
function startTest() {
mgr.once("on", function() {executeSoon(onUIOpen)});
document.getElementById("Tools:ResponsiveUI").doCommand();
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
instance.stack.setAttribute("notransition", "true");
ok(instance, "instance of the module is attached to the tab.");

View File

@ -8,11 +8,12 @@ function test() {
let inspector;
waitForExplicitFinish();
let mgr = ResponsiveUI.ResponsiveUIManager;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
startTest();
}, true);
content.location = "data:text/html;charset=utf-8,<html><style>" +
@ -43,7 +44,7 @@ function test() {
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.stack.setAttribute("notransition", "true");

View File

@ -11,10 +11,7 @@ function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
gBrowser.selectedBrowser.addEventListener("load", startTest, true);
content.location = "data:text/html;charset=utf-8,<html><style>" +
"div {" +
@ -34,12 +31,13 @@ function test() {
}
function startTest() {
gBrowser.selectedBrowser.removeEventListener("load", startTest, true);
document.getElementById("Tools:ResponsiveUI").doCommand();
executeSoon(onUIOpen);
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.stack.setAttribute("notransition", "true");

View File

@ -1,27 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Protocol error (unknownError): Error: Got an invalid root window in DocumentWalker");
function test() {
let instance, widthBeforeClose, heightBeforeClose;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
SimpleTest.requestCompleteLog();
Task.spawn(function() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
function extractSizeFromString(str) {
let numbers = str.match(/(\d+)[^\d]*(\d+)/);
if (numbers) {
return [numbers[1], numbers[2]];
} else {
return [null, null];
}
}
content.location = "data:text/html,mop";
function processStringAsKey(str) {
for (let i = 0, l = str.length; i < l; i++) {
EventUtils.synthesizeKey(str.charAt(i), {});
}
}
yield addTab("data:text/html,mop");
let mgr = ResponsiveUI.ResponsiveUIManager;
function startTest() {
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
mgr.once("on", function() {executeSoon(onUIOpen)});
synthesizeKeyFromKeyTag("key_responsiveUI");
}
function onUIOpen() {
yield once(mgr, "on");
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
@ -29,75 +38,58 @@ function test() {
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
instance = gBrowser.selectedTab.__responsiveUI;
let instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
if (instance._floatingScrollbars) {
ensureScrollbarsAreFloating();
}
let originalWidth = content.innerWidth;
content.location = "data:text/html;charset=utf-8,mop<div style%3D'height%3A5000px'><%2Fdiv>";
let newWidth = content.innerWidth;
is(originalWidth, newWidth, "Floating scrollbars are presents");
yield instance._test_notifyOnResize();
yield nextTick();
instance.transitionsEnabled = false;
testPresets();
}
function ensureScrollbarsAreFloating() {
let body = gBrowser.contentDocument.body;
let html = gBrowser.contentDocument.documentElement;
let originalWidth = body.getBoundingClientRect().width;
html.style.overflowY = "scroll"; // Force scrollbars
// Flush. Should not be needed as getBoundingClientRect() should flush,
// but just in case.
gBrowser.contentWindow.getComputedStyle(html).overflowY;
let newWidth = body.getBoundingClientRect().width;
is(originalWidth, newWidth, "Floating scrollbars are presents");
}
function testPresets() {
function testOnePreset(c) {
if (c == 0) {
executeSoon(testCustom);
return;
}
instance.menulist.selectedIndex = c;
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
for (let c = instance.menulist.firstChild.childNodes.length - 4; c >= 0; c--) {
let item = instance.menulist.firstChild.childNodes[c];
let [width, height] = extractSizeFromString(item.getAttribute("label"));
let onContentResize = once(mgr, "contentResize");
instance.menulist.selectedIndex = c;
yield onContentResize;
is(content.innerWidth, width, "preset " + c + ": dimension valid (width)");
is(content.innerHeight, height, "preset " + c + ": dimension valid (height)");
testOnePreset(c - 1);
}
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
testOnePreset(instance.menulist.firstChild.childNodes.length - 4);
}
function extractSizeFromString(str) {
let numbers = str.match(/(\d+)[^\d]*(\d+)/);
if (numbers) {
return [numbers[1], numbers[2]];
} else {
return [null, null];
}
}
// test custom
instance.setSize(100, 100);
yield once(mgr, "contentResize");
function testCustom() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
is(initialWidth, 100, "Width reset to 100");
is(initialHeight, 100, "Height reset to 100");
let x = 2, y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 20; y += 10;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove"}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
yield once(mgr, "contentResize");
let expectedWidth = initialWidth + 20;
let expectedHeight = initialHeight + 10;
info("initial width: " + initialWidth);
info("initial height: " + initialHeight);
is(content.innerWidth, expectedWidth, "Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "Size correcty updated (height).");
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
@ -108,71 +100,80 @@ function test() {
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustom2();
}
function testCustom2() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
// With "shift" key pressed
let x = 2, y = 2;
instance.setSize(100, 100);
yield once(mgr, "contentResize");
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
x = 2; y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 23; y += 13;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", shiftKey: true}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
let expectedWidth = initialWidth + 20;
let expectedHeight = initialHeight + 10;
is(content.innerWidth, expectedWidth, "with shift: Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "with shift: Size correcty updated (height).");
yield once(mgr, "contentResize");
expectedWidth = initialWidth + 20;
expectedHeight = initialHeight + 10;
is(content.innerWidth, expectedWidth, "with shift: Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "with shift: Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "with shift: Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
let [width, height] = extractSizeFromString(label);
label = instance.menulist.firstChild.firstChild.getAttribute("label");
value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
[width, height] = extractSizeFromString(label);
is(width, expectedWidth, "Label updated (width).");
is(height, expectedHeight, "Label updated (height).");
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustom3();
}
function testCustom3() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let x = 2, y = 2;
// With "ctrl" key pressed
instance.setSize(100, 100);
yield once(mgr, "contentResize");
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
x = 2; y = 2;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
x += 60; y += 30;
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", ctrlKey: true}, window);
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
let expectedWidth = initialWidth + 10;
let expectedHeight = initialHeight + 5;
is(content.innerWidth, expectedWidth, "with ctrl: Size correcty updated (width).");
is(content.innerHeight, expectedHeight, "with ctrl: Size correcty updated (height).");
yield once(mgr, "contentResize");
expectedWidth = initialWidth + 10;
expectedHeight = initialHeight + 5;
is(content.innerWidth, expectedWidth, "with ctrl: Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "with ctrl: Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "with ctrl: Custom menuitem cannot be selected");
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
let value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
let [width, height] = extractSizeFromString(label);
label = instance.menulist.firstChild.firstChild.getAttribute("label");
value = instance.menulist.value;
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
[width, height] = extractSizeFromString(label);
is(width, expectedWidth, "Label updated (width).");
is(height, expectedHeight, "Label updated (height).");
[width, height] = extractSizeFromString(value);
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustomInput();
}
function testCustomInput() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let expectedWidth = initialWidth - 20;
let expectedHeight = initialHeight - 10;
// Test custom input
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
expectedWidth = initialWidth - 20;
expectedHeight = initialHeight - 10;
let index = instance.menulist.selectedIndex;
let label, value, width, height;
let userInput = expectedWidth + " x " + expectedHeight;
@ -187,6 +188,8 @@ function test() {
// Only the `change` event must change the size
EventUtils.synthesizeKey("VK_RETURN", {});
yield once(mgr, "contentResize");
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
@ -200,17 +203,17 @@ function test() {
is(width, expectedWidth, "Value updated (width).");
is(height, expectedHeight, "Value updated (height).");
testCustomInput2();
}
function testCustomInput2() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
let index = instance.menulist.selectedIndex;
// Invalid input
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
index = instance.menulist.selectedIndex;
let expectedValue = initialWidth + "x" + initialHeight;
let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label");
let userInput = "I'm wrong";
userInput = "I'm wrong";
instance.menulist.inputField.value = "";
instance.menulist.focus();
@ -221,93 +224,75 @@ function test() {
is(content.innerHeight, initialHeight, "Size hasn't changed (height).");
is(instance.menulist.selectedIndex, index, "Selected item hasn't changed.");
is(instance.menulist.value, expectedValue, "Value has been reset")
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
label = instance.menulist.firstChild.firstChild.getAttribute("label");
is(label, expectedLabel, "Custom menuitem's label hasn't changed");
rotate();
}
function rotate() {
let initialWidth = content.innerWidth;
let initialHeight = content.innerHeight;
// Rotate
initialWidth = content.innerWidth;
initialHeight = content.innerHeight;
info("rotate");
instance.rotate();
yield once(mgr, "contentResize");
is(content.innerWidth, initialHeight, "The width is now the height.");
is(content.innerHeight, initialWidth, "The height is now the width.");
let [width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
[width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
is(width, initialHeight, "Label updated (width).");
is(height, initialWidth, "Label updated (height).");
widthBeforeClose = content.innerWidth;
heightBeforeClose = content.innerHeight;
let widthBeforeClose = content.innerWidth;
let heightBeforeClose = content.innerHeight;
info("XXX BUG 851296: instance.closing: " + !!instance.closing);
// Restart
mgr.once("off", function() {
info("XXX BUG 851296: 'off' received.");
executeSoon(restart);
});
mgr.toggle(window, gBrowser.selectedTab);
}
function restart() {
info("XXX BUG 851296: restarting.");
info("XXX BUG 851296: __responsiveUI: " + gBrowser.selectedTab.__responsiveUI);
mgr.once("on", function() {
info("XXX BUG 851296: 'on' received.");
executeSoon(onUIOpen2);
});
//XXX BUG 851296: synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "off");
mgr.toggle(window, gBrowser.selectedTab);
info("XXX BUG 851296: restart() finished.");
}
function onUIOpen2() {
info("XXX BUG 851296: onUIOpen2.");
let container = gBrowser.getBrowserContainer();
yield once(mgr, "on");
container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
is(content.innerWidth, widthBeforeClose, "width restored.");
is(content.innerHeight, heightBeforeClose, "height restored.");
mgr.once("off", function() {executeSoon(testScreenshot)});
mgr.toggle(window, gBrowser.selectedTab);
}
// Screenshot
function testScreenshot() {
let isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
if (isWinXP) {
// We have issues testing this on Windows XP.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=848760#c17
return finishUp();
}
if (!isWinXP) {
info("screenshot");
instance.screenshot("responsiveui");
let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
info("screenshot");
instance.screenshot("responsiveui");
let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
// while(1) until we find the file.
// no need for a timeout, the test will get killed anyway.
info("checking if file exists in 200ms");
function checkIfFileExist() {
let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]);
if (file.exists()) {
ok(true, "Screenshot file exists");
file.remove(false);
finishUp();
} else {
setTimeout(checkIfFileExist, 200);
while(true) {
// while(true) until we find the file.
// no need for a timeout, the test will get killed anyway.
let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]);
if (file.exists()) {
ok(true, "Screenshot file exists");
file.remove(false);
break;
}
info("checking if file exists in 200ms");
yield wait(200);
}
}
checkIfFileExist();
}
function finishUp() {
mgr.toggle(window, gBrowser.selectedTab);
yield once(mgr, "off");
// Menus are correctly updated?
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "false", "menu unchecked");
@ -315,39 +300,6 @@ function test() {
delete instance;
gBrowser.removeCurrentTab();
finish();
}
function synthesizeKeyFromKeyTag(aKeyId) {
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode"))
name = key.getAttribute("keycode");
else if (key.getAttribute("key"))
name = key.getAttribute("key");
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
}
info("XXX BUG 851296: key name: " + name);
info("XXX BUG 851296: key modifiers: " + JSON.stringify(modifiers));
EventUtils.synthesizeKey(name, modifiers);
}
function processStringAsKey(str) {
for (let i = 0, l = str.length; i < l; i++) {
EventUtils.synthesizeKey(str.charAt(i), {});
}
}
});
}

View File

@ -34,7 +34,7 @@ function test() {
}
function testWithTouch() {
gBrowser.selectedTab.__responsiveUI.enableTouch();
mgr.getResponsiveUIForTab(gBrowser.selectedTab).enableTouch();
let div = content.document.querySelector("div");
let x = 2, y = 2;
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);
@ -47,7 +47,7 @@ function test() {
}
function testWithTouchAgain() {
gBrowser.selectedTab.__responsiveUI.disableTouch();
mgr.getResponsiveUIForTab(gBrowser.selectedTab).disableTouch();
let div = content.document.querySelector("div");
let x = 2, y = 2;
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);

View File

@ -2,170 +2,10 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let instance, deletedPresetA, deletedPresetB, oldPrompt;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
SimpleTest.requestCompleteLog();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html;charset=utf8,test custom presets in responsive mode";
// This test uses executeSoon() when responsive mode is initialized and when
// it is destroyed such that we get out of the init/destroy loops. If we try
// to init/destroy immediately, without waiting for the next loop, we get
// intermittent test failures.
function startTest() {
// Mocking prompt
oldPrompt = Services.prompt;
Services.prompt = {
value: "",
returnBool: true,
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
aValue.value = this.value;
return this.returnBool;
}
};
registerCleanupFunction(() => Services.prompt = oldPrompt);
info("test started, waiting for responsive mode to activate");
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
mgr.once("on", onUIOpen);
synthesizeKeyFromKeyTag("key_responsiveUI");
}
function onUIOpen() {
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
ok(instance, "instance of the module is attached to the tab.");
instance.transitionsEnabled = false;
testAddCustomPreset();
}
function testAddCustomPreset() {
// Tries to add a custom preset and cancel the prompt
let idx = instance.menulist.selectedIndex;
let presetCount = instance.presets.length;
Services.prompt.value = "";
Services.prompt.returnBool = false;
instance.addbutton.doCommand();
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
let customHeight = 123, customWidth = 456;
instance.setSize(customWidth, customHeight);
// Adds the custom preset with "Testing preset"
Services.prompt.value = "Testing preset";
Services.prompt.returnBool = true;
instance.addbutton.doCommand();
instance.menulist.selectedIndex = 1;
info("waiting for responsive mode to turn off");
mgr.once("off", restart);
// Force document reflow to avoid intermittent failures.
info("document height " + document.height);
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
executeSoon(function() {
instance.close();
});
}
function restart() {
info("Restarting Responsive Mode");
mgr.once("on", function() {
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetInList();
});
// We're still in the loop of destroying the responsive mode.
// Let's wait next loop to start it.
executeSoon(function() {
synthesizeKeyFromKeyTag("key_responsiveUI");
});
}
function testCustomPresetInList() {
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
instance.menulist.selectedIndex = customPresetIndex;
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
testDeleteCustomPresets();
}
function testDeleteCustomPresets() {
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
info("waiting for responsive mode to turn off");
mgr.once("off", restartAgain);
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
executeSoon(() => instance.close());
}
function restartAgain() {
info("waiting for responsive mode to turn on");
mgr.once("on", () => {
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetsNotInListAnymore();
});
// We're still in the loop of destroying the responsive mode.
// Let's wait next loop to start it.
executeSoon(() => synthesizeKeyFromKeyTag("key_responsiveUI"));
}
function testCustomPresetsNotInListAnymore() {
let customPresetIndex = getPresetIndex(deletedPresetA);
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
customPresetIndex = getPresetIndex(deletedPresetB);
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
executeSoon(finishUp);
}
function finishUp() {
delete instance;
gBrowser.removeCurrentTab();
finish();
}
let instance, deletedPresetA, deletedPresetB, oldPrompt;
function getPresetIndex(presetLabel) {
function testOnePreset(c) {
@ -199,4 +39,121 @@ function test() {
key.doCommand();
}
Task.spawn(function() {
yield addTab("data:text/html;charset=utf8,test custom presets in responsive mode");
let mgr = ResponsiveUI.ResponsiveUIManager;
synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "on");
oldPrompt = Services.prompt;
Services.prompt = {
value: "",
returnBool: true,
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
aValue.value = this.value;
return this.returnBool;
}
};
registerCleanupFunction(() => Services.prompt = oldPrompt);
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
ok(instance, "instance of the module is attached to the tab.");
instance.transitionsEnabled = false;
yield instance._test_notifyOnResize();
// Tries to add a custom preset and cancel the prompt
let idx = instance.menulist.selectedIndex;
let presetCount = instance.presets.length;
Services.prompt.value = "";
Services.prompt.returnBool = false;
instance.addbutton.doCommand();
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
// Adds the custom preset with "Testing preset"
Services.prompt.value = "Testing preset";
Services.prompt.returnBool = true;
let customHeight = 123, customWidth = 456;
instance.startResizing({});
instance.setSize(customWidth, customHeight);
instance.stopResizing({});
instance.addbutton.doCommand();
// Force document reflow to avoid intermittent failures.
info("document height " + document.height);
instance.close();
info("waiting for responsive mode to turn off");
yield once(mgr, "off");
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
yield nextTick();
synthesizeKeyFromKeyTag("key_responsiveUI");
yield once(mgr, "on");
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
info(customPresetIndex);
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
instance.menulist.selectedIndex = customPresetIndex;
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
yield nextTick();
instance.close();
yield once(mgr, "off");
synthesizeKeyFromKeyTag("key_responsiveUI");
info("waiting for responsive mode to turn on");
yield once(mgr, "on");
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
customPresetIndex = getPresetIndex(deletedPresetA);
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
customPresetIndex = getPresetIndex(deletedPresetB);
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
yield nextTick();
gBrowser.removeCurrentTab();
finish();
});
}

View File

@ -123,3 +123,92 @@ function openComputedView() {
function openRuleView() {
return openInspectorSideBar("ruleview");
}
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @return a promise that resolves to the tab object when the url is loaded
*/
let addTab = Task.async(function* (url) {
info("Adding a new tab with URL: '" + url + "'");
window.focus();
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
let browser = tab.linkedBrowser;
yield once(browser, "load", true);
info("URL '" + url + "' loading complete");
return tab;
});
/**
* Wait for eventName on target.
* @param {Object} target An observable object that either supports on/off or
* addEventListener/removeEventListener
* @param {String} eventName
* @param {Boolean} useCapture Optional, for addEventListener/removeEventListener
* @return A promise that resolves when the event has been handled
*/
function once(target, eventName, useCapture=false) {
info("Waiting for event: '" + eventName + "' on " + target + ".");
let deferred = promise.defer();
for (let [add, remove] of [
["addEventListener", "removeEventListener"],
["addListener", "removeListener"],
["on", "off"]
]) {
if ((add in target) && (remove in target)) {
target[add](eventName, function onEvent(...aArgs) {
info("Got event: '" + eventName + "' on " + target + ".");
target[remove](eventName, onEvent, useCapture);
deferred.resolve.apply(deferred, aArgs);
}, useCapture);
break;
}
}
return deferred.promise;
}
function wait(ms) {
let def = promise.defer();
setTimeout(def.resolve, ms);
return def.promise;
}
function synthesizeKeyFromKeyTag(aKeyId) {
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode"))
name = key.getAttribute("keycode");
else if (key.getAttribute("key"))
name = key.getAttribute("key");
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
}
EventUtils.synthesizeKey(name, modifiers);
}
function nextTick() {
let def = promise.defer();
executeSoon(() => def.resolve())
return def.promise;
}

View File

@ -1,126 +0,0 @@
/* 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/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
this.EXPORTED_SYMBOLS = [ "switchToFloatingScrollbars", "switchToNativeScrollbars" ];
Cu.import("resource://gre/modules/Services.jsm");
let URL = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
let trackedTabs = new WeakMap();
/**
* Switch to floating scrollbars, à la mobile.
*
* @param aTab the targeted tab.
*
*/
this.switchToFloatingScrollbars = function switchToFloatingScrollbars(aTab) {
let mgr = trackedTabs.get(aTab);
if (!mgr) {
mgr = new ScrollbarManager(aTab);
}
mgr.switchToFloating();
}
/**
* Switch to original native scrollbars.
*
* @param aTab the targeted tab.
*
*/
this.switchToNativeScrollbars = function switchToNativeScrollbars(aTab) {
let mgr = trackedTabs.get(aTab);
if (mgr) {
mgr.reset();
}
}
function ScrollbarManager(aTab) {
trackedTabs.set(aTab, this);
this.attachedTab = aTab;
this.attachedBrowser = aTab.linkedBrowser;
this.reset = this.reset.bind(this);
this.switchToFloating = this.switchToFloating.bind(this);
this.attachedTab.addEventListener("TabClose", this.reset, true);
this.attachedBrowser.addEventListener("DOMContentLoaded", this.switchToFloating, true);
}
ScrollbarManager.prototype = {
get win() {
return this.attachedBrowser.contentWindow;
},
/*
* Change the look of the scrollbars.
*/
switchToFloating: function() {
let windows = this.getInnerWindows(this.win);
windows.forEach(this.injectStyleSheet);
this.forceStyle();
},
/*
* Reset the look of the scrollbars.
*/
reset: function() {
let windows = this.getInnerWindows(this.win);
windows.forEach(this.removeStyleSheet);
this.forceStyle(this.attachedBrowser);
this.attachedBrowser.removeEventListener("DOMContentLoaded", this.switchToFloating, true);
this.attachedTab.removeEventListener("TabClose", this.reset, true);
trackedTabs.delete(this.attachedTab);
},
/*
* Toggle the display property of the window to force the style to be applied.
*/
forceStyle: function() {
let parentWindow = this.attachedBrowser.ownerDocument.defaultView;
let display = parentWindow.getComputedStyle(this.attachedBrowser).display; // Save display value
this.attachedBrowser.style.display = "none";
parentWindow.getComputedStyle(this.attachedBrowser).display; // Flush
this.attachedBrowser.style.display = display; // Restore
},
/*
* return all the window objects present in the hiearchy of a window.
*/
getInnerWindows: function(win) {
let iframes = win.document.querySelectorAll("iframe");
let innerWindows = [];
for (let iframe of iframes) {
innerWindows = innerWindows.concat(this.getInnerWindows(iframe.contentWindow));
}
return [win].concat(innerWindows);
},
/*
* Append the new scrollbar style.
*/
injectStyleSheet: function(win) {
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.loadSheet(URL, win.AGENT_SHEET);
}catch(e) {}
},
/*
* Remove the injected stylesheet.
*/
removeStyleSheet: function(win) {
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
try {
winUtils.removeSheet(URL, win.AGENT_SHEET);
}catch(e) {}
},
}

View File

@ -12,7 +12,6 @@ EXTRA_JS_MODULES.devtools += [
'Curl.jsm',
'DeveloperToolbar.jsm',
'DOMHelpers.jsm',
'FloatingScrollbars.jsm',
'Jsbeautify.jsm',
'Parser.jsm',
'SplitView.jsm',

View File

@ -41,7 +41,7 @@ let WebAudioEditorController = {
/**
* Listen for events emitted by the current tab target.
*/
initialize: function() {
initialize: Task.async(function* () {
telemetry.toolOpened("webaudioeditor");
this._onTabNavigated = this._onTabNavigated.bind(this);
this._onThemeChange = this._onThemeChange.bind(this);
@ -60,7 +60,10 @@ let WebAudioEditorController = {
// the graph's marker styling, since we can't do this
// with CSS
gDevTools.on("pref-changed", this._onThemeChange);
},
// Store the AudioNode definitions from the WebAudioFront
AUDIO_NODE_DEFINITION = yield gFront.getDefinition();
}),
/**
* Remove events emitted by the current tab target.

View File

@ -15,6 +15,7 @@ const { require } = devtools;
let { console } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
let { EventTarget } = require("sdk/event/target");
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
const { Class } = require("sdk/core/heritage");
const EventEmitter = require("devtools/toolkit/event-emitter");
@ -25,6 +26,10 @@ const telemetry = new Telemetry();
devtools.lazyImporter(this, "LineGraphWidget",
"resource:///modules/devtools/Graphs.jsm");
// `AUDIO_NODE_DEFINITION` defined in the controller's initialization,
// which describes all the properties of an AudioNode
let AUDIO_NODE_DEFINITION;
// Override DOM promises with Promise.jsm helpers
const { defer, all } = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;

View File

@ -35,6 +35,12 @@ const AudioNodeModel = Class({
*/
setup: Task.async(function* () {
yield this.getType();
// Query bypass status on start up
this._bypassed = yield this.isBypassed();
// Store whether or not this node is bypassable in the first place
this.bypassable = !AUDIO_NODE_DEFINITION[this.type].unbypassable;
}),
/**
@ -75,6 +81,26 @@ const AudioNodeModel = Class({
coreEmit(this, "disconnect", this);
},
/**
* Gets the bypass status of the audio node.
*
* @return Promise->Boolean
*/
isBypassed: function () {
return this.actor.isBypassed();
},
/**
* Sets the bypass value of an AudioNode.
*
* @param Boolean enable
* @return Promise
*/
bypass: function (enable) {
this._bypassed = enable;
return this.actor.bypass(enable).then(() => coreEmit(this, "bypass", this, enable));
},
/**
* Returns a promise that resolves to an array of objects containing
* both a `param` name property and a `value` property.
@ -106,7 +132,8 @@ const AudioNodeModel = Class({
graph.addNode(this.id, {
type: this.type,
label: this.type.replace(/Node$/, ""),
id: this.id
id: this.id,
bypassed: this._bypassed
});
},
@ -279,7 +306,7 @@ const AudioNodesCollection = Class({
this.remove(node);
} else {
// Pipe the event to the collection
coreEmit(this, eventName, [node].concat(args));
coreEmit(this, eventName, node, ...args);
}
}
});

View File

@ -52,6 +52,7 @@ support-files =
[browser_wa_inspector.js]
[browser_wa_inspector-toggle.js]
[browser_wa_inspector-bypass-01.js]
[browser_wa_properties-view.js]
[browser_wa_properties-view-edit-01.js]

View File

@ -15,14 +15,22 @@ add_task(function*() {
is((yield gainNode.isBypassed()), false, "Nodes start off unbypassed.");
info("Calling node#bypass(true)");
yield gainNode.bypass(true);
let isBypassed = yield gainNode.bypass(true);
is(isBypassed, true, "node.bypass(true) resolves to true");
is((yield gainNode.isBypassed()), true, "Node is now bypassed.");
info("Calling node#bypass(false)");
yield gainNode.bypass(false);
isBypassed = yield gainNode.bypass(false);
is(isBypassed, false, "node.bypass(false) resolves to false");
is((yield gainNode.isBypassed()), false, "Node back to being unbypassed.");
info("Calling node#bypass(true) on unbypassable node");
isBypassed = yield destNode.bypass(true);
is(isBypassed, false, "node.bypass(true) resolves to false for unbypassable node");
is((yield gainNode.isBypassed()), false, "Unbypassable node is unaffect");
yield removeTab(target.tab);
});

View File

@ -20,11 +20,12 @@ add_task(function*() {
waitForGraphRendered(panelWin, 3, 2)
]);
let nodeIds = actors.map(actor => actor.actorID);
let $tabbox = $("#web-audio-editor-tabs");
// Oscillator node
click(panelWin, findGraphNode(panelWin, nodeIds[1]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(isVisible($("#automation-graph-container")), "graph container should be visible");
ok(isVisible($("#automation-content")), "automation content should be visible");
@ -34,17 +35,17 @@ add_task(function*() {
// Gain node
click(panelWin, findGraphNode(panelWin, nodeIds[2]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(!isVisible($("#automation-graph-container")), "graph container should be visible");
ok(isVisible($("#automation-content")), "automation content should not be visible");
ok(!isVisible($("#automation-graph-container")), "graph container should not be visible");
ok(isVisible($("#automation-content")), "automation content should be visible");
ok(isVisible($("#automation-no-events")), "no-events panel should be visible");
ok(!isVisible($("#automation-empty")), "empty panel should not be visible");
// destination node
click(panelWin, findGraphNode(panelWin, nodeIds[0]));
yield waitForInspectorRender(panelWin, EVENTS);
click(panelWin, $("#automation-tab"));
$tabbox.selectedIndex = 1;
ok(!isVisible($("#automation-graph-container")), "graph container should not be visible");
ok(!isVisible($("#automation-content")), "automation content should not be visible");

View File

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that nodes are correctly bypassed when bypassing.
*/
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
reload(target);
let [actors] = yield Promise.all([
get3(gFront, "create-node"),
waitForGraphRendered(panelWin, 3, 2)
]);
let nodeIds = actors.map(actor => actor.actorID);
click(panelWin, findGraphNode(panelWin, nodeIds[1]));
// Wait for the node to be set as well as the inspector to come fully into the view
yield Promise.all([
waitForInspectorRender(panelWin, EVENTS),
once(panelWin, EVENTS.UI_INSPECTOR_TOGGLED)
]);
let $bypass = $("toolbarbutton.bypass");
is((yield actors[1].isBypassed()), false, "AudioNodeActor is not bypassed by default.")
is($bypass.checked, true, "Button is 'on' for normal nodes");
is($bypass.disabled, false, "Bypass button is not disabled for normal nodes");
command($bypass);
yield gAudioNodes.once("bypass");
is((yield actors[1].isBypassed()), true, "AudioNodeActor is bypassed.")
is($bypass.checked, false, "Button is 'off' when clicked");
is($bypass.disabled, false, "Bypass button is not disabled after click");
ok(findGraphNode(panelWin, nodeIds[1]).classList.contains("bypassed"),
"AudioNode has 'bypassed' class.");
command($bypass);
yield gAudioNodes.once("bypass");
is((yield actors[1].isBypassed()), false, "AudioNodeActor is no longer bypassed.")
is($bypass.checked, true, "Button is back on when clicked");
is($bypass.disabled, false, "Bypass button is not disabled after click");
ok(!findGraphNode(panelWin, nodeIds[1]).classList.contains("bypassed"),
"AudioNode no longer has 'bypassed' class.");
click(panelWin, findGraphNode(panelWin, nodeIds[0]));
yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET);
is((yield actors[0].isBypassed()), false, "Unbypassable AudioNodeActor is not bypassed.");
is($bypass.checked, false, "Button is 'off' for unbypassable nodes");
is($bypass.disabled, true, "Bypass button is disabled for unbypassable nodes");
command($bypass);
is((yield actors[0].isBypassed()), false,
"Clicking button on unbypassable node does not change bypass state on actor.");
is($bypass.checked, false, "Button is still 'off' for unbypassable nodes");
is($bypass.disabled, true, "Bypass button is still disabled for unbypassable nodes");
yield teardown(target);
});

View File

@ -34,8 +34,6 @@ add_task(function*() {
"InspectorView empty message should still be visible.");
ok(!isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view should still be hidden.");
is($("#web-audio-inspector-title").value, "AudioNode Inspector",
"Inspector should still have default title.");
// Close inspector pane
$("#inspector-pane-toggle").click();
@ -59,8 +57,6 @@ add_task(function*() {
"Empty message hides even when loading node while open.");
ok(isVisible($("#web-audio-editor-tabs")),
"Switches to tab view when loading node while open.");
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector title updates when loading node while open.");
yield teardown(target);
});

View File

@ -27,8 +27,6 @@ add_task(function*() {
"InspectorView empty message should show when no node's selected.");
ok(!isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view should be hidden when no node's selected.");
is($("#web-audio-inspector-title").value, "AudioNode Inspector",
"Inspector should have default title when empty.");
// Wait for the node to be set as well as the inspector to come fully into the view
let nodeSet = Promise.all([
@ -44,9 +42,6 @@ add_task(function*() {
ok(isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view visible when node selected.");
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector should have the node title when a node is selected.");
is($("#web-audio-editor-tabs").selectedIndex, 0,
"default tab selected should be the parameters tab.");
@ -54,8 +49,5 @@ add_task(function*() {
click(panelWin, findGraphNode(panelWin, nodeIds[2]));
yield nodeSet;
is($("#web-audio-inspector-title").value, "Gain",
"Inspector title updates when a new node is selected.");
yield teardown(target);
});

View File

@ -318,6 +318,12 @@ function mouseOver (win, element) {
EventUtils.sendMouseEvent({ type: "mouseover" }, element, win);
}
function command (button) {
let ev = button.ownerDocument.createEvent("XULCommandEvent");
ev.initCommandEvent("command", true, true, button.ownerDocument.defaultView, 0, false, false, false, false, null);
button.dispatchEvent(ev);
}
function isVisible (element) {
return !element.getAttribute("hidden");
}

View File

@ -36,13 +36,13 @@ let ContextView = {
* Initialization function, called when the tool is started.
*/
initialize: function() {
this._onGraphNodeClick = this._onGraphNodeClick.bind(this);
this._onGraphClick = this._onGraphClick.bind(this);
this._onThemeChange = this._onThemeChange.bind(this);
this._onStartContext = this._onStartContext.bind(this);
this._onEvent = this._onEvent.bind(this);
this.draw = debounce(this.draw.bind(this), GRAPH_DEBOUNCE_TIMER);
$('#graph-target').addEventListener('click', this._onGraphNodeClick, false);
$("#graph-target").addEventListener("click", this._onGraphClick, false);
window.on(EVENTS.THEME_CHANGE, this._onThemeChange);
window.on(EVENTS.START_CONTEXT, this._onStartContext);
@ -58,7 +58,8 @@ let ContextView = {
if (this._zoomBinding) {
this._zoomBinding.on("zoom", null);
}
$('#graph-target').removeEventListener('click', this._onGraphNodeClick, false);
$("#graph-target").removeEventListener("click", this._onGraphClick, false);
window.off(EVENTS.THEME_CHANGE, this._onThemeChange);
window.off(EVENTS.START_CONTEXT, this._onStartContext);
gAudioNodes.off("*", this._onEvent);
@ -126,6 +127,15 @@ let ContextView = {
return $(".nodes > g[data-id='" + actorID + "']");
},
/**
* Sets the appropriate class on an SVG node when its bypass
* status is toggled.
*/
_bypassNode: function (node, enabled) {
let el = this._getNodeByID(node.id);
el.classList[enabled ? "add" : "remove"]("bypassed");
},
/**
* This method renders the nodes currently available in `gAudioNodes` and is
* throttled to be called at most every `GRAPH_DEBOUNCE_TIMER` milliseconds.
@ -143,42 +153,33 @@ let ContextView = {
let oldDrawNodes = renderer.drawNodes();
renderer.drawNodes(function(graph, root) {
let svgNodes = oldDrawNodes(graph, root);
svgNodes.attr("class", (n) => {
svgNodes.each(function (n) {
let node = graph.node(n);
return "audionode type-" + node.type;
});
svgNodes.attr("data-id", (n) => {
let node = graph.node(n);
return node.id;
let classString = "audionode type-" + node.type + (node.bypassed ? " bypassed" : "");
this.setAttribute("class", classString);
this.setAttribute("data-id", node.id);
this.setAttribute("data-type", node.type);
});
return svgNodes;
});
// Post-render manipulation of edges
// TODO do all of this more efficiently, rather than
// using the direct D3 helper utilities to loop over each
// edge several times
let oldDrawEdgePaths = renderer.drawEdgePaths();
let defaultClasses = "edgePath enter";
renderer.drawEdgePaths(function(graph, root) {
let svgEdges = oldDrawEdgePaths(graph, root);
svgEdges.attr("data-source", (n) => {
let edge = graph.edge(n);
return edge.source;
});
svgEdges.attr("data-target", (n) => {
let edge = graph.edge(n);
return edge.target;
});
svgEdges.attr("data-param", (n) => {
let edge = graph.edge(n);
return edge.param ? edge.param : null;
});
// We have to manually specify the default classes on the edges
// as to not overwrite them
let defaultClasses = "edgePath enter";
svgEdges.attr("class", (n) => {
let edge = graph.edge(n);
return defaultClasses + (edge.param ? (" param-connection " + edge.param) : "");
svgEdges.each(function (e) {
let edge = graph.edge(e);
// We have to manually specify the default classes on the edges
// as to not overwrite them
let edgeClass = defaultClasses + (edge.param ? (" param-connection " + edge.param) : "");
this.setAttribute("data-source", edge.source);
this.setAttribute("data-target", edge.target);
this.setAttribute("data-param", edge.param ? edge.param : null);
this.setAttribute("class", edgeClass);
});
return svgEdges;
@ -263,6 +264,11 @@ let ContextView = {
* in GRAPH_REDRAW_EVENTS) qualify as a redraw event.
*/
_onEvent: function (eventName, ...args) {
// If bypassing, just toggle the class on the SVG node
// rather than rerendering everything
if (eventName === "bypass") {
this._bypassNode.apply(this, args);
}
if (~GRAPH_REDRAW_EVENTS.indexOf(eventName)) {
this.draw();
}
@ -280,12 +286,12 @@ let ContextView = {
},
/**
* Fired when a node in the svg graph is clicked. Used to handle triggering the AudioNodePane.
* Fired when a click occurs in the graph.
*
* @param Event e
* Click event.
*/
_onGraphNodeClick: function (e) {
_onGraphClick: function (e) {
let node = findGraphNodeParent(e.target);
// If node not found (clicking outside of an audio node in the graph),
// then ignore this event

View File

@ -43,8 +43,12 @@ let InspectorView = {
this._onNodeSelect = this._onNodeSelect.bind(this);
this._onDestroyNode = this._onDestroyNode.bind(this);
this._onResize = this._onResize.bind(this);
this._onCommandClick = this._onCommandClick.bind(this);
this.splitter.addEventListener("mouseup", this._onResize);
for (let $el of $$("#audio-node-toolbar toolbarbutton")) {
$el.addEventListener("command", this._onCommandClick);
}
window.on(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
gAudioNodes.on("remove", this._onDestroyNode);
},
@ -55,6 +59,11 @@ let InspectorView = {
destroy: function () {
this.unbindToggle();
this.splitter.removeEventListener("mouseup", this._onResize);
$("#audio-node-toolbar toolbarbutton").removeEventListener("command", this._onCommandClick);
for (let $el of $$("#audio-node-toolbar toolbarbutton")) {
$el.removeEventListener("command", this._onCommandClick);
}
window.off(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
gAudioNodes.off("remove", this._onDestroyNode);
@ -67,7 +76,7 @@ let InspectorView = {
* Takes a AudioNodeView `node` and sets it as the current
* node and scaffolds the inspector view based off of the new node.
*/
setCurrentAudioNode: function (node) {
setCurrentAudioNode: Task.async(function* (node) {
this._currentNode = node || null;
// If no node selected, set the inspector back to "no AudioNode selected"
@ -81,10 +90,10 @@ let InspectorView = {
else {
$("#web-audio-editor-details-pane-empty").setAttribute("hidden", "true");
$("#web-audio-editor-tabs").removeAttribute("hidden");
this._setTitle();
yield this._buildToolbar();
window.emit(EVENTS.UI_INSPECTOR_NODE_SET, this._currentNode.id);
}
},
}),
/**
* Returns the current AudioNodeView.
@ -104,14 +113,25 @@ let InspectorView = {
this.hideImmediately();
},
/**
* Sets the title of the Inspector view
*/
_setTitle: function () {
let node = this._currentNode;
let title = node.type.replace(/Node$/, "");
$("#web-audio-inspector-title").setAttribute("value", title);
},
_buildToolbar: Task.async(function* () {
let node = this.getCurrentAudioNode();
let bypassable = node.bypassable;
let bypassed = yield node.isBypassed();
let button = $("#audio-node-toolbar .bypass");
if (!bypassable) {
button.setAttribute("disabled", true);
} else {
button.removeAttribute("disabled");
}
if (!bypassable || bypassed) {
button.removeAttribute("checked");
} else {
button.setAttribute("checked", true);
}
}),
/**
* Event handlers
@ -140,5 +160,26 @@ let InspectorView = {
if (this._currentNode && this._currentNode.id === node.id) {
this.setCurrentAudioNode(null);
}
},
_onCommandClick: function (e) {
let node = this.getCurrentAudioNode();
let button = e.target;
let command = button.getAttribute("data-command");
let checked = button.getAttribute("checked");
if (button.getAttribute("disabled")) {
return;
}
if (command === "bypass") {
if (checked) {
button.removeAttribute("checked");
node.bypass(true);
} else {
button.setAttribute("checked", true);
node.bypass(false);
}
}
}
};

View File

@ -3,10 +3,10 @@
- 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/. -->
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/webaudioeditor.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/webaudioeditor.dtd">
%debuggerDTD;
@ -79,9 +79,6 @@
</hbox>
<splitter id="inspector-splitter" class="devtools-side-splitter"/>
<vbox id="web-audio-inspector" hidden="true">
<hbox class="devtools-toolbar">
<label id="web-audio-inspector-title" value="&webAudioEditorUI.inspectorTitle;"></label>
</hbox>
<deck id="web-audio-editor-details-pane" flex="1">
<vbox id="web-audio-editor-details-pane-empty" flex="1">
<label value="&webAudioEditorUI.inspectorEmpty;"></label>
@ -89,6 +86,13 @@
<tabbox id="web-audio-editor-tabs"
class="devtools-sidebar-tabs"
handleCtrlTab="false">
<toolbar id="audio-node-toolbar" class="devtools-toolbar">
<hbox class="devtools-toolbarbutton-group">
<toolbarbutton class="bypass devtools-toolbarbutton"
data-command="bypass"
tabindex="0"/>
</hbox>
</toolbar>
<tabs>
<tab id="properties-tab"
label="&webAudioEditorUI.tab.properties;"/>

View File

@ -33,3 +33,7 @@ collapseInspector=Collapse inspector
# that expands the inspector in the web audio tool UI.
expandInspector=Expand inspector
# LOCALIZATION NOTE (webAudioEditorTooltipBypass): This is the tooltip for the
# button that bypasses an AudioNode
webAudioEditorTooltipBypass=Bypass AudioNode

View File

@ -20,10 +20,10 @@ Cu.import("resource://gre/modules/Services.jsm");
*/
/**
* If a hang hasn't been reported for more than 5 seconds, assume the
* If a hang hasn't been reported for more than 10 seconds, assume the
* content process has gotten unstuck (and hide the hang notification).
*/
const HANG_EXPIRATION_TIME = 5000;
const HANG_EXPIRATION_TIME = 10000;
let ProcessHangMonitor = {
/**

View File

@ -229,6 +229,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -360,6 +360,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -13,4 +13,15 @@
<feFuncB type="table" tableValues=".6 0"/>
</feComponentTransfer>
</filter>
<!-- Web Audio Gradients -->
<linearGradient id="bypass-light" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
<stop offset="0%" stop-color="#f0f1f2"/> <!-- theme-toolbar-background -->
<stop offset="50%" stop-color="#fff"/>
</linearGradient>
<linearGradient id="bypass-dark" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
<stop offset="0%" stop-color="#343c45"/> <!-- theme-toolbar-background -->
<stop offset="50%" stop-color="transparent"/>
</linearGradient>
</svg>

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,14 @@
<!--
Logo from raphaeljs.com, MIT License
Copyright © 2008 Dmitry Baranovskiy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
-->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
<path stroke="#edf0f1" d="m10.89891,2.50043c-0.49827,-0.24134 -1.09841,-0.03411 -1.34129,0.46514c-0.24185,0.49928 -0.03311,1.09942 0.46517,1.34128c1.56306,0.76071 2.64193,2.36094 2.64092,4.21555c-0.00501,2.58626 -2.09749,4.6787 -4.68322,4.68321c-2.58623,-0.005 -4.67869,-2.09746 -4.68371,-4.68321c-0.001,-1.85561 1.07834,-3.45731 2.64294,-4.21654c0.49928,-0.24185 0.7065,-0.84201 0.46514,-1.34129c-0.24185,-0.49825 -0.84098,-0.70697 -1.34029,-0.46513c-2.23396,1.08135 -3.77446,3.37351 -3.77545,6.02296c0.00099,3.69518 2.99518,6.68989 6.69138,6.69088c3.6957,-0.00099 6.69037,-2.9957 6.69089,-6.69088c-0.00102,-2.64846 -1.53948,-4.9391 -3.77247,-6.02197zm-2.91842,4.9346c0.55398,0 1.00309,-0.44861 1.00309,-1.00357l0,-4.68373c0,-0.55446 -0.44911,-1.00309 -1.00309,-1.00309c-0.555,0 -1.00358,0.44911 -1.00358,1.00309l0,4.68321c0,0.55499 0.44858,1.00409 1.00358,1.00409z" stroke-width="0" fill="#edf0f1"/>
</svg>

View File

@ -81,13 +81,47 @@ g.edgePath.param-connection {
.nodes rect {
stroke: var(--theme-tab-toolbar-background);
}
.theme-light rect {
fill: var(--theme-tab-toolbar-background);
}
.theme-dark rect {
fill: var(--theme-toolbar-background);
}
/**
* Bypassed Nodes
*/
.theme-light .nodes g.bypassed rect {
fill: url(chrome://browser/skin/devtools/filters.svg#bypass-light);
}
.theme-dark .nodes g.bypassed rect {
fill: url(chrome://browser/skin/devtools/filters.svg#bypass-dark);
}
.nodes g.bypassed.selected rect {
stroke: var(--theme-selection-background);
}
/*
.nodes g.bypassed text {
opacity: 0.8;
}
*/
/**
* Selected Nodes
*/
.nodes g.selected rect {
fill: var(--theme-selection-background);
}
/* Don't style bypassed nodes text different because it'd be illegible in light-theme */
.theme-light g.selected:not(.bypassed) text {
fill: var(--theme-toolbar-background);
}
/* Text in nodes and edges */
text {
cursor: default; /* override the "text" cursor */
@ -100,9 +134,6 @@ text {
fill: var(--theme-body-color-alt);
}
.theme-light g.selected text {
fill: var(--theme-toolbar-background);
}
.nodes text {
cursor: pointer;
@ -178,6 +209,32 @@ text {
}
}
/**
* Inspector toolbar
*/
#audio-node-toolbar .bypass {
list-style-image: url(power.svg);
}
#audio-node-toolbar toolbarbutton[disabled] {
opacity: 0.5;
background-color: transparent;
}
.theme-dark #audio-node-toolbar toolbarbutton[checked] {
background-color: #1d4f73; /* Select Highlight Blue */
}
.theme-light #audio-node-toolbar toolbarbutton[checked] {
background-color: #4c9ed9; /* Select Highlight Blue */
}
/* don't invert checked buttons so we can have white icons on light theme */
#audio-node-toolbar toolbarbutton[checked] > .toolbarbutton-icon {
filter: none;
}
/**
* Responsive Styles
* `.devtools-responsive-container` takes care of most of

View File

@ -266,6 +266,7 @@ browser.jar:
skin/classic/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
@ -729,6 +730,7 @@ browser.jar:
skin/classic/aero/browser/devtools/newtab-inverted.png (../shared/devtools/images/newtab-inverted.png)
skin/classic/aero/browser/devtools/newtab-inverted@2x.png (../shared/devtools/images/newtab-inverted@2x.png)
* skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/aero/browser/devtools/power.svg (../shared/devtools/images/power.svg)
skin/classic/aero/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
skin/classic/aero/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
skin/classic/aero/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)

View File

@ -39,7 +39,7 @@ if test $android_version -lt MIN_ANDROID_VERSION ; then
fi
case "$target" in
arm-linux*-android*|*-linuxandroid*)
arm-*linux*-android*|*-linuxandroid*)
android_tool_prefix="arm-linux-androideabi"
;;
i?86-*android*)

View File

@ -10,9 +10,9 @@ int operator+(X, int);
int operator++(X);
void badArithmeticsInArgs() {
int a;
int a = 1;
typedef int myint;
myint b;
myint b = 2;
X goodObj1(a);
goodObj1.baz(b);
X badObj1(a + b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}

View File

@ -35,7 +35,7 @@ GENERATED_INCLUDES += [
]
LOCAL_INCLUDES += [
'/netwerk/base/src',
'/netwerk/base',
'/netwerk/protocol/res',
'/xpcom/components'
]

View File

@ -2211,17 +2211,15 @@ ia64*-hpux*)
_DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
CFLAGS="$CFLAGS -W3 -Gy"
CXXFLAGS="$CXXFLAGS -W3 -Gy"
if test "$_CC_SUITE" -ge "11" -a "$CPU_ARCH" = "x86"; then
if test "$CPU_ARCH" = "x86"; then
dnl VS2012+ defaults to -arch:SSE2.
CFLAGS="$CFLAGS -arch:IA32"
CXXFLAGS="$CXXFLAGS -arch:IA32"
fi
if test "$_CC_SUITE" -ge "12"; then
dnl VS2013+ requires -FS when parallel building by make -jN.
dnl If nothing, compiler sometimes causes C1041 error.
CFLAGS="$CFLAGS -FS"
CXXFLAGS="$CXXFLAGS -FS"
fi
dnl VS2013+ requires -FS when parallel building by make -jN.
dnl If nothing, compiler sometimes causes C1041 error.
CFLAGS="$CFLAGS -FS"
CXXFLAGS="$CXXFLAGS -FS"
# khuey says we can safely ignore MSVC warning C4251
# MSVC warning C4244 (implicit type conversion may lose data) warns
# and requires workarounds for perfectly valid code. Also, GCC/clang
@ -2283,10 +2281,8 @@ ia64*-hpux*)
dnl both SSSE3 and SSE4.1.
HAVE_TOOLCHAIN_SUPPORT_MSSSE3=1
HAVE_TOOLCHAIN_SUPPORT_MSSE4_1=1
if test "$_CC_SUITE" -ge "11"; then
dnl allow AVX2 code from VS2012
HAVE_X86_AVX2=1
fi
dnl allow AVX2 code from VS2012
HAVE_X86_AVX2=1
MOZ_MEMORY=1
fi
AC_DEFINE(HAVE_SNPRINTF)
@ -3886,6 +3882,8 @@ LIBJPEG_TURBO_ASFLAGS=
LIBJPEG_TURBO_X86_ASM=
LIBJPEG_TURBO_X64_ASM=
LIBJPEG_TURBO_ARM_ASM=
LIBJPEG_TURBO_ARM64_ASM=
LIBJPEG_TURBO_MIPS_ASM=
MOZ_PERMISSIONS=1
MOZ_PLACES=1
MOZ_SOCIAL=1
@ -6154,6 +6152,14 @@ if test -n "$MOZ_LIBJPEG_TURBO"; then
LIBJPEG_TURBO_ASFLAGS="-march=armv7-a -mfpu=neon"
LIBJPEG_TURBO_ARM_ASM=1
;;
*:aarch64*)
LIBJPEG_TURBO_ASFLAGS="-march=armv8-a"
LIBJPEG_TURBO_ARM64_ASM=1
;;
*:mips*)
LIBJPEG_TURBO_ASFLAGS="-mdspr2"
LIBJPEG_TURBO_MIPS_ASM=1
;;
*:x86|*:i?86)
if $CC -E -dM -</dev/null | grep -q __ELF__; then
LIBJPEG_TURBO_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC -DELF"
@ -8831,6 +8837,8 @@ AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
AC_SUBST(LIBJPEG_TURBO_ARM64_ASM)
AC_SUBST(LIBJPEG_TURBO_MIPS_ASM)
AC_SUBST(MOZ_PACKAGE_JSSHELL)
AC_SUBST(MOZ_FOLD_LIBS)

View File

@ -411,7 +411,7 @@ LOCAL_INCLUDES += [
'/layout/style',
'/layout/svg',
'/layout/xul',
'/netwerk/base/src',
'/netwerk/base',
'/widget',
'/xpcom/ds',
]

View File

@ -509,6 +509,8 @@ Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
// must be true when web apps check it after they call preventDefault().
if (!aCalledByDefaultHandler) {
mEvent->mFlags.mDefaultPreventedByContent = true;
} else {
mEvent->mFlags.mDefaultPreventedByChrome = true;
}
if (!IsTrusted()) {
@ -569,6 +571,8 @@ Event::InitEvent(const nsAString& aEventTypeArg,
mEvent->mFlags.mCancelable = aCancelableArg;
mEvent->mFlags.mDefaultPrevented = false;
mEvent->mFlags.mDefaultPreventedByContent = false;
mEvent->mFlags.mDefaultPreventedByChrome = false;
// Clearing the old targets, so that the event is targeted correctly when
// re-dispatching it.

View File

@ -204,7 +204,7 @@ protected:
uint32_t mLoadID;
};
class nsAsyncEventRunner : public nsMediaEvent
class HTMLMediaElement::nsAsyncEventRunner : public nsMediaEvent
{
private:
nsString mName;

View File

@ -217,8 +217,6 @@ public:
layers::ImageContainer* GetImageContainer();
// Dispatch events
using nsGenericHTMLElement::DispatchEvent;
virtual nsresult DispatchEvent(const nsAString& aName) MOZ_FINAL MOZ_OVERRIDE;
virtual nsresult DispatchAsyncEvent(const nsAString& aName) MOZ_FINAL MOZ_OVERRIDE;
// Dispatch events that were raised while in the bfcache
@ -980,6 +978,11 @@ protected:
// MediaElement doesn't yet have one then it will create it.
TextTrackManager* GetOrCreateTextTrackManager();
class nsAsyncEventRunner;
using nsGenericHTMLElement::DispatchEvent;
// For nsAsyncEventRunner.
nsresult DispatchEvent(const nsAString& aName);
// The current decoder. Load() has been called on this decoder.
// At most one of mDecoder and mSrcStream can be non-null.
nsRefPtr<MediaDecoder> mDecoder;

View File

@ -241,7 +241,7 @@ LOCAL_INCLUDES += [
'/layout/style',
'/layout/tables',
'/layout/xul',
'/netwerk/base/src',
'/netwerk/base',
]
FINAL_LIBRARY = 'xul'

View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=910532
Verify that an ESC key press canceling the context menu
won't exit DOM fullscreen.
-->
<head>
<meta charset="UTF-8">
<title>Text for bug 910532</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="file_fullscreen-utils.js"></script>
<style>
body:-moz-full-screen {
background-color: red;
}
</style>
</head>
<body>
<script type="application/javascript">
const Ci = SpecialPowers.Ci;
SimpleTest.requestFlakyTimeout("We need to wait a small time to confirm " +
"that the first ESC key does not exit fullscreen.");
function ok(condition, msg) {
opener.ok(condition, "[esc-context-menu] " + msg);
}
function is(a, b, msg) {
opener.is(a, b, "[esc-context-menu] " + msg);
}
var contextMenu;
var escapeSent = 0;
function sendEscape() {
escapeSent++;
synthesizeKey("VK_ESCAPE", {});
}
function begin() {
// Copy from browser/base/content/test/general/test_contextmenu.html
var chromeWin = SpecialPowers.wrap(window)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow)
.QueryInterface(Ci.nsIDOMChromeWindow);
contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
ok(contextMenu, "Got context menu XUL");
addFullscreenChangeContinuation("enter", fullscreenEntered);
SpecialPowers.setBoolPref("full-screen-api.approval-required", false);
document.body.mozRequestFullScreen();
}
function finish() {
SpecialPowers.clearUserPref("full-screen-api.approval-required");
opener.nextTest();
}
function fullscreenEntered(event) {
ok(document.mozFullScreen, "Should have entered fullscreen mode");
is(document.mozFullScreenElement, document.body, "FSE should be doc");
contextMenu.addEventListener("popupshown", contextMenuOpened, false);
is(contextMenu.state, "closed", "Should not have opened context menu");
synthesizeMouseAtCenter(document.body, {type: 'contextmenu', button: 2});
}
function contextMenuOpened(event) {
contextMenu.removeEventListener("popupshown", contextMenuOpened);
is(contextMenu.state, "open", "Should have opened context menu");
addFullscreenChangeContinuation("exit", fullscreenExited);
contextMenu.addEventListener("popuphidden", contextMenuClosed, false);
sendEscape();
}
function contextMenuClosed(event) {
is(contextMenu.state, "closed", "Should have closed context menu");
setTimeout(function () {
ok(document.mozFullScreen, "Should still be in fullscreen mode");
sendEscape();
}, 100);
}
function fullscreenExited(event) {
is(escapeSent, 2, "Only the second escape should exit fullscreen");
ok(!document.mozFullScreen, "Should have left fullscreen mode");
finish();
}
</script>
</body>
</html>

View File

@ -51,6 +51,7 @@ support-files =
file_fullscreen-api.html
file_fullscreen-denied-inner.html
file_fullscreen-denied.html
file_fullscreen-esc-context-menu.html
file_fullscreen-esc-exit-inner.html
file_fullscreen-esc-exit.html
file_fullscreen-hidden.html

View File

@ -39,6 +39,7 @@ var gTestWindows = [
"file_fullscreen-ancestor-stacking-context.html",
"file_fullscreen-multiple.html",
"file_fullscreen-rollback.html",
"file_fullscreen-esc-context-menu.html",
"file_fullscreen-esc-exit.html",
"file_fullscreen-denied.html",
"file_fullscreen-api.html",

View File

@ -132,7 +132,7 @@ LOCAL_INCLUDES += [
'/hal/sandbox',
'/js/ipc',
'/layout/base',
'/netwerk/base/src',
'/netwerk/base',
'/toolkit/xre',
'/uriloader/exthandler',
'/widget',

View File

@ -16,7 +16,7 @@ FAIL_ON_WARNINGS = True
LOCAL_INCLUDES += [
"/dom/base",
"/netwerk/base/src",
"/netwerk/base",
]
FINAL_LIBRARY = 'xul'

View File

@ -1253,7 +1253,7 @@ void MediaDecoder::DurationChanged()
if (mOwner && oldDuration != mDuration && !IsInfinite()) {
DECODER_LOG("Duration changed to %lld", mDuration);
mOwner->DispatchEvent(NS_LITERAL_STRING("durationchange"));
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
}
}

View File

@ -21,9 +21,6 @@ public:
// Called by the media decoder to indicate that the download is progressing.
virtual void DownloadProgressed() = 0;
// Dispatch a synchronous event to the decoder owner
virtual nsresult DispatchEvent(const nsAString& aName) = 0;
// Dispatch an asynchronous event to the decoder owner
virtual nsresult DispatchAsyncEvent(const nsAString& aName) = 0;

View File

@ -333,8 +333,9 @@ RTCPeerConnection.prototype = {
this._mustValidateRTCConfiguration(rtcConfig,
"RTCPeerConnection constructor passed invalid RTCConfiguration");
if (_globalPCList._networkdown || !this._win.navigator.onLine) {
throw new this._win.DOMError("InvalidStateError",
"Can't create RTCPeerConnections when the network is down");
throw new this._win.DOMException(
"Can't create RTCPeerConnections when the network is down",
"InvalidStateError");
}
this.makeGetterSetterEH("onaddstream");
@ -351,7 +352,7 @@ RTCPeerConnection.prototype = {
this.makeGetterSetterEH("onidpvalidationerror");
this._pc = new this._win.PeerConnectionImpl();
this._taskChain = this._win.Promise.resolve();
this._operationsChain = this._win.Promise.resolve();
this.__DOM_IMPL__._innerObject = this;
this._observer = new this._win.PeerConnectionObserver(this.__DOM_IMPL__);
@ -367,8 +368,9 @@ RTCPeerConnection.prototype = {
get _impl() {
if (!this._pc) {
throw new this._win.DOMError("InvalidStateError",
"RTCPeerConnection is gone (did you enter Offline mode?)");
throw new this._win.DOMException(
"RTCPeerConnection is gone (did you enter Offline mode?)",
"InvalidStateError");
}
return this._pc;
},
@ -383,19 +385,40 @@ RTCPeerConnection.prototype = {
this.dispatchEvent.bind(this));
},
/**
* Add a function to the task chain.
* onSuccess - legacy callback (optional)
* onError - legacy callback (optional)
*/
_queue: function(func, onSuccess, onError) {
let p = this._taskChain.then(() => {
this._checkClosed(); // TODO: Move outside promise once Bug 1107592 is fixed.
return func();
// Add a function to the internal operations chain.
_chain: function(func) {
this._checkClosed(); // out here DOMException line-numbers work.
let p = this._operationsChain.then(() => {
// Don't _checkClosed() inside the chain, because it throws, and spec
// behavior as of this writing is to NOT reject outstanding promises on
// close. This is what happens most of the time anyways, as the c++ code
// stops calling us once closed, hanging the chain. However, c++ may
// already have queued tasks on us, so if we're one of those then sit back.
if (!this._closed) {
return func();
}
});
this._taskChain = p.catch(() => {}); // don't propagate errors in taskChain!
return onSuccess? p.then(this._wrapLegacyCallback(onSuccess),
this._wrapLegacyCallback(onError)) : p;
// don't propagate errors in the operations chain (this is a fork of p).
this._operationsChain = p.catch(() => {});
return p;
},
// This wrapper helps implement legacy callbacks in a manner that produces
// correct line-numbers in errors, provided that methods validate their inputs
// before putting themselves on the pc's operations chain.
_legacyCatch: function(onSuccess, onError, func) {
if (!onSuccess) {
return func();
}
try {
return func().then(this._wrapLegacyCallback(onSuccess),
this._wrapLegacyCallback(onError));
} catch (e) {
this._wrapLegacyCallback(onError)(e);
return this._win.Promise.resolve(); // avoid webidl TypeError
}
},
_wrapLegacyCallback: function(func) {
@ -417,46 +440,44 @@ RTCPeerConnection.prototype = {
*
* WebIDL normalizes structure for us, so we test well-formed stun/turn urls,
* but not validity of servers themselves, before passing along to C++.
* ErrorMsg is passed in to detail which array-entry failed, if any.
*
* msg - Error message to detail which array-entry failed, if any.
*/
_mustValidateRTCConfiguration: function(rtcConfig, errorMsg) {
var errorCtor = this._win.DOMError;
var warningFunc = this.logWarning.bind(this);
function nicerNewURI(uriStr, errorMsg) {
let ios = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
_mustValidateRTCConfiguration: function(rtcConfig, msg) {
let ios = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
let nicerNewURI = uriStr => {
try {
return ios.newURI(uriStr, null, null);
} catch (e if (e.result == Cr.NS_ERROR_MALFORMED_URI)) {
throw new errorCtor("", errorMsg + " - malformed URI: " + uriStr);
throw new this._win.DOMException(msg + " - malformed URI: " + uriStr,
"SyntaxError");
}
}
function mustValidateServer(server) {
};
rtcConfig.iceServers.forEach(server => {
if (!server.url) {
throw new errorCtor("", errorMsg + " - missing url");
throw new this._win.DOMException(msg + " - missing url", "InvalidAccessError");
}
let url = nicerNewURI(server.url, errorMsg);
let url = nicerNewURI(server.url);
if (url.scheme in { turn:1, turns:1 }) {
if (!server.username) {
throw new errorCtor("", errorMsg + " - missing username: " + server.url);
throw new this._win.DOMException(msg + " - missing username: " + server.url,
"InvalidAccessError");
}
if (!server.credential) {
throw new errorCtor("", errorMsg + " - missing credential: " +
server.url);
throw new this._win.DOMException(msg + " - missing credential: " + server.url,
"InvalidAccessError");
}
}
else if (!(url.scheme in { stun:1, stuns:1 })) {
throw new errorCtor("", errorMsg + " - improper scheme: " + url.scheme);
throw new this._win.DOMException(msg + " - improper scheme: " + url.scheme,
"SyntaxError");
}
if (url.scheme in { stuns:1, turns:1 }) {
warningFunc(url.scheme.toUpperCase() + " is not yet supported.", null, 0);
this.logWarning(url.scheme.toUpperCase() + " is not yet supported.", null, 0);
}
}
if (rtcConfig.iceServers) {
let len = rtcConfig.iceServers.length;
for (let i=0; i < len; i++) {
mustValidateServer (rtcConfig.iceServers[i], errorMsg);
}
}
});
},
// Ideally, this should be of the form _checkState(state),
@ -465,7 +486,8 @@ RTCPeerConnection.prototype = {
// spec. See Bug 831756.
_checkClosed: function() {
if (this._closed) {
throw new this._win.DOMError("InvalidStateError", "Peer connection is closed");
throw new this._win.DOMException("Peer connection is closed",
"InvalidStateError");
}
},
@ -529,227 +551,168 @@ RTCPeerConnection.prototype = {
},
createOffer: function(optionsOrOnSuccess, onError, options) {
// TODO: Remove old constraint-like RTCOptions support soon (Bug 1064223).
// Note that webidl bindings make o.mandatory implicit but not o.optional.
function convertLegacyOptions(o) {
// Detect (mandatory OR optional) AND no other top-level members.
let lcy = ((o.mandatory && Object.keys(o.mandatory).length) || o.optional) &&
Object.keys(o).length == (o.mandatory? 1 : 0) + (o.optional? 1 : 0);
if (!lcy) {
return false;
}
let old = o.mandatory || {};
if (o.mandatory) {
delete o.mandatory;
}
if (o.optional) {
o.optional.forEach(one => {
// The old spec had optional as an array of objects w/1 attribute each.
// Assumes our JS-webidl bindings only populate passed-in properties.
let key = Object.keys(one)[0];
if (key && old[key] === undefined) {
old[key] = one[key];
}
});
delete o.optional;
}
o.offerToReceiveAudio = old.OfferToReceiveAudio;
o.offerToReceiveVideo = old.OfferToReceiveVideo;
o.mozDontOfferDataChannel = old.MozDontOfferDataChannel;
o.mozBundleOnly = old.MozBundleOnly;
Object.keys(o).forEach(k => {
if (o[k] === undefined) {
delete o[k];
}
});
return true;
}
let onSuccess;
if (optionsOrOnSuccess && typeof optionsOrOnSuccess === "function") {
if (typeof optionsOrOnSuccess == "function") {
onSuccess = optionsOrOnSuccess;
} else {
options = optionsOrOnSuccess;
onError = undefined;
}
if (options && convertLegacyOptions(options)) {
this.logWarning(
"Mandatory/optional in createOffer options is deprecated! Use " +
JSON.stringify(options) + " instead (note the case difference)!",
null, 0);
}
return this._queue(() => this._createOffer(options), onSuccess, onError);
},
return this._legacyCatch(onSuccess, onError, () => {
_createOffer: function(options) {
return new this._win.Promise((resolve, reject) => {
this._onCreateOfferSuccess = resolve;
this._onCreateOfferFailure = reject;
this._impl.createOffer(options);
});
},
// TODO: Remove old constraint-like RTCOptions support soon (Bug 1064223).
// Note that webidl bindings make o.mandatory implicit but not o.optional.
function convertLegacyOptions(o) {
// Detect (mandatory OR optional) AND no other top-level members.
let lcy = ((o.mandatory && Object.keys(o.mandatory).length) || o.optional) &&
Object.keys(o).length == (o.mandatory? 1 : 0) + (o.optional? 1 : 0);
if (!lcy) {
return false;
}
let old = o.mandatory || {};
if (o.mandatory) {
delete o.mandatory;
}
if (o.optional) {
o.optional.forEach(one => {
// The old spec had optional as an array of objects w/1 attribute each.
// Assumes our JS-webidl bindings only populate passed-in properties.
let key = Object.keys(one)[0];
if (key && old[key] === undefined) {
old[key] = one[key];
}
});
delete o.optional;
}
o.offerToReceiveAudio = old.OfferToReceiveAudio;
o.offerToReceiveVideo = old.OfferToReceiveVideo;
o.mozDontOfferDataChannel = old.MozDontOfferDataChannel;
o.mozBundleOnly = old.MozBundleOnly;
Object.keys(o).forEach(k => {
if (o[k] === undefined) {
delete o[k];
}
});
return true;
}
_createAnswer: function() {
return new this._win.Promise((resolve, reject) => {
if (!this.remoteDescription) {
throw new this._win.DOMError("InvalidStateError",
"setRemoteDescription not called");
if (options && convertLegacyOptions(options)) {
this.logWarning(
"Mandatory/optional in createOffer options is deprecated! Use " +
JSON.stringify(options) + " instead (note the case difference)!",
null, 0);
}
if (this.remoteDescription.type != "offer") {
throw new this._win.DOMError("InvalidStateError",
"No outstanding offer");
}
this._onCreateAnswerSuccess = resolve;
this._onCreateAnswerFailure = reject;
this._impl.createAnswer();
return this._chain(() => new this._win.Promise((resolve, reject) => {
this._onCreateOfferSuccess = resolve;
this._onCreateOfferFailure = reject;
this._impl.createOffer(options);
}));
});
},
createAnswer: function(onSuccess, onError) {
return this._queue(() => this._createAnswer(), onSuccess, onError);
return this._legacyCatch(onSuccess, onError, () => {
return this._chain(() => new this._win.Promise((resolve, reject) => {
// We give up line-numbers in errors by doing this here, but do all
// state-checks inside the chain, to support the legacy feature that
// callers don't have to wait for setRemoteDescription to finish.
if (!this.remoteDescription) {
throw new this._win.DOMException("setRemoteDescription not called",
"InvalidStateError");
}
if (this.remoteDescription.type != "offer") {
throw new this._win.DOMException("No outstanding offer",
"InvalidStateError");
}
this._onCreateAnswerSuccess = resolve;
this._onCreateAnswerFailure = reject;
this._impl.createAnswer();
}));
});
},
setLocalDescription: function(desc, onSuccess, onError) {
this._localType = desc.type;
return this._legacyCatch(onSuccess, onError, () => {
this._localType = desc.type;
let type;
switch (desc.type) {
case "offer":
type = Ci.IPeerConnection.kActionOffer;
break;
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new this._win.DOMError("NotSupportedError", "pranswer not yet implemented");
default:
throw new this._win.DOMError("InvalidParameterError",
"Invalid type " + desc.type + " provided to setLocalDescription");
}
return this._queue(() => this._setLocalDescription(type, desc.sdp),
onSuccess, onError);
},
_setLocalDescription: function(type, sdp) {
return new this._win.Promise((resolve, reject) => {
this._onSetLocalDescriptionSuccess = resolve;
this._onSetLocalDescriptionFailure = reject;
this._impl.setLocalDescription(type, sdp);
let type;
switch (desc.type) {
case "offer":
type = Ci.IPeerConnection.kActionOffer;
break;
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new this._win.DOMException("pranswer not yet implemented",
"NotSupportedError");
default:
throw new this._win.DOMException(
"Invalid type " + desc.type + " provided to setLocalDescription",
"InvalidParameterError");
}
return this._chain(() => new this._win.Promise((resolve, reject) => {
this._onSetLocalDescriptionSuccess = resolve;
this._onSetLocalDescriptionFailure = reject;
this._impl.setLocalDescription(type, desc.sdp);
}));
});
},
setRemoteDescription: function(desc, onSuccess, onError) {
this._remoteType = desc.type;
return this._legacyCatch(onSuccess, onError, () => {
this._remoteType = desc.type;
let type;
switch (desc.type) {
case "offer":
type = Ci.IPeerConnection.kActionOffer;
break;
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new this._win.DOMError("NotSupportedError", "pranswer not yet implemented");
default:
throw new this._win.DOMError("InvalidParameterError",
"Invalid type " + desc.type + " provided to setRemoteDescription");
}
// Have to get caller's origin outside of Promise constructor and pass it in
let origin = Cu.getWebIDLCallerPrincipal().origin;
return this._queue(() => this._setRemoteDescription(type, desc.sdp, origin),
onSuccess, onError);
},
/**
* Takes a result from the IdP and checks it against expectations.
* If OK, generates events.
* Returns true if it is either present and valid, or if there is no
* need for identity.
*/
_processIdpResult: function(message) {
let good = !!message;
// This might be a valid assertion, but if we are constrained to a single peer
// identity, then we also need to make sure that the assertion matches
if (good && this._impl.peerIdentity) {
good = (message.identity === this._impl.peerIdentity);
}
if (good) {
this._impl.peerIdentity = message.identity;
this._peerIdentity = new this._win.RTCIdentityAssertion(
this._remoteIdp.provider, message.identity);
this.dispatchEvent(new this._win.Event("peeridentity"));
}
return good;
},
_setRemoteDescription: function(type, sdp, origin) {
return new this._win.Promise((resolve, reject) =>
this._setRemoteDescriptionImpl(type, sdp, origin, resolve, reject));
},
_setRemoteDescriptionImpl: function(type, sdp, origin, onSuccess, onError) {
let idpComplete = false;
let setRemoteComplete = false;
let idpError = null;
let isDone = false;
// we can run the IdP validation in parallel with setRemoteDescription this
// complicates much more than would be ideal, but it ensures that the IdP
// doesn't hold things up too much when it's not on the critical path
let allDone = () => {
if (!setRemoteComplete || !idpComplete || isDone) {
return;
let type;
switch (desc.type) {
case "offer":
type = Ci.IPeerConnection.kActionOffer;
break;
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new this._win.DOMException("pranswer not yet implemented",
"NotSupportedError");
default:
throw new this._win.DOMException(
"Invalid type " + desc.type + " provided to setRemoteDescription",
"InvalidParameterError");
}
// May be null if the user didn't supply success/failure callbacks.
// Violation of spec, but we allow it for now
onSuccess();
isDone = true;
};
let setRemoteDone = () => {
setRemoteComplete = true;
allDone();
};
// Get caller's origin before chaining and pass it in
let origin = Cu.getWebIDLCallerPrincipal().origin;
// If we aren't waiting for something specific, allow this
// to complete asynchronously.
let idpDone;
if (!this._impl.peerIdentity) {
idpDone = this._processIdpResult.bind(this);
idpComplete = true; // lie about this for allDone()
} else {
idpDone = message => {
let idpGood = this._processIdpResult(message);
if (!idpGood) {
// iff we are waiting for a very specific peerIdentity
// call the error callback directly and then close
idpError = "Peer Identity mismatch, expected: " +
this._impl.peerIdentity;
onError(idpError);
this.close();
} else {
idpComplete = true;
allDone();
}
};
}
return this._chain(() => {
let expectedIdentity = this._impl.peerIdentity;
try {
this._remoteIdp.verifyIdentityFromSDP(sdp, origin, idpDone);
} catch (e) {
// if processing the SDP for identity doesn't work
this.logWarning(e.message, e.fileName, e.lineNumber);
idpDone(null);
}
// Do setRemoteDescription and identity validation in parallel
let p = new this._win.Promise((resolve, reject) => {
this._onSetRemoteDescriptionSuccess = resolve;
this._onSetRemoteDescriptionFailure = reject;
this._impl.setRemoteDescription(type, desc.sdp);
});
this._onSetRemoteDescriptionSuccess = setRemoteDone;
this._onSetRemoteDescriptionFailure = onError;
this._impl.setRemoteDescription(type, sdp);
let pp = new Promise(resolve =>
this._remoteIdp.verifyIdentityFromSDP(desc.sdp, origin, resolve))
.then(msg => {
// If this pc has an identity already, then identity in sdp must match
if (expectedIdentity && (!msg || msg.identity !== expectedIdentity)) {
throw new this._win.DOMException(
"Peer Identity mismatch, expected: " + expectedIdentity,
"IncompatibleSessionDescriptionError");
}
if (msg) {
// Set new identity and generate an event.
this._impl.peerIdentity = msg.identity;
this._peerIdentity = new this._win.RTCIdentityAssertion(
this._remoteIdp.provider, msg.identity);
this.dispatchEvent(new this._win.Event("peeridentity"));
}
});
// Only wait for Idp validation if we need identity matching.
return expectedIdentity? this._win.Promise.all([p, pp]).then(() => {}) : p;
});
});
},
setIdentityProvider: function(provider, protocol, username) {
@ -777,24 +740,21 @@ RTCPeerConnection.prototype = {
},
updateIce: function(config) {
throw new this._win.DOMError("NotSupportedError", "updateIce not yet implemented");
throw new this._win.DOMException("updateIce not yet implemented",
"NotSupportedError");
},
addIceCandidate: function(cand, onSuccess, onError) {
if (!cand.candidate && !cand.sdpMLineIndex) {
throw new this._win.DOMError("InvalidParameterError",
"Invalid candidate passed to addIceCandidate!");
}
return this._queue(() => this._addIceCandidate(cand), onSuccess, onError);
},
_addIceCandidate: function(cand) {
return new this._win.Promise((resolve, reject) => {
this._onAddIceCandidateSuccess = resolve;
this._onAddIceCandidateError = reject;
this._impl.addIceCandidate(cand.candidate, cand.sdpMid || "",
cand.sdpMLineIndex);
addIceCandidate: function(c, onSuccess, onError) {
return this._legacyCatch(onSuccess, onError, () => {
if (!c.candidate && !c.sdpMLineIndex) {
throw new this._win.DOMException("Invalid candidate passed to addIceCandidate!",
"InvalidParameterError");
}
return this._chain(() => new this._win.Promise((resolve, reject) => {
this._onAddIceCandidateSuccess = resolve;
this._onAddIceCandidateError = reject;
this._impl.addIceCandidate(c.candidate, c.sdpMid || "", c.sdpMLineIndex);
}));
});
},
@ -804,19 +764,22 @@ RTCPeerConnection.prototype = {
removeStream: function(stream) {
// Bug 844295: Not implementing this functionality.
throw new this._win.DOMError("NotSupportedError", "removeStream not yet implemented");
throw new this._win.DOMException("removeStream not yet implemented",
"NotSupportedError");
},
getStreamById: function(id) {
throw new this._win.DOMError("NotSupportedError", "getStreamById not yet implemented");
throw new this._win.DOMException("getStreamById not yet implemented",
"NotSupportedError");
},
addTrack: function(track, stream) {
if (stream.currentTime === undefined) {
throw new this._win.DOMError("InvalidParameterError", "invalid stream.");
throw new this._win.DOMException("invalid stream.", "InvalidParameterError");
}
if (stream.getTracks().indexOf(track) == -1) {
throw new this._win.DOMError("InvalidParameterError", "track is not in stream.");
if (stream.getTracks().indexOf(track) < 0) {
throw new this._win.DOMException("track is not in stream.",
"InvalidParameterError");
}
this._checkClosed();
this._impl.addTrack(track, stream);
@ -829,11 +792,12 @@ RTCPeerConnection.prototype = {
removeTrack: function(sender) {
// Bug 844295: Not implementing this functionality.
throw new this._win.DOMError("NotSupportedError", "removeTrack not yet implemented");
throw new this._win.DOMException("removeTrack not yet implemented",
"NotSupportedError");
},
_replaceTrack: function(sender, withTrack) {
// TODO: Do a (sender._stream.getTracks().indexOf(track) == -1) check
// TODO: Do a (sender._stream.getTracks().indexOf(track) < 0) check
// on both track args someday.
//
// The proposed API will be that both tracks must already be in the same
@ -961,14 +925,12 @@ RTCPeerConnection.prototype = {
},
getStats: function(selector, onSuccess, onError) {
return this._queue(() => this._getStats(selector), onSuccess, onError);
},
_getStats: function(selector) {
return new this._win.Promise((resolve, reject) => {
this._onGetStatsSuccess = resolve;
this._onGetStatsFailure = reject;
this._impl.getStats(selector);
return this._legacyCatch(onSuccess, onError, () => {
return this._chain(() => new this._win.Promise((resolve, reject) => {
this._onGetStatsSuccess = resolve;
this._onGetStatsFailure = reject;
this._impl.getStats(selector);
}));
});
},
@ -995,10 +957,10 @@ RTCPeerConnection.prototype = {
this.logWarning("Deprecated RTCDataChannelInit dictionary entry stream used!", null, 0);
}
if (dict.maxRetransmitTime != undefined &&
dict.maxRetransmits != undefined) {
throw new this._win.DOMError("InvalidParameterError",
"Both maxRetransmitTime and maxRetransmits cannot be provided");
if (dict.maxRetransmitTime !== null && dict.maxRetransmits !== null) {
throw new this._win.DOMException(
"Both maxRetransmitTime and maxRetransmits cannot be provided",
"InvalidParameterError");
}
let protocol;
if (dict.protocol == undefined) {
@ -1043,7 +1005,7 @@ PeerConnectionObserver.prototype = {
this._dompc = dompc._innerObject;
},
newError: function(code, message) {
newError: function(message, code) {
// These strings must match those defined in the WebRTC spec.
const reasonName = [
"",
@ -1058,7 +1020,7 @@ PeerConnectionObserver.prototype = {
"InternalError"
];
let name = reasonName[Math.min(code, reasonName.length - 1)];
return new this._dompc._win.DOMError(name, message);
return new this._dompc._win.DOMException(message, name);
},
dispatchEvent: function(event) {
@ -1079,7 +1041,7 @@ PeerConnectionObserver.prototype = {
},
onCreateOfferError: function(code, message) {
this._dompc._onCreateOfferFailure(this.newError(code, message));
this._dompc._onCreateOfferFailure(this.newError(message, code));
},
onCreateAnswerSuccess: function(sdp) {
@ -1096,7 +1058,7 @@ PeerConnectionObserver.prototype = {
},
onCreateAnswerError: function(code, message) {
this._dompc._onCreateAnswerFailure(this.newError(code, message));
this._dompc._onCreateAnswerFailure(this.newError(message, code));
},
onSetLocalDescriptionSuccess: function() {
@ -1109,12 +1071,12 @@ PeerConnectionObserver.prototype = {
onSetLocalDescriptionError: function(code, message) {
this._localType = null;
this._dompc._onSetLocalDescriptionFailure(this.newError(code, message));
this._dompc._onSetLocalDescriptionFailure(this.newError(message, code));
},
onSetRemoteDescriptionError: function(code, message) {
this._remoteType = null;
this._dompc._onSetRemoteDescriptionFailure(this.newError(code, message));
this._dompc._onSetRemoteDescriptionFailure(this.newError(message, code));
},
onAddIceCandidateSuccess: function() {
@ -1122,7 +1084,7 @@ PeerConnectionObserver.prototype = {
},
onAddIceCandidateError: function(code, message) {
this._dompc._onAddIceCandidateError(this.newError(code, message));
this._dompc._onAddIceCandidateError(this.newError(message, code));
},
onIceCandidate: function(level, mid, candidate) {
@ -1250,7 +1212,7 @@ PeerConnectionObserver.prototype = {
},
onGetStatsError: function(code, message) {
this._dompc._onGetStatsFailure(this.newError(code, message));
this._dompc._onGetStatsFailure(this.newError(message, code));
},
onAddStream: function(stream) {
@ -1287,7 +1249,7 @@ PeerConnectionObserver.prototype = {
var pc = this._dompc;
pc._onReplaceTrackWithTrack = null;
pc._onReplaceTrackSender = null;
pc._onReplaceTrackError(this.newError(code, message));
pc._onReplaceTrackError(this.newError(message, code));
},
foundIceCandidate: function(cand) {
@ -1333,7 +1295,7 @@ RTCRtpSender.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
replaceTrack: function(withTrack) {
return this._pc._queue(() => this._pc._replaceTrack(this, withTrack));
return this._pc._chain(() => this._pc._replaceTrack(this, withTrack));
}
};

View File

@ -95,9 +95,12 @@ PeerConnectionIdp.prototype = {
_getIdentityFromSdp: function(sdp) {
// a=identity is session level
let idMatch;
let mLineMatch = sdp.match(PeerConnectionIdp._mLinePattern);
let sessionLevel = sdp.substring(0, mLineMatch.index);
let idMatch = sessionLevel.match(PeerConnectionIdp._identityPattern);
if (mLineMatch) {
let sessionLevel = sdp.substring(0, mLineMatch.index);
idMatch = sessionLevel.match(PeerConnectionIdp._identityPattern);
}
if (idMatch) {
let assertion = {};
try {

View File

@ -18,6 +18,7 @@
#include "mp4_demuxer/DecoderData.h"
#include "prlog.h"
#include "gfx2DGlue.h"
#include "gfxWindowsPlatform.h"
#ifdef PR_LOGGING
PRLogModuleInfo* GetDemuxerLog();
@ -149,6 +150,10 @@ WMFVideoMFTManager::InitializeDXVA()
return false;
}
if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
return false;
}
// The DXVA manager must be created on the main thread.
nsRefPtr<CreateDXVAManagerEvent> event(new CreateDXVAManagerEvent());
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);

View File

@ -22,3 +22,5 @@ UNIFIED_SOURCES += [
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']

View File

@ -317,7 +317,7 @@ GMPChild::PreLoadLibraries(const std::string& aPluginPath)
std::ifstream stream;
#ifdef _MSC_VER
stream.open(path.get());
stream.open(static_cast<const wchar_t*>(path.get()));
#else
stream.open(NS_ConvertUTF16toUTF8(path).get());
#endif

View File

@ -13,10 +13,6 @@ namespace mozilla
class MockMediaDecoderOwner : public MediaDecoderOwner
{
public:
virtual nsresult DispatchEvent(const nsAString& aName) MOZ_OVERRIDE
{
return NS_OK;
}
virtual nsresult DispatchAsyncEvent(const nsAString& aName) MOZ_OVERRIDE
{
return NS_OK;

View File

@ -339,7 +339,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
bool evicted = toEvict < (totalSize - aThreshold);
if (evicted) {
nsRefPtr<TimeRanges> ranges = new TimeRanges();
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
mCurrentDecoder->GetBuffered(ranges);
*aBufferStartTime = std::max(0.0, ranges->GetStartTime());
}

View File

@ -27,25 +27,25 @@ runWithMSE(function (ms, v) {
v.addEventListener("loadedmetadata", function () {
v.addEventListener("durationchange", function () {
durationChangeCount++;
if (durationChangeCount == 1) {
sb.addEventListener('updateend', function(e) {
sb.removeEventListener('updateend', arguments.callee);
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
});
}
});
// Set mediasource duration to 0, so future appendBuffer
// will update the mediasource duration
// setting ms.duration will fire updatestart/update/updateend
// event as per w3c spec
// event as per w3c spec followed by a durationchange
ms.duration = 0;
});
} else if (updateCount == 2) {
// will fire updatestart/update/updateend
// and a durationchange
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
} else if (updateCount == 3) {
// this will not fire durationchange as new duration == old duration
ms.endOfStream();
}
});
});
});
v.addEventListener("loadeddata", function () {
ms.addEventListener("sourceended", function () {
// XXX: Duration should be exactly 4.0, see bug 1065207.
is(durationChangeCount, 2, "durationchange not fired as many times as expected");
ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");

View File

@ -251,7 +251,7 @@ LOCAL_INCLUDES += [
'/dom/camera',
'/layout/generic',
'/layout/xul',
'/netwerk/base/src',
'/netwerk/base',
]
if CONFIG['MOZ_DIRECTSHOW']:

View File

@ -511,9 +511,13 @@ bool MediaCodecProxy::Prepare()
bool MediaCodecProxy::UpdateOutputBuffers()
{
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from input!");
return false;
// Read Lock for mCodec
{
RWLock::AutoRLock autolock(mCodecLock);
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from UpdateOutputBuffers");
return false;
}
}
status_t err = getOutputBuffers(&mOutputBuffers);
@ -527,9 +531,13 @@ bool MediaCodecProxy::UpdateOutputBuffers()
status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
int64_t aTimestampUsecs, uint64_t aflags)
{
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from input!");
return NO_INIT;
// Read Lock for mCodec
{
RWLock::AutoRLock autolock(mCodecLock);
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from input!");
return NO_INIT;
}
}
size_t index;
@ -560,9 +568,13 @@ status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
status_t MediaCodecProxy::Output(MediaBuffer** aBuffer, int64_t aTimeoutUs)
{
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from output!");
return NO_INIT;
// Read Lock for mCodec
{
RWLock::AutoRLock autolock(mCodecLock);
if (mCodec == nullptr) {
MCP_LOG("MediaCodec has not been inited from output!");
return NO_INIT;
}
}
size_t index = 0;

View File

@ -33,6 +33,7 @@
#include "MediaStreamSource.h"
#include "MediaTaskQueue.h"
#include "MP3FrameParser.h"
#include "nsMimeTypes.h"
#include "nsThreadUtils.h"
#include "ImageContainer.h"
#include "SharedThreadPool.h"
@ -688,7 +689,9 @@ MediaCodecReader::ReadMetadata(MediaInfo* aInfo,
return NS_ERROR_FAILURE;
}
if (!TriggerIncrementalParser()) {
bool incrementalParserNeeded =
mDecoder->GetResource()->GetContentType().EqualsASCII(AUDIO_MP3);
if (incrementalParserNeeded && !TriggerIncrementalParser()) {
return NS_ERROR_FAILURE;
}
@ -1419,10 +1422,10 @@ MediaCodecReader::TriggerIncrementalParser()
mParsedDataLength = INT64_C(0);
// MP3 file duration
mMP3FrameParser = new MP3FrameParser(mDecoder->GetResource()->GetLength());
const char* mime = nullptr;
if (mMetaData->findCString(kKeyMIMEType, &mime) &&
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
mMP3FrameParser = new MP3FrameParser(mDecoder->GetResource()->GetLength());
{
MonitorAutoUnlock monUnlock(mParserMonitor);
// trigger parsing logic and wait for finishing parsing data in the beginning.

View File

@ -26,14 +26,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// For M_PI from cmath
#ifdef _MSC_VER
# define _USE_MATH_DEFINES
#endif
// For M_PI
// VS2015 requires <math.h> to be used; <cmath> doesn't seem to honor
// _USE_MATH_DEFINES.
#define _USE_MATH_DEFINES
#include <math.h>
#include "Biquad.h"
#include <cmath>
#include <float.h>
#include <algorithm>

View File

@ -32,7 +32,7 @@ using dom::ConstrainLongRange;
NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
MediaEngineTabVideoSource::MediaEngineTabVideoSource()
: mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
: mData(NULL), mDataSize(0), mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
{
}
@ -79,7 +79,6 @@ MediaEngineTabVideoSource::Notify(nsITimer*) {
nsresult
MediaEngineTabVideoSource::InitRunnable::Run()
{
mVideoSource->mData = (unsigned char*)malloc(mVideoSource->mBufW * mVideoSource->mBufH * 4);
if (mVideoSource->mWindowId != -1) {
nsCOMPtr<nsPIDOMWindow> window = nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
if (window) {
@ -150,20 +149,10 @@ MediaEngineTabVideoSource::Allocate(const VideoTrackConstraintsN& aConstraints,
}
}
mBufW = aPrefs.GetWidth(false);
mBufH = aPrefs.GetHeight(false);
ConstrainLongRange defaultRange;
if (cWidth.mMin > mBufW) {
mBufW = cWidth.mMin;
} else if (cWidth.mMax < mBufW) {
mBufW = cWidth.mMax;
}
if (cHeight.mMin > mBufH) {
mBufH = cHeight.mMin;
} else if (cHeight.mMax < mBufH) {
mBufH = cHeight.mMax;
}
mBufWidthMax = defaultRange.mMax > cWidth.mMax ? cWidth.mMax : aPrefs.GetWidth(false);
mBufHeightMax = defaultRange.mMax > cHeight.mMax ? cHeight.mMax : aPrefs.GetHeight(false);
mTimePerFrame = aPrefs.mFPS ? 1000 / aPrefs.mFPS : aPrefs.mFPS;
return NS_OK;
@ -213,35 +202,38 @@ MediaEngineTabVideoSource::NotifyPull(MediaStreamGraph*,
void
MediaEngineTabVideoSource::Draw() {
IntSize size(mBufW, mBufH);
nsresult rv;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mWindow);
if (!win) {
return;
}
int32_t width, height;
win->GetInnerWidth(&width);
win->GetInnerHeight(&height);
int32_t innerWidth, innerHeight;
win->GetInnerWidth(&innerWidth);
win->GetInnerHeight(&innerHeight);
if (width == 0 || height == 0) {
if (innerWidth == 0 || innerHeight == 0) {
return;
}
int32_t srcW;
int32_t srcH;
float aspectRatio = ((float) size.width) / size.height;
if (width / aspectRatio < height) {
srcW = width;
srcH = width / aspectRatio;
IntSize size;
// maintain source aspect ratio
if (mBufWidthMax/innerWidth < mBufHeightMax/innerHeight) {
size = IntSize(mBufWidthMax, (mBufWidthMax * ((float) innerHeight/innerWidth)));
} else {
srcW = height * aspectRatio;
srcH = height;
size = IntSize((mBufHeightMax * ((float) innerWidth/innerHeight)), mBufHeightMax);
}
gfxImageFormat format = gfxImageFormat::RGB24;
uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
if (mDataSize < static_cast<size_t>(stride * size.height)) {
mDataSize = stride * size.height;
mData = static_cast<unsigned char*>(malloc(mDataSize));
}
if (!mData) {
return;
}
nsRefPtr<nsPresContext> presContext;
@ -259,11 +251,8 @@ MediaEngineTabVideoSource::Draw() {
if (!mScrollWithPage) {
renderDocFlags |= nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
}
nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)srcW),
nsPresContext::CSSPixelsToAppUnits((float)srcH));
gfxImageFormat format = gfxImageFormat::RGB24;
uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)innerWidth),
nsPresContext::CSSPixelsToAppUnits((float)innerHeight));
nsRefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
RefPtr<DrawTarget> dt =
@ -276,12 +265,10 @@ MediaEngineTabVideoSource::Draw() {
return;
}
nsRefPtr<gfxContext> context = new gfxContext(dt);
context->SetMatrix(context->CurrentMatrix().Scale((float)size.width/srcW,
(float)size.height/srcH));
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/innerWidth),
(((float) size.height)/innerHeight)));
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS_VOID(rv);
NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
RefPtr<SourceSurface> surface = dt->Snapshot();
if (!surface) {

View File

@ -70,12 +70,13 @@ protected:
~MediaEngineTabVideoSource() {}
private:
int mBufW;
int mBufH;
int mBufWidthMax;
int mBufHeightMax;
int64_t mWindowId;
bool mScrollWithPage;
int mTimePerFrame;
ScopedFreePtr<unsigned char> mData;
size_t mDataSize;
nsCOMPtr<nsIDOMWindow> mWindow;
nsRefPtr<layers::CairoImage> mImage;
nsCOMPtr<nsITimer> mTimer;

View File

@ -17,6 +17,7 @@
#include "ImageContainer.h"
#include "Layers.h"
#include "mozilla/layers/LayersTypes.h"
#include "gfxWindowsPlatform.h"
#ifndef MOZ_SAMPLE_TYPE_FLOAT32
#error We expect 32bit float audio samples on desktop for the Windows Media Foundation media backend.
@ -110,6 +111,10 @@ WMFReader::InitializeDXVA()
return false;
}
if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
return false;
}
mDXVA2Manager = DXVA2Manager::Create();
return mDXVA2Manager != nullptr;

View File

@ -30,3 +30,5 @@ FINAL_LIBRARY = 'xul'
if CONFIG['OS_ARCH'] == 'WINNT':
DEFINES['NOMINMAX'] = True
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']

View File

@ -29,5 +29,5 @@ FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/caps',
'/netwerk/base/src',
'/netwerk/base',
]

View File

@ -11179,248 +11179,250 @@
46753a52402,52403
> terahertz/M
> terapixel/MS
46806,46807c52456
46756a52407
> teriyaki
46806,46807c52457
< test's/AFK
< test/AKFCDGS
---
> test/AKFCDGSM
46817a52467
46817a52468
> testcase/MS
46831a52482
46831a52483
> testsuite/MS
46845a52497
46845a52498
> textbox/SM
46925a52578
46925a52579
> theremin/MS
46999c52652
46999c52653
< thinking's
---
> thinking/M
47095,47096c52748
47095,47096c52749
< throne's
< throne/CDS
---
> throne/CDSM
47188,47189c52840
47188,47189c52841
< tie's
< tie/AUSD
---
> tie/AUSDM
47213,47214c52864
47213,47214c52865
< till's
< till/EDRZGS
---
> till/EDRZGSM
47303,47304c52953
47303,47304c52954
< tire's
< tire/AGDS
---
> tire/AGDSM
47433,47434c53082
47433,47434c53083
< tone's
< tone/IZGDRS
---
> tone/IZGDRSM
47453,47455c53101,53102
47453,47455c53102,53103
< tool's
< tool/ADGS
< toolbar
---
> tool/ADGSM
> toolbar/MS
47540,47541c53187
47540,47541c53188
< tort's
< tort/FEAS
---
> tort/FEASM
47644a53291
47644a53292
> traceur/SM
47657,47658c53304
47657,47658c53305
< tract's
< tract/CEKFAS
---
> tract/CEKFASM
47755a53402
47755a53403
> transfect/DSMG
47774a53422,53423
47774a53423,53424
> transgenderism
> transgene/MS
47807,47808c53456
47807,47808c53457
< transmission's
< transmission/AS
---
> transmission/ASM
47928,47929c53576
47928,47929c53577
< trench's
< trench/AIGSD
---
> trench/AIGSDM
47951c53598
47951c53599
< triage/M
---
> triage/MGS
47976,47977c53623
47976,47977c53624
< tribute's
< tribute/FS
---
> tribute/FSM
47997a53644
47997a53645
> trifecta/S
48165,48166c53812
48165,48166c53813
< trust's/E
< trust/IESGD
---
> trust/IESGDM
48180,48181c53826
48180,48181c53827
< try's
< try/AGDS
---
> try/AGDSM
48271a53917
48271a53918
> turducken
48334a53981
48334a53982
> tweep/S
48371,48372c54018
48371,48372c54019
< twist's
< twist/USDG
---
> twist/USDGM
48396,48397c54042
48396,48397c54043
< type's
< type/AGDS
---
> type/AGDSM
48869a54515
48869a54516
> unlikeable
49163,49164c54809
49163,49164c54810
< usual's
< usual/UY
---
> usual/UYM
49211c54856
49211c54857
< vagina/M
---
> vagina/MS
49249,49250c54894
49249,49250c54895
< value's
< value/CAGSD
---
> value/CAGSDM
49292,49293c54936
49292,49293c54937
< variant's
< variant/IS
---
> variant/ISM
49356,49357c54999
49356,49357c55000
< veil's
< veil/UDGS
---
> veil/UDGSM
49368,49369c55010
49368,49369c55011
< velour's
< velours's
---
> velour/MS
49398,49399c55039
49398,49399c55040
< vent's
< vent/DGS
---
> vent/DGSM
49435,49436c55075
49435,49436c55076
< verge's
< verge/FDSG
---
> verge/FDSGM
49478a55118
49478a55119
> vertices
49488,49489c55128
49488,49489c55129
< vest's
< vest/ILDGS
---
> vest/ILDGSM
49681,49682c55320
49681,49682c55321
< visit's
< visit/ASGD
---
> visit/ASGDM
49772a55411,55413
49772a55412,55414
> volcanological
> volcanologist/MS
> volcanology/M
49807,49808c55448
49807,49808c55449
< vote's
< vote/CGVDS
---
> vote/CGVDSM
50148a55789
50148a55790
> weaponize/DSG
50215,50216c55856
50215,50216c55857
< weigh's
< weigh/AGD
---
> weigh/AGDM
50260,50261d55899
50260,50261d55900
< werwolf/M
< werwolves
50555,50556c56193
50555,50556c56194
< wind's
< wind/UASG
---
> wind/UASGM
50626,50627c56263
50626,50627c56264
< wire's
< wire/AGDS
---
> wire/AGDSM
50728c56364
50728c56365
< women
---
> women/M
50794,50796c56430,56431
50794,50796c56431,56432
< wop/S!
< word's
< word/AJDSG
---
> wop/MS!
> word/AJDSGM
50801c56436
50801c56437
< wording's
---
> wording/M
50808,50809c56443
50808,50809c56444
< work's
< work/ADJSG
---
> work/ADJSGM
50824c56458
50824c56459
< working's
---
> working/M
50884,50885c56518
50884,50885c56519
< worthy's
< worthy/UPRT
---
> worthy/UPRTM
50903,50904c56536
50903,50904c56537
< wrap's
< wrap/US
---
> wrap/USM
50945c56577
50945c56578
< writing's
---
> writing/M
51118,51119c56750
51118,51119c56751
< yoke's
< yoke/UGDS
---
> yoke/UGDSM
51212,51213c56843
51212,51213c56844
< zip's
< zip/US
---
> zip/USM
51228,51229c56858
51228,51229c56859
< zone's
< zone/AGDS
---

View File

@ -1,4 +1,4 @@
57245
57246
0/nm
0th/pt
1/n1
@ -52757,6 +52757,7 @@ terapixel/MS
terbium/M
tercentenary/SM
tercentennial/MS
teriyaki
term/MDYGS
termagant/MS
terminable/IC

View File

@ -12,7 +12,7 @@
#include <fstream>
#if defined(_MSC_VER)
#include <hash_set>
#include <unordered_set>
#else
#include <set>
#endif
@ -53,7 +53,7 @@ protected:
virtual void Flush() = 0;
#if defined(_MSC_VER)
typedef stdext::hash_set<const void*> ObjectSet;
typedef std::unordered_set<const void*> ObjectSet;
#else
typedef std::set<const void*> ObjectSet;
#endif

View File

@ -14,11 +14,7 @@
#include <vector>
#include <sstream>
#ifdef _MSC_VER
#include <hash_set>
#else
#include <unordered_set>
#endif
struct IDWriteFactory;
@ -165,11 +161,7 @@ private:
friend class AutoSaveRestoreClippedOut;
friend class SourceSurfaceD2DTarget;
#ifdef _MSC_VER
typedef stdext::hash_set<DrawTargetD2D*> TargetSet;
#else
typedef std::unordered_set<DrawTargetD2D*> TargetSet;
#endif
bool InitD2DRenderTarget();
void PrepareForDrawing(ID2D1RenderTarget *aRT);

View File

@ -15,11 +15,7 @@
#include <vector>
#include <sstream>
#ifdef _MSC_VER
#include <hash_set>
#else
#include <unordered_set>
#endif
struct IDWriteFactory;
@ -154,11 +150,7 @@ public:
private:
friend class SourceSurfaceD2D1;
#ifdef _MSC_VER
typedef stdext::hash_set<DrawTargetD2D1*> TargetSet;
#else
typedef std::unordered_set<DrawTargetD2D1*> TargetSet;
#endif
// This function will mark the surface as changing, and make sure any
// copy-on-write snapshots are notified.

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et: */
/* 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/. */
@ -365,6 +366,8 @@ StaticAutoPtr<LayerScopeWebSocketManager> WebSocketHelper::sWebSocketManager;
* 1. DebugGLFrameStatusData (Frame start/end packet)
* 2. DebugGLColorData (Color data packet)
* 3. DebugGLTextureData (Texture data packet)
* 4. DebugGLLayersData (Layers Tree data packet)
* 5. DebugGLMetaData (Meta data packet)
*/
class DebugGLData: public LinkedListElement<DebugGLData> {
public:
@ -566,6 +569,37 @@ protected:
UniquePtr<Packet> mPacket;
};
class DebugGLMetaData : public DebugGLData
{
public:
DebugGLMetaData(Packet::DataType aDataType,
bool aValue)
: DebugGLData(aDataType),
mComposedByHwc(aValue)
{ }
explicit DebugGLMetaData(Packet::DataType aDataType)
: DebugGLData(aDataType),
mComposedByHwc(false)
{ }
virtual bool Write() MOZ_OVERRIDE {
Packet packet;
packet.set_type(mDataType);
MetaPacket* mp = packet.mutable_meta();
mp->set_composedbyhwc(mComposedByHwc);
if (!WriteToStream(packet))
return false;
return true;
}
protected:
bool mComposedByHwc;
};
class DebugListener : public nsIServerSocketListener
{
virtual ~DebugListener() { }
@ -1005,6 +1039,16 @@ LayerScope::CleanLayer()
}
}
void
LayerScope::SetHWComposed()
{
if (CheckSendable()) {
WebSocketHelper::GetSocketManager()->AppendDebugData(
new DebugGLMetaData(Packet::META, true));
}
}
// ----------------------------------------------
// LayerScopeAutoFrame implementation
// ----------------------------------------------

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et: */
/* 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/. */
@ -34,6 +35,7 @@ public:
static void SendLayerDump(UniquePtr<layerscope::Packet> aPacket);
static bool CheckSendable();
static void CleanLayer();
static void SetHWComposed();
private:
static void Init();

View File

@ -662,6 +662,7 @@ LayerManagerComposite::Render()
}
if (!mTarget && composer2D && composer2D->TryRender(mRoot, mGeometryChanged)) {
LayerScope::SetHWComposed();
if (mFPS) {
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
if (gfxPrefs::LayersDrawFPS()) {

View File

@ -25,6 +25,7 @@ void protobuf_ShutdownFile_LayerScopePacket_2eproto() {
delete LayersPacket_Layer_Region::default_instance_;
delete LayersPacket_Layer_Matrix::default_instance_;
delete LayersPacket_Layer_Shadow::default_instance_;
delete MetaPacket::default_instance_;
delete Packet::default_instance_;
}
@ -44,6 +45,7 @@ void protobuf_AddDesc_LayerScopePacket_2eproto() {
LayersPacket_Layer_Region::default_instance_ = new LayersPacket_Layer_Region();
LayersPacket_Layer_Matrix::default_instance_ = new LayersPacket_Layer_Matrix();
LayersPacket_Layer_Shadow::default_instance_ = new LayersPacket_Layer_Shadow();
MetaPacket::default_instance_ = new MetaPacket();
Packet::default_instance_ = new Packet();
FramePacket::default_instance_->InitAsDefaultInstance();
ColorPacket::default_instance_->InitAsDefaultInstance();
@ -55,6 +57,7 @@ void protobuf_AddDesc_LayerScopePacket_2eproto() {
LayersPacket_Layer_Region::default_instance_->InitAsDefaultInstance();
LayersPacket_Layer_Matrix::default_instance_->InitAsDefaultInstance();
LayersPacket_Layer_Shadow::default_instance_->InitAsDefaultInstance();
MetaPacket::default_instance_->InitAsDefaultInstance();
Packet::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_LayerScopePacket_2eproto);
}
@ -3028,6 +3031,162 @@ void LayersPacket::Swap(LayersPacket* other) {
}
// ===================================================================
#ifndef _MSC_VER
const int MetaPacket::kComposedByHwcFieldNumber;
#endif // !_MSC_VER
MetaPacket::MetaPacket()
: ::google::protobuf::MessageLite() {
SharedCtor();
}
void MetaPacket::InitAsDefaultInstance() {
}
MetaPacket::MetaPacket(const MetaPacket& from)
: ::google::protobuf::MessageLite() {
SharedCtor();
MergeFrom(from);
}
void MetaPacket::SharedCtor() {
_cached_size_ = 0;
composedbyhwc_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
MetaPacket::~MetaPacket() {
SharedDtor();
}
void MetaPacket::SharedDtor() {
if (this != default_instance_) {
}
}
void MetaPacket::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const MetaPacket& MetaPacket::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto(); return *default_instance_;
}
MetaPacket* MetaPacket::default_instance_ = NULL;
MetaPacket* MetaPacket::New() const {
return new MetaPacket;
}
void MetaPacket::Clear() {
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
composedbyhwc_ = false;
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
bool MetaPacket::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional bool composedByHwc = 1;
case 1: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
input, &composedbyhwc_)));
set_has_composedbyhwc();
} else {
goto handle_uninterpreted;
}
if (input->ExpectAtEnd()) return true;
break;
}
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
break;
}
}
}
return true;
#undef DO_
}
void MetaPacket::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// optional bool composedByHwc = 1;
if (has_composedbyhwc()) {
::google::protobuf::internal::WireFormatLite::WriteBool(1, this->composedbyhwc(), output);
}
}
int MetaPacket::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional bool composedByHwc = 1;
if (has_composedbyhwc()) {
total_size += 1 + 1;
}
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void MetaPacket::CheckTypeAndMergeFrom(
const ::google::protobuf::MessageLite& from) {
MergeFrom(*::google::protobuf::down_cast<const MetaPacket*>(&from));
}
void MetaPacket::MergeFrom(const MetaPacket& from) {
GOOGLE_CHECK_NE(&from, this);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_composedbyhwc()) {
set_composedbyhwc(from.composedbyhwc());
}
}
}
void MetaPacket::CopyFrom(const MetaPacket& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool MetaPacket::IsInitialized() const {
return true;
}
void MetaPacket::Swap(MetaPacket* other) {
if (other != this) {
std::swap(composedbyhwc_, other->composedbyhwc_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
std::swap(_cached_size_, other->_cached_size_);
}
}
::std::string MetaPacket::GetTypeName() const {
return "mozilla.layers.layerscope.MetaPacket";
}
// ===================================================================
bool Packet_DataType_IsValid(int value) {
@ -3037,6 +3196,7 @@ bool Packet_DataType_IsValid(int value) {
case 3:
case 4:
case 5:
case 6:
return true;
default:
return false;
@ -3049,6 +3209,7 @@ const Packet_DataType Packet::FRAMEEND;
const Packet_DataType Packet::COLOR;
const Packet_DataType Packet::TEXTURE;
const Packet_DataType Packet::LAYERS;
const Packet_DataType Packet::META;
const Packet_DataType Packet::DataType_MIN;
const Packet_DataType Packet::DataType_MAX;
const int Packet::DataType_ARRAYSIZE;
@ -3059,6 +3220,7 @@ const int Packet::kFrameFieldNumber;
const int Packet::kColorFieldNumber;
const int Packet::kTextureFieldNumber;
const int Packet::kLayersFieldNumber;
const int Packet::kMetaFieldNumber;
#endif // !_MSC_VER
Packet::Packet()
@ -3071,6 +3233,7 @@ void Packet::InitAsDefaultInstance() {
color_ = const_cast< ::mozilla::layers::layerscope::ColorPacket*>(&::mozilla::layers::layerscope::ColorPacket::default_instance());
texture_ = const_cast< ::mozilla::layers::layerscope::TexturePacket*>(&::mozilla::layers::layerscope::TexturePacket::default_instance());
layers_ = const_cast< ::mozilla::layers::layerscope::LayersPacket*>(&::mozilla::layers::layerscope::LayersPacket::default_instance());
meta_ = const_cast< ::mozilla::layers::layerscope::MetaPacket*>(&::mozilla::layers::layerscope::MetaPacket::default_instance());
}
Packet::Packet(const Packet& from)
@ -3086,6 +3249,7 @@ void Packet::SharedCtor() {
color_ = NULL;
texture_ = NULL;
layers_ = NULL;
meta_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -3099,6 +3263,7 @@ void Packet::SharedDtor() {
delete color_;
delete texture_;
delete layers_;
delete meta_;
}
}
@ -3132,6 +3297,9 @@ void Packet::Clear() {
if (has_layers()) {
if (layers_ != NULL) layers_->::mozilla::layers::layerscope::LayersPacket::Clear();
}
if (has_meta()) {
if (meta_ != NULL) meta_->::mozilla::layers::layerscope::MetaPacket::Clear();
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -3212,6 +3380,20 @@ bool Packet::MergePartialFromCodedStream(
} else {
goto handle_uninterpreted;
}
if (input->ExpectTag(50)) goto parse_meta;
break;
}
// optional .mozilla.layers.layerscope.MetaPacket meta = 6;
case 6: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
parse_meta:
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, mutable_meta()));
} else {
goto handle_uninterpreted;
}
if (input->ExpectAtEnd()) return true;
break;
}
@ -3263,6 +3445,12 @@ void Packet::SerializeWithCachedSizes(
5, this->layers(), output);
}
// optional .mozilla.layers.layerscope.MetaPacket meta = 6;
if (has_meta()) {
::google::protobuf::internal::WireFormatLite::WriteMessage(
6, this->meta(), output);
}
}
int Packet::ByteSize() const {
@ -3303,6 +3491,13 @@ int Packet::ByteSize() const {
this->layers());
}
// optional .mozilla.layers.layerscope.MetaPacket meta = 6;
if (has_meta()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->meta());
}
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
@ -3333,6 +3528,9 @@ void Packet::MergeFrom(const Packet& from) {
if (from.has_layers()) {
mutable_layers()->::mozilla::layers::layerscope::LayersPacket::MergeFrom(from.layers());
}
if (from.has_meta()) {
mutable_meta()->::mozilla::layers::layerscope::MetaPacket::MergeFrom(from.meta());
}
}
}
@ -3364,6 +3562,7 @@ void Packet::Swap(Packet* other) {
std::swap(color_, other->color_);
std::swap(texture_, other->texture_);
std::swap(layers_, other->layers_);
std::swap(meta_, other->meta_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
std::swap(_cached_size_, other->_cached_size_);
}

View File

@ -43,6 +43,7 @@ class LayersPacket_Layer_Rect;
class LayersPacket_Layer_Region;
class LayersPacket_Layer_Matrix;
class LayersPacket_Layer_Shadow;
class MetaPacket;
class Packet;
enum LayersPacket_Layer_LayerType {
@ -89,11 +90,12 @@ enum Packet_DataType {
Packet_DataType_FRAMEEND = 2,
Packet_DataType_COLOR = 3,
Packet_DataType_TEXTURE = 4,
Packet_DataType_LAYERS = 5
Packet_DataType_LAYERS = 5,
Packet_DataType_META = 6
};
bool Packet_DataType_IsValid(int value);
const Packet_DataType Packet_DataType_DataType_MIN = Packet_DataType_FRAMESTART;
const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_LAYERS;
const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_META;
const int Packet_DataType_DataType_ARRAYSIZE = Packet_DataType_DataType_MAX + 1;
// ===================================================================
@ -1229,6 +1231,75 @@ class LayersPacket : public ::google::protobuf::MessageLite {
};
// -------------------------------------------------------------------
class MetaPacket : public ::google::protobuf::MessageLite {
public:
MetaPacket();
virtual ~MetaPacket();
MetaPacket(const MetaPacket& from);
inline MetaPacket& operator=(const MetaPacket& from) {
CopyFrom(from);
return *this;
}
static const MetaPacket& default_instance();
void Swap(MetaPacket* other);
// implements Message ----------------------------------------------
MetaPacket* New() const;
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
void CopyFrom(const MetaPacket& from);
void MergeFrom(const MetaPacket& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::std::string GetTypeName() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional bool composedByHwc = 1;
inline bool has_composedbyhwc() const;
inline void clear_composedbyhwc();
static const int kComposedByHwcFieldNumber = 1;
inline bool composedbyhwc() const;
inline void set_composedbyhwc(bool value);
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.MetaPacket)
private:
inline void set_has_composedbyhwc();
inline void clear_has_composedbyhwc();
bool composedbyhwc_;
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
friend void protobuf_AddDesc_LayerScopePacket_2eproto();
friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
void InitAsDefaultInstance();
static MetaPacket* default_instance_;
};
// -------------------------------------------------------------------
class Packet : public ::google::protobuf::MessageLite {
public:
Packet();
@ -1276,6 +1347,7 @@ class Packet : public ::google::protobuf::MessageLite {
static const DataType COLOR = Packet_DataType_COLOR;
static const DataType TEXTURE = Packet_DataType_TEXTURE;
static const DataType LAYERS = Packet_DataType_LAYERS;
static const DataType META = Packet_DataType_META;
static inline bool DataType_IsValid(int value) {
return Packet_DataType_IsValid(value);
}
@ -1327,6 +1399,14 @@ class Packet : public ::google::protobuf::MessageLite {
inline ::mozilla::layers::layerscope::LayersPacket* mutable_layers();
inline ::mozilla::layers::layerscope::LayersPacket* release_layers();
// optional .mozilla.layers.layerscope.MetaPacket meta = 6;
inline bool has_meta() const;
inline void clear_meta();
static const int kMetaFieldNumber = 6;
inline const ::mozilla::layers::layerscope::MetaPacket& meta() const;
inline ::mozilla::layers::layerscope::MetaPacket* mutable_meta();
inline ::mozilla::layers::layerscope::MetaPacket* release_meta();
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.Packet)
private:
inline void set_has_type();
@ -1339,15 +1419,18 @@ class Packet : public ::google::protobuf::MessageLite {
inline void clear_has_texture();
inline void set_has_layers();
inline void clear_has_layers();
inline void set_has_meta();
inline void clear_has_meta();
::mozilla::layers::layerscope::FramePacket* frame_;
::mozilla::layers::layerscope::ColorPacket* color_;
::mozilla::layers::layerscope::TexturePacket* texture_;
::mozilla::layers::layerscope::LayersPacket* layers_;
::mozilla::layers::layerscope::MetaPacket* meta_;
int type_;
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
friend void protobuf_AddDesc_LayerScopePacket_2eproto();
friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
@ -2524,6 +2607,32 @@ LayersPacket::mutable_layer() {
// -------------------------------------------------------------------
// MetaPacket
// optional bool composedByHwc = 1;
inline bool MetaPacket::has_composedbyhwc() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void MetaPacket::set_has_composedbyhwc() {
_has_bits_[0] |= 0x00000001u;
}
inline void MetaPacket::clear_has_composedbyhwc() {
_has_bits_[0] &= ~0x00000001u;
}
inline void MetaPacket::clear_composedbyhwc() {
composedbyhwc_ = false;
clear_has_composedbyhwc();
}
inline bool MetaPacket::composedbyhwc() const {
return composedbyhwc_;
}
inline void MetaPacket::set_composedbyhwc(bool value) {
set_has_composedbyhwc();
composedbyhwc_ = value;
}
// -------------------------------------------------------------------
// Packet
// required .mozilla.layers.layerscope.Packet.DataType type = 1;
@ -2665,6 +2774,35 @@ inline ::mozilla::layers::layerscope::LayersPacket* Packet::release_layers() {
return temp;
}
// optional .mozilla.layers.layerscope.MetaPacket meta = 6;
inline bool Packet::has_meta() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
inline void Packet::set_has_meta() {
_has_bits_[0] |= 0x00000020u;
}
inline void Packet::clear_has_meta() {
_has_bits_[0] &= ~0x00000020u;
}
inline void Packet::clear_meta() {
if (meta_ != NULL) meta_->::mozilla::layers::layerscope::MetaPacket::Clear();
clear_has_meta();
}
inline const ::mozilla::layers::layerscope::MetaPacket& Packet::meta() const {
return meta_ != NULL ? *meta_ : *default_instance_->meta_;
}
inline ::mozilla::layers::layerscope::MetaPacket* Packet::mutable_meta() {
set_has_meta();
if (meta_ == NULL) meta_ = new ::mozilla::layers::layerscope::MetaPacket;
return meta_;
}
inline ::mozilla::layers::layerscope::MetaPacket* Packet::release_meta() {
clear_has_meta();
::mozilla::layers::layerscope::MetaPacket* temp = meta_;
meta_ = NULL;
return temp;
}
// @@protoc_insertion_point(namespace_scope)

View File

@ -1,3 +1,5 @@
/* vim:set ts=2 sw=2 sts=2 et: */
option optimize_for = LITE_RUNTIME;
package mozilla.layers.layerscope;
@ -108,6 +110,10 @@ message LayersPacket {
repeated Layer layer = 1;
}
message MetaPacket {
optional bool composedByHwc = 1;
}
// We only need to use this Packet.
// Other packet definitions are just type defines
message Packet {
@ -117,6 +123,7 @@ message Packet {
COLOR = 3;
TEXTURE = 4;
LAYERS = 5;
META = 6;
}
required DataType type = 1;
@ -124,4 +131,5 @@ message Packet {
optional ColorPacket color = 3;
optional TexturePacket texture = 4;
optional LayersPacket layers = 5;
optional MetaPacket meta = 6;
}

View File

@ -375,18 +375,19 @@ nsDeviceContext::SetDPI()
nsresult
nsDeviceContext::Init(nsIWidget *aWidget)
{
nsresult rv = NS_OK;
if (mScreenManager && mWidget == aWidget)
return NS_OK;
return rv;
mWidget = aWidget;
SetDPI();
if (mScreenManager)
return NS_OK;
return rv;
mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1", &rv);
return NS_OK;
return rv;
}
already_AddRefed<gfxContext>
@ -422,7 +423,7 @@ nsDeviceContext::CreateRenderingContext()
nsresult
nsDeviceContext::GetDepth(uint32_t& aDepth)
{
if (mDepth == 0) {
if (mDepth == 0 && mScreenManager) {
nsCOMPtr<nsIScreen> primaryScreen;
mScreenManager->GetPrimaryScreen(getter_AddRefs(primaryScreen));
primaryScreen->GetColorDepth(reinterpret_cast<int32_t *>(&mDepth));
@ -644,11 +645,15 @@ nsDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
void
nsDeviceContext::FindScreen(nsIScreen** outScreen)
{
if (mWidget && mWidget->GetOwningTabChild()) {
if (!mWidget || !mScreenManager) {
return;
}
if (mWidget->GetOwningTabChild()) {
mScreenManager->ScreenForNativeWidget((void *)mWidget->GetOwningTabChild(),
outScreen);
}
else if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW)) {
else if (mWidget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW),
outScreen);
}

View File

@ -327,6 +327,7 @@ NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter)
gfxWindowsPlatform::gfxWindowsPlatform()
: mD3D11DeviceInitialized(false)
, mIsWARP(false)
{
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
mUseClearTypeAlways = UNINITIALIZED_VALUE;
@ -1787,6 +1788,7 @@ gfxWindowsPlatform::InitD3D11Devices()
MOZ_CRASH();
}
mIsWARP = true;
reporterWARP.SetSuccessful();
}

View File

@ -250,6 +250,8 @@ public:
static bool IsOptimus();
bool IsWARP() { return mIsWARP; }
protected:
RenderMode mRenderMode;
@ -279,6 +281,7 @@ private:
mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
bool mD3D11DeviceInitialized;
mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
bool mIsWARP;
virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
};

View File

@ -66,7 +66,7 @@ LOCAL_INCLUDES += [
# Because VectorImage.cpp includes nsSVGUtils.h and nsSVGEffects.h
'/layout/svg',
# For URI-related functionality
'/netwerk/base/src',
'/netwerk/base',
]
# Because imgFrame.cpp includes "cairo.h"

View File

@ -20,8 +20,15 @@
#include "base/string16.h"
#if defined(COMPILER_MSVC) || (defined(ANDROID) && defined(_STLP_STD_NAME))
#ifdef COMPILER_MSVC
#pragma push_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
#endif
#include <hash_map>
#include <hash_set>
#ifdef COMPILER_MSVC
#pragma pop_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
#endif
namespace base {
#ifdef ANDROID
using _STLP_STD_NAME::hash_map;

View File

@ -197,7 +197,8 @@ class ScopedRunnableMethodFactory : public RevocableStore {
virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
private:
T* obj_;
T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
"external factors.") obj_;
Method meth_;
Params params_;
@ -225,7 +226,8 @@ class DeleteTask : public CancelableTask {
obj_ = NULL;
}
private:
T* obj_;
T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
"external factors.") obj_;
};
// Task to Release() an object
@ -242,7 +244,8 @@ class ReleaseTask : public CancelableTask {
obj_ = NULL;
}
private:
T* obj_;
T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
"external factors.") obj_;
};
// RunnableMethodTraits --------------------------------------------------------
@ -319,7 +322,9 @@ class RunnableMethod : public CancelableTask,
}
}
T* obj_;
// This is owning because of the RetainCallee and ReleaseCallee calls in the
// constructor and destructor.
T* MOZ_OWNING_REF obj_;
Method meth_;
Params params_;
};
@ -513,7 +518,8 @@ class CallbackStorage {
}
protected:
T* obj_;
T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
"external factors.") obj_;
Method meth_;
};

View File

@ -71,7 +71,7 @@ TestDataStructuresParent::DeallocPTestDataStructuresSubParent(PTestDataStructure
}
bool TestDataStructuresParent::RecvTest1(
const InfallibleTArray<int>& ia,
InfallibleTArray<int>&& ia,
InfallibleTArray<int>* oa)
{
test_assert(5 == ia.Length(), "wrong length");
@ -84,7 +84,7 @@ bool TestDataStructuresParent::RecvTest1(
}
bool TestDataStructuresParent::RecvTest2(
const InfallibleTArray<PTestDataStructuresSubParent*>& i1,
InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
InfallibleTArray<PTestDataStructuresSubParent*>* o1)
{
test_assert(nactors == i1.Length(), "wrong #actors");
@ -110,7 +110,7 @@ bool TestDataStructuresParent::RecvTest3(
}
bool TestDataStructuresParent::RecvTest4(
const InfallibleTArray<IntDouble>& i1,
InfallibleTArray<IntDouble>&& i1,
InfallibleTArray<IntDouble>* o1)
{
test_assert(4 == i1.Length(), "wrong length");
@ -171,7 +171,7 @@ TestDataStructuresParent::RecvTest7_0(const ActorWrapper& i1,
}
bool TestDataStructuresParent::RecvTest6(
const InfallibleTArray<IntDoubleArrays>& i1,
InfallibleTArray<IntDoubleArrays>&& i1,
InfallibleTArray<IntDoubleArrays>* o1)
{
test_assert(3 == i1.Length(), "wrong length");
@ -224,7 +224,7 @@ bool TestDataStructuresParent::RecvTest7(
}
bool TestDataStructuresParent::RecvTest8(
const InfallibleTArray<Actors>& i1,
InfallibleTArray<Actors>&& i1,
InfallibleTArray<Actors>* o1)
{
test_assert(3 == i1.Length(), "wrong length");
@ -276,7 +276,7 @@ bool TestDataStructuresParent::RecvTest9(
}
bool TestDataStructuresParent::RecvTest10(
const InfallibleTArray<Unions>& i1,
InfallibleTArray<Unions>&& i1,
InfallibleTArray<Unions>* o1)
{
test_assert(42 == i1[0].get_int(), "wrong value");
@ -438,14 +438,14 @@ bool TestDataStructuresParent::RecvTest16(
return true;
}
bool TestDataStructuresParent::RecvTest17(const InfallibleTArray<Op>& sa)
bool TestDataStructuresParent::RecvTest17(InfallibleTArray<Op>&& sa)
{
test_assert(sa.Length() == 1 && Op::TSetAttrs == sa[0].type(),
"wrong value");
return true;
}
bool TestDataStructuresParent::RecvTest18(const RegionArray& ra)
bool TestDataStructuresParent::RecvTest18(RegionArray&& ra)
{
for (RegionArray::index_type i = 0; i < ra.Length(); ++i) {
nsIntRegionRectIterator it(ra[i]);

View File

@ -58,11 +58,11 @@ protected:
virtual bool DeallocPTestDataStructuresSubParent(PTestDataStructuresSubParent* actor) MOZ_OVERRIDE;
virtual bool RecvTest1(
const InfallibleTArray<int>& i1,
InfallibleTArray<int>&& i1,
InfallibleTArray<int>* o1) MOZ_OVERRIDE;
virtual bool RecvTest2(
const InfallibleTArray<PTestDataStructuresSubParent*>& i1,
InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
InfallibleTArray<PTestDataStructuresSubParent*>* o1) MOZ_OVERRIDE;
virtual bool RecvTest3(
@ -72,7 +72,7 @@ protected:
IntDouble* o2) MOZ_OVERRIDE;
virtual bool RecvTest4(
const InfallibleTArray<IntDouble>& i1,
InfallibleTArray<IntDouble>&& i1,
InfallibleTArray<IntDouble>* o1) MOZ_OVERRIDE;
virtual bool RecvTest5(
@ -84,7 +84,7 @@ protected:
IntDoubleArrays* o3) MOZ_OVERRIDE;
virtual bool RecvTest6(
const InfallibleTArray<IntDoubleArrays>& i1,
InfallibleTArray<IntDoubleArrays>&& i1,
InfallibleTArray<IntDoubleArrays>* o1) MOZ_OVERRIDE;
@ -100,7 +100,7 @@ protected:
Actors* o3) MOZ_OVERRIDE;
virtual bool RecvTest8(
const InfallibleTArray<Actors>& i1,
InfallibleTArray<Actors>&& i1,
InfallibleTArray<Actors>* o1) MOZ_OVERRIDE;
virtual bool RecvTest9(
@ -114,7 +114,7 @@ protected:
Unions* o4) MOZ_OVERRIDE;
virtual bool RecvTest10(
const InfallibleTArray<Unions>& i1,
InfallibleTArray<Unions>&& i1,
InfallibleTArray<Unions>* o1) MOZ_OVERRIDE;
virtual bool RecvTest11(
@ -149,9 +149,9 @@ protected:
const WithUnions& i,
WithUnions* o) MOZ_OVERRIDE;
virtual bool RecvTest17(const InfallibleTArray<Op>& sa) MOZ_OVERRIDE;
virtual bool RecvTest17(InfallibleTArray<Op>&& sa) MOZ_OVERRIDE;
virtual bool RecvTest18(const InfallibleTArray<nsIntRegion>& ra) MOZ_OVERRIDE;
virtual bool RecvTest18(InfallibleTArray<nsIntRegion>&& ra) MOZ_OVERRIDE;
virtual bool RecvDummy(const ShmemUnion& su, ShmemUnion* rsu) MOZ_OVERRIDE
{

View File

@ -51,7 +51,7 @@ TestShmemParent::Main()
bool
TestShmemParent::RecvTake(Shmem& mem, Shmem& unsafe,
TestShmemParent::RecvTake(Shmem&& mem, Shmem&& unsafe,
const size_t& expectedSize)
{
if (mem.Size<char>() != expectedSize)
@ -80,7 +80,7 @@ TestShmemParent::RecvTake(Shmem& mem, Shmem& unsafe,
// Child
bool
TestShmemChild::RecvGive(Shmem& mem, Shmem& unsafe, const size_t& expectedSize)
TestShmemChild::RecvGive(Shmem&& mem, Shmem&& unsafe, const size_t& expectedSize)
{
if (mem.Size<char>() != expectedSize)
fail("expected shmem size %lu, but it has size %lu",

View File

@ -24,8 +24,8 @@ public:
protected:
virtual bool RecvTake(
Shmem& mem,
Shmem& unsafe,
Shmem&& mem,
Shmem&& unsafe,
const size_t& expectedSize) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
@ -47,8 +47,8 @@ public:
protected:
virtual bool RecvGive(
Shmem& mem,
Shmem& unsafe,
Shmem&& mem,
Shmem&& unsafe,
const size_t& expectedSize) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE

View File

@ -56,7 +56,7 @@ TestSysVShmemParent::Main()
bool
TestSysVShmemParent::RecvTake(Shmem& mem, Shmem& unsafe,
TestSysVShmemParent::RecvTake(Shmem&& mem, Shmem&& unsafe,
const size_t& expectedSize)
{
if (mem.Size<char>() != expectedSize)
@ -85,7 +85,7 @@ TestSysVShmemParent::RecvTake(Shmem& mem, Shmem& unsafe,
// Child
bool
TestSysVShmemChild::RecvGive(Shmem& mem, Shmem& unsafe, const size_t& expectedSize)
TestSysVShmemChild::RecvGive(Shmem&& mem, Shmem&& unsafe, const size_t& expectedSize)
{
if (mem.Size<char>() != expectedSize)
fail("expected shmem size %lu, but it has size %lu",

View File

@ -24,8 +24,8 @@ public:
protected:
virtual bool RecvTake(
Shmem& mem,
Shmem& unsafe,
Shmem&& mem,
Shmem&& unsafe,
const size_t& expectedSize) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
@ -47,8 +47,8 @@ public:
protected:
virtual bool RecvGive(
Shmem& mem,
Shmem& unsafe,
Shmem&& mem,
Shmem&& unsafe,
const size_t& expectedSize) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE

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