Merge m-c to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-09-11 15:35:49 +02:00
commit e393d7ab02
248 changed files with 4941 additions and 2363 deletions

3
.gitignore vendored
View File

@ -12,6 +12,9 @@ ID
# Vim swap files.
.*.sw[a-z]
# Emacs directory variable files.
**/.dir-locals.el
# User files that may appear at the root
/.mozconfig*
/mozconfig

View File

@ -11,6 +11,9 @@
^\.sw.$
.[^/]*\.sw.$
# Emacs directory variable files.
\.dir-locals\.el
# User files that may appear at the root
^\.mozconfig
^mozconfig*

View File

@ -11,3 +11,7 @@ function parseQueryString() {
}
document.title = parseQueryString();
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
var event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true});
document.dispatchEvent(event);

View File

@ -96,7 +96,7 @@ function shouldAllowRelink(acctName) {
let wrapper = {
iframe: null,
init: function (url=null) {
init: function (url, entryPoint) {
let weave = Cc["@mozilla.org/weave/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
@ -116,9 +116,11 @@ let wrapper = {
let iframe = document.getElementById("remote");
this.iframe = iframe;
iframe.addEventListener("load", this);
try {
iframe.src = url || fxAccounts.getAccountsSignUpURI();
if (entryPoint) {
url += (url.indexOf("?") >= 0 ? "&" : "?") + entryPoint;
}
iframe.src = url;
} catch (e) {
error("Couldn't init Firefox Account wrapper: " + e.message);
}
@ -288,6 +290,17 @@ function openPrefs() {
function init() {
fxAccounts.getSignedInUser().then(user => {
// If the url contains an entrypoint query parameter, extract it into a variable
// to append it to the accounts URI resource.
// Works for the following cases:
// - about:accounts?entrypoint="abouthome"
// - about:accounts?entrypoint=abouthome&action=signup
let entryPointQParam = "entrypoint=";
let entryPointPos = window.location.href.indexOf(entryPointQParam);
let entryPoint = "";
if (entryPointPos >= 0) {
entryPoint = window.location.href.substring(entryPointPos).split("&")[0];
}
// tests in particular might cause the window to start closing before
// getSignedInUser has returned.
if (window.closed) {
@ -299,7 +312,7 @@ function init() {
show("stage", "manage");
} else {
show("remote");
wrapper.init(fxAccounts.getAccountsSignInURI());
wrapper.init(fxAccounts.getAccountsSignInURI(), entryPoint);
}
} else if (window.location.href.contains("action=signup")) {
if (user) {
@ -307,7 +320,7 @@ function init() {
show("stage", "manage");
} else {
show("remote");
wrapper.init();
wrapper.init(fxAccounts.getAccountsSignUpURI(), entryPoint);
}
} else if (window.location.href.contains("action=reauth")) {
// ideally we would only show this when we know the user is in a
@ -316,7 +329,7 @@ function init() {
// promiseAccountsForceSigninURI, just always show it.
fxAccounts.promiseAccountsForceSigninURI().then(url => {
show("remote");
wrapper.init(url);
wrapper.init(url, entryPoint);
});
} else {
// No action specified
@ -327,7 +340,7 @@ function init() {
} else {
show("stage", "intro");
// load the remote frame in the background
wrapper.init();
wrapper.init(fxAccounts.getAccountsSignUpURI(), entryPoint);
}
}
});

View File

@ -224,10 +224,22 @@ let gFxAccounts = {
},
openAccountsPage: function () {
switchToTabHavingURI("about:accounts", true);
let entryPoint = "menupanel";
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
},
openSignInAgainPage: function () {
switchToTabHavingURI("about:accounts?action=reauth", true);
let entryPoint = "menupanel";
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?action=reauth&entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
}
};

View File

@ -476,7 +476,7 @@
label="&syncSetup.label;"
accesskey="&syncSetup.accesskey;"
observes="sync-setup-state"
oncommand="gSyncUI.openSetup()"/>
oncommand="gSyncUI.openSetup(null, 'menubar')"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
@ -486,7 +486,7 @@
label="&syncReAuthItem.label;"
accesskey="&syncReAuthItem.accesskey;"
observes="sync-reauth-state"
oncommand="gSyncUI.openSignInAgainPage();"/>
oncommand="gSyncUI.openSignInAgainPage('menubar');"/>
#endif
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"

View File

@ -314,9 +314,11 @@ let gSyncUI = {
* null -- regular set up wizard
* "pair" -- pair a device first
* "reset" -- reset sync
* @param entryPoint
* Indicates the entrypoint from where this method was called.
*/
openSetup: function SUI_openSetup(wizardType) {
openSetup: function SUI_openSetup(wizardType, entryPoint = "syncbutton") {
let xps = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
@ -325,7 +327,13 @@ let gSyncUI = {
if (userData) {
this.openPrefs();
} else {
switchToTabHavingURI("about:accounts", true);
// If the user is also in an uitour, set the entrypoint to `uitour`
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
}
});
} else {
@ -366,8 +374,14 @@ let gSyncUI = {
openPreferences("paneSync");
},
openSignInAgainPage: function () {
switchToTabHavingURI("about:accounts?action=reauth", true);
openSignInAgainPage: function (entryPoint = "syncbutton") {
// If the user is also in an uitour, set the entrypoint to `uitour`
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?action=reauth&entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
},
// Helpers

View File

@ -180,6 +180,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "TabCrashReporter",
XPCOMUtils.defineLazyModuleGetter(this, "FormValidationHandler",
"resource:///modules/FormValidationHandler.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
"resource:///modules/UITour.jsm");
let gInitialPages = [
"about:blank",
"about:newtab",
@ -1017,6 +1020,12 @@ var gBrowserInit = {
}
});
gBrowser.addEventListener("AboutTabCrashedLoad", function(event) {
#ifdef MOZ_CRASHREPORTER
TabCrashReporter.onAboutTabCrashedLoad(gBrowser.getBrowserForDocument(event.target));
#endif
}, false, true);
if (uriToLoad && uriToLoad != "about:blank") {
if (uriToLoad instanceof Ci.nsISupportsArray) {
let count = uriToLoad.Count();
@ -4044,11 +4053,6 @@ var TabsProgressListener = {
if (event.target.documentElement)
event.target.documentElement.removeAttribute("hasBrowserHandlers");
}, true);
#ifdef MOZ_CRASHREPORTER
if (doc.documentURI.startsWith("about:tabcrashed"))
TabCrashReporter.onAboutTabCrashedLoad(aBrowser);
#endif
}
},
@ -6916,9 +6920,13 @@ let gRemoteTabsUI = {
* If switching to this URI results in us opening a tab, aOpenParams
* will be the parameter object that gets passed to openUILinkIn. Please
* see the documentation for openUILinkIn to see what parameters can be
* passed via this object. This object also allows the 'ignoreFragment'
* property to be set to true to exclude fragment-portion matching when
* comparing URIs.
* passed via this object.
* This object also allows:
* - 'ignoreFragment' property to be set to true to exclude fragment-portion
* matching when comparing URIs.
* - 'replaceQueryString' property to be set to true to exclude query string
* matching when comparing URIs and ovewrite the initial query string with
* the one from the new URI.
* @return True if an existing tab was found, false otherwise
*/
function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
@ -6929,6 +6937,8 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
]);
let ignoreFragment = aOpenParams.ignoreFragment;
let replaceQueryString = aOpenParams.replaceQueryString;
// This property is only used by switchToTabHavingURI and should
// not be used as a parameter for the new load.
delete aOpenParams.ignoreFragment;
@ -6960,6 +6970,15 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
}
return true;
}
if (replaceQueryString) {
if (browser.currentURI.spec.split("?")[0] == aURI.spec.split("?")[0]) {
// Focus the matching window & tab
aWindow.focus();
aWindow.gBrowser.tabContainer.selectedIndex = i;
browser.loadURI(aURI.spec);
return true;
}
}
}
return false;
}

View File

@ -323,7 +323,7 @@ function onLoadPageInfo()
window.arguments[0];
if (!args || !args.doc) {
gWindow = window.opener.content;
gWindow = window.opener.gBrowser.selectedBrowser.contentWindowAsCPOW;
gDocument = gWindow.document;
}

View File

@ -189,6 +189,38 @@ let gTests = [
is(tab.linkedBrowser.contentDocument.location.href, "about:accounts?action=signin");
}
},
{
desc: "Test entrypoint query string, no action, no user logged in",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
setPref("identity.fxaccounts.remote.signup.uri", "https://example.com/");
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?entrypoint=abouthome");
is(url, "https://example.com/?entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
{
desc: "Test entrypoint query string for signin",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
const expected_url = "https://example.com/?is_sign_in";
setPref("identity.fxaccounts.remote.signin.uri", expected_url);
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?action=signin&entrypoint=abouthome");
is(url, expected_url + "&entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
{
desc: "Test entrypoint query string for signup",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
const sign_up_url = "https://example.com/?is_sign_up";
setPref("identity.fxaccounts.remote.signup.uri", sign_up_url);
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?entrypoint=abouthome&action=signup");
is(url, sign_up_url + "&entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
]; // gTests
function test()

View File

@ -454,6 +454,18 @@ let gTests = [
yield promiseWaitForCondition(() => doc.activeElement === searchInput);
is(searchInput, doc.activeElement, "Search bar should be the active element.");
})
},
{
desc: "Sync button should open about:accounts page with `abouthome` entrypoint",
setup: function () {},
run: Task.async(function* () {
let syncButton = gBrowser.selectedTab.linkedBrowser.contentDocument.getElementById("sync");
yield EventUtils.synthesizeMouseAtCenter(syncButton, {}, gBrowser.contentWindow);
yield promiseTabLoadEvent(gBrowser.selectedTab, null, "load");
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=abouthome",
"Entry point should be `abouthome`.");
})
}
];

View File

@ -15,21 +15,48 @@ add_task(function() {
gBrowser.selectedTab = tabRefAboutMozilla;
let numTabsAtStart = gBrowser.tabs.length;
switchTab("about:home#1", false, true);
switchTab("about:mozilla", false, true);
switchTab("about:home#2", true, true);
switchTab("about:home#1", false, false, true);
switchTab("about:mozilla", false, false, true);
switchTab("about:home#2", true, false, true);
is(tabRefAboutHome, gBrowser.selectedTab, "The same about:home tab should be switched to");
is(gBrowser.currentURI.ref, "2", "The ref should be updated to the new ref");
switchTab("about:mozilla", false, true);
switchTab("about:home#1", false, false);
switchTab("about:mozilla", false, false, true);
switchTab("about:home#1", false, false, false);
isnot(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should not be initial about:blank tab");
is(gBrowser.tabs.length, numTabsAtStart + 1, "Should have one new tab opened");
switchTab("about:about", true, false);
switchTab("about:about", true, false, false);
});
function switchTab(aURI, aIgnoreFragment, aShouldFindExistingTab) {
let tabFound = switchToTabHavingURI(aURI, true, {ignoreFragment: aIgnoreFragment});
// Test for replaceQueryString option.
add_task(function() {
registerCleanupFunction(function() {
while (gBrowser.tabs.length > 1)
gBrowser.removeCurrentTab();
});
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
yield promiseTabLoaded(tabRefAboutHome);
switchTab("about:home", false, false, false);
switchTab("about:home?hello=firefox", false, false, true);
switchTab("about:home?hello=firefoxos", false, false, false);
// Remove the last opened tab to test replaceQueryString option.
gBrowser.removeCurrentTab();
switchTab("about:home?hello=firefoxos", false, true, true);
is(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should be the initial about:home tab");
// Wait for the tab to load the new URI spec.
yield promiseTabLoaded(tabRefAboutHome);
is(gBrowser.currentURI.spec, "about:home?hello=firefoxos", "The spec should be updated to the new spec");
});
function switchTab(aURI, aIgnoreFragment, aReplaceQueryString, aShouldFindExistingTab) {
let tabFound = switchToTabHavingURI(aURI, true, {
ignoreFragment: aIgnoreFragment,
replaceQueryString: aReplaceQueryString
});
is(tabFound, aShouldFindExistingTab,
"Should switch to existing " + aURI + " tab if one existed, " +
(aIgnoreFragment ? "ignoring" : "including") + " fragment portion");
(aIgnoreFragment ? "ignoring" : "including") + " fragment portion, " +
(aReplaceQueryString ? "ignoring" : "replacing") + " query string.");
}

View File

@ -2,12 +2,16 @@
* 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/. */
// The test expects the about:accounts page to open in the current tab
"use strict";
XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
let initialLocation = gBrowser.currentURI.spec;
let newTab = null;
add_task(function() {
function openAboutAccountsFromMenuPanel(entryPoint) {
info("Check Sync button functionality");
Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "http://example.com/");
@ -17,14 +21,27 @@ add_task(function() {
// check the button's functionality
yield PanelUI.show();
if (entryPoint == "uitour") {
UITour.originTabs.set(window, new Set());
UITour.originTabs.get(window).add(gBrowser.selectedTab);
}
let syncButton = document.getElementById("sync-button");
ok(syncButton, "The Sync button was added to the Panel Menu");
let deferred = Promise.defer();
let handler = () => {
gBrowser.selectedTab.removeEventListener("load", handler, true);
deferred.resolve();
}
gBrowser.selectedTab.addEventListener("load", handler, true);
syncButton.click();
yield deferred.promise;
newTab = gBrowser.selectedTab;
yield promiseTabLoadEvent(newTab, "about:accounts");
is(gBrowser.currentURI.spec, "about:accounts", "Firefox Sync page opened");
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=" + entryPoint,
"Firefox Sync page opened with `menupanel` entrypoint");
ok(!isPanelUIOpen(), "The panel closed");
if(isPanelUIOpen()) {
@ -32,9 +49,9 @@ add_task(function() {
PanelUI.hide();
yield panelHidePromise;
}
});
}
add_task(function asyncCleanup() {
function asyncCleanup() {
Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
// reset the panel UI to the default state
yield resetCustomization();
@ -43,4 +60,11 @@ add_task(function asyncCleanup() {
// restore the tabs
gBrowser.addTab(initialLocation);
gBrowser.removeTab(newTab);
});
UITour.originTabs.delete(window);
}
add_task(() => openAboutAccountsFromMenuPanel("syncbutton"));
add_task(asyncCleanup);
// Test that uitour is in progress, the entrypoint is `uitour` and not `menupanel`
add_task(() => openAboutAccountsFromMenuPanel("uitour"));
add_task(asyncCleanup);

View File

@ -2263,6 +2263,22 @@ let E10SUINotification = {
if (!activationNoticeShown) {
this._showE10sActivatedNotice();
}
} else {
let e10sPromptShownCount = 0;
try {
e10sPromptShownCount = Services.prefs.getIntPref("browser.displayedE10SPrompt");
} catch(e) {}
if (!Services.appinfo.inSafeMode && e10sPromptShownCount < 5) {
Services.tm.mainThread.dispatch(() => {
try {
this._showE10SPrompt();
Services.prefs.setIntPref("browser.displayedE10SPrompt", e10sPromptShownCount + 1);
} catch (ex) {
Cu.reportError("Failed to show e10s prompt: " + ex);
}
}, Ci.nsIThread.DISPATCH_NORMAL);
}
}
},
@ -2287,8 +2303,48 @@ let E10SUINotification = {
nb.appendNotification(message, "e10s-activated-noticed",
null, nb.PRIORITY_WARNING_MEDIUM, buttons);
},
_showE10SPrompt: function BG__showE10SPrompt() {
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win)
return;
let browser = win.gBrowser.selectedBrowser;
let promptMessage = "Would you like to help us test multiprocess Nightly (e10s)? You can also enable e10s in Nightly preferences.";
let mainAction = {
label: "Enable and Restart",
accessKey: "E",
callback: function () {
Services.prefs.setBoolPref("browser.tabs.remote.autostart", true);
Services.prefs.setBoolPref("browser.enabledE10SFromPrompt", true);
// Restart the app
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
if (cancelQuit.data)
return; // somebody canceled our quit request
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
}
};
let secondaryActions = [
{
label: "No thanks",
accessKey: "N",
callback: function () {
Services.prefs.setIntPref("browser.displayedE10SPrompt", 5);
}
}
];
let options = {
popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
learnMoreURL: "https://wiki.mozilla.org/Electrolysis",
persistWhileVisible: true
};
win.PopupNotifications.show(browser, "enable_e10s", promptMessage, null, mainAction, secondaryActions, options);
},
};
#endif
var components = [BrowserGlue, ContentPermissionPrompt];

View File

@ -88,12 +88,52 @@ var gMainPane = {
setEventListener("chooseFolder", "command",
gMainPane.chooseFolder);
#ifdef E10S_TESTING_ONLY
setEventListener("e10sAutoStart", "command",
gMainPane.enableE10SChange);
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
e10sCheckbox.checked = e10sPref.value;
#endif
// Notify observers that the UI is now ready
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(window, "main-pane-loaded", null);
},
#ifdef E10S_TESTING_ONLY
enableE10SChange: function ()
{
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
const Cc = Components.classes, Ci = Components.interfaces;
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
let bundle = document.getElementById("bundlePreferences");
let msg = bundle.getFormattedString(e10sCheckbox.checked ?
"featureEnableRequiresRestart" : "featureDisableRequiresRestart",
[brandName]);
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
let shouldProceed = Services.prompt.confirm(window, title, msg)
if (shouldProceed) {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
shouldProceed = !cancelQuit.data;
if (shouldProceed) {
e10sPref.value = e10sCheckbox.checked;
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
}
}
// Revert the checkbox in case we didn't quit
e10sCheckbox.checked = e10sPref.value;
},
#endif
// HOME PAGE
/*

View File

@ -9,6 +9,12 @@
<preferences id="mainPreferences">
#ifdef E10S_TESTING_ONLY
<preference id="browser.tabs.remote.autostart"
name="browser.tabs.remote.autostart"
type="bool"/>
#endif
<!-- Startup -->
<preference id="browser.startup.page"
name="browser.startup.page"
@ -108,6 +114,11 @@
hidden="true">
<caption><label>&startup.label;</label></caption>
#ifdef E10S_TESTING_ONLY
<checkbox id="e10sAutoStart"
label="Enable E10S (multi-process)"/>
#endif
#ifdef HAVE_SHELL_SERVICE
<vbox id="defaultBrowserBox">
<hbox align="center">

View File

@ -4,7 +4,7 @@
# 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/.
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME', 'E10S_TESTING_ONLY'):
DEFINES[var] = CONFIG[var]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'cocoa'):

View File

@ -313,7 +313,9 @@ let gSyncPane = {
.wrappedJSObject;
if (service.fxAccountsEnabled) {
this.openContentInBrowser("about:accounts");
this.openContentInBrowser("about:accounts?entrypoint=preferences", {
replaceQueryString: true
});
} else {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win)
@ -326,7 +328,7 @@ let gSyncPane = {
}
},
openContentInBrowser: function(url) {
openContentInBrowser: function(url, options) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
// no window to use, so use _openLink to create a new one. We don't
@ -335,7 +337,7 @@ let gSyncPane = {
gSyncUtils._openLink(url);
return;
}
win.openUILinkIn(url, "tab");
win.switchToTabHavingURI(url, true, options);
},
@ -350,15 +352,21 @@ let gSyncPane = {
},
signUp: function() {
this.openContentInBrowser("about:accounts?action=signup");
this.openContentInBrowser("about:accounts?action=signup&entrypoint=preferences", {
replaceQueryString: true
});
},
signIn: function() {
this.openContentInBrowser("about:accounts?action=signin");
this.openContentInBrowser("about:accounts?action=signin&entrypoint=preferences", {
replaceQueryString: true
});
},
reSignIn: function() {
this.openContentInBrowser("about:accounts?action=reauth");
this.openContentInBrowser("about:accounts?action=reauth&entrypoint=preferences", {
replaceQueryString: true
});
},
manageFirefoxAccount: function() {

View File

@ -229,7 +229,9 @@ let gSyncPane = {
.wrappedJSObject;
if (service.fxAccountsEnabled) {
this.openContentInBrowser("about:accounts");
this.openContentInBrowser("about:accounts?entrypoint=preferences", {
replaceQueryString: true
});
} else {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win) {
@ -242,7 +244,7 @@ let gSyncPane = {
}
},
openContentInBrowser: function(url) {
openContentInBrowser: function(url, options) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
// no window to use, so use _openLink to create a new one. We don't
@ -251,21 +253,27 @@ let gSyncPane = {
gSyncUtils._openLink(url);
return;
}
win.switchToTabHavingURI(url, true);
win.switchToTabHavingURI(url, true, options);
// seeing as we are doing this in a tab we close the prefs dialog.
window.close();
},
signUp: function() {
this.openContentInBrowser("about:accounts?action=signup");
this.openContentInBrowser("about:accounts?action=signup&entrypoint=preferences", {
replaceQueryString: true
});
},
signIn: function() {
this.openContentInBrowser("about:accounts?action=signin");
this.openContentInBrowser("about:accounts?action=signin&entrypoint=preferences", {
replaceQueryString: true
});
},
reSignIn: function() {
this.openContentInBrowser("about:accounts?action=reauth");
this.openContentInBrowser("about:accounts?action=reauth&entrypoint=preferences", {
replaceQueryString: true
});
},
manageFirefoxAccount: function() {

View File

@ -31,6 +31,7 @@ MOZ_SERVICES_CRYPTO=1
MOZ_SERVICES_HEALTHREPORT=1
MOZ_SERVICES_METRICS=1
MOZ_SERVICES_SYNC=1
MOZ_SERVICES_CLOUDSYNC=1
MOZ_APP_VERSION=$FIREFOX_VERSION
MOZ_EXTENSIONS_DEFAULT=" gio"
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh

View File

@ -159,7 +159,7 @@ let AboutHome = {
if (userData) {
window.openPreferences("paneSync");
} else {
window.loadURI("about:accounts");
window.loadURI("about:accounts?entrypoint=abouthome");
}
});
} else {

View File

@ -424,7 +424,7 @@ this.UITour = {
// 'signup' is the only action that makes sense currently, so we don't
// accept arbitrary actions just to be safe...
// We want to replace the current tab.
contentDocument.location.href = "about:accounts?action=signup";
contentDocument.location.href = "about:accounts?action=signup&entrypoint=uitour";
break;
}
}

View File

@ -51,7 +51,7 @@ let tests = [
tabBrowser.removeEventListener("load", onload, true);
ise(tabBrowser.contentDocument.location.href,
"about:accounts?action=signup",
"about:accounts?action=signup&entrypoint=uitour",
"about:accounts should have replaced the tab");
// the iframe in about:accounts will still be loading, so we stop

View File

@ -383,3 +383,6 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

View File

@ -542,6 +542,9 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
% override chrome://browser/skin/toolbarbutton-dropmarker.png chrome://browser/skin/lion/toolbarbutton-dropmarker.png os=Darwin osversion>=10.7
% override chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png chrome://browser/skin/lion/tabbrowser/alltabs-box-bkgnd-icon.png os=Darwin osversion>=10.7

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -420,6 +420,9 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
#ifdef XP_WIN
browser.jar:
@ -841,6 +844,9 @@ browser.jar:
skin/classic/aero/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/aero/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/aero/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/aero/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6.1

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

View File

@ -2,7 +2,6 @@
# 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/.
NO_EXPAND_LIBS = 1
ENABLE_CLANG_PLUGIN :=
include $(topsrcdir)/config/rules.mk

View File

@ -667,7 +667,7 @@ EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
ifneq ($(OS_ARCH),Darwin)
CHECK_STDCXX = @$(TOOLCHAIN_PREFIX)objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_stdcxx | We do not want these libstdc++ symbols to be used:' && $(TOOLCHAIN_PREFIX)objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && false || true
CHECK_STDCXX = @$(TOOLCHAIN_PREFIX)objdump -p $(1) | grep -v -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null || ( echo 'TEST-UNEXPECTED-FAIL | check_stdcxx | We do not want these libstdc++ symbols to be used:' && $(TOOLCHAIN_PREFIX)objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && false)
endif
endif

View File

@ -104,6 +104,7 @@ class ExpandArgs(list):
'''Creates a clone of the |args| list and performs file expansion on
each item it contains'''
super(ExpandArgs, self).__init__()
self._descs = set()
for arg in args:
self += self._expand(arg)
@ -124,8 +125,12 @@ class ExpandArgs(list):
def _expand_desc(self, arg):
'''Internal function taking care of lib descriptor expansion only'''
if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
with open(arg + conf.LIBS_DESC_SUFFIX, 'r') as f:
desc = os.path.abspath(arg + conf.LIBS_DESC_SUFFIX)
if os.path.exists(desc):
if desc in self._descs:
return []
self._descs.add(desc)
with open(desc, 'r') as f:
desc = LibDescriptor(f.readlines())
objs = [relativize(o) for o in desc['OBJS']]
for lib in desc['LIBS']:

View File

@ -4154,7 +4154,6 @@ cairo-gtk3)
USE_FC_FREETYPE=1
TK_CFLAGS='$(MOZ_GTK3_CFLAGS)'
TK_LIBS='$(MOZ_GTK3_LIBS)'
MOZ_WIDGET_GTK=3
AC_DEFINE_UNQUOTED(MOZ_WIDGET_GTK,$MOZ_WIDGET_GTK)
MOZ_PDF_PRINTING=1
@ -4267,6 +4266,10 @@ if test "$COMPILE_ENVIRONMENT"; then
if test "$MOZ_ENABLE_GTK3"; then
PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
MOZ_GTK3_CFLAGS="-I${_topsrcdir}/widget/gtk/compat-gtk3 $MOZ_GTK3_CFLAGS"
dnl Contrary to MOZ_GTK2_LIBS, MOZ_GTK3_LIBS needs to be literally added to TK_LIBS instead
dnl of a make reference because of how TK_LIBS is mangled in toolkit/library/moz.build
dnl for GTK+3 builds.
TK_LIBS=$MOZ_GTK3_LIBS
fi
if test "$MOZ_ENABLE_GTK"; then
if test "$MOZ_X11"; then
@ -9116,6 +9119,11 @@ if test -n "$_WRAP_MALLOC"; then
_SUBDIR_CONFIG_ARGS="`echo $_SUBDIR_CONFIG_ARGS | sed -e 's/--enable-wrap-malloc *//'`"
fi
if test -n "$MOZ_USING_CCACHE"; then
# Avoid double prepending ccache by omitting --with-ccache in building NSPR.
_SUBDIR_CONFIG_ARGS="`echo $_SUBDIR_CONFIG_ARGS | sed -e 's/--with-ccache\S* *//'`"
fi
MOZ_SUBCONFIGURE_NSPR()
dnl ========================================================

View File

@ -202,7 +202,7 @@ private:
class MP4ContainerParser : public ContainerParser {
public:
MP4ContainerParser() : mTimescale(0) {}
MP4ContainerParser() {}
bool IsInitSegmentPresent(const uint8_t* aData, uint32_t aLength)
{
@ -234,15 +234,21 @@ public:
virtual bool ParseStartAndEndTimestamps(const uint8_t* aData, uint32_t aLength,
double& aStart, double& aEnd)
{
mp4_demuxer::MoofParser parser(new mp4_demuxer::BufferStream(aData, aLength), 0);
parser.mMdhd.mTimescale = mTimescale;
bool initSegment = IsInitSegmentPresent(aData, aLength);
if (initSegment) {
mStream = new mp4_demuxer::BufferStream();
mParser = new mp4_demuxer::MoofParser(mStream, 0);
} else if (!mStream || !mParser) {
return false;
}
mStream->AppendBytes(aData, aLength);
nsTArray<MediaByteRange> byteRanges;
byteRanges.AppendElement(MediaByteRange(0, aLength));
parser.RebuildFragmentedIndex(byteRanges);
byteRanges.AppendElement(mStream->GetByteRange());
mParser->RebuildFragmentedIndex(byteRanges);
if (IsInitSegmentPresent(aData, aLength)) {
const MediaByteRange& range = parser.mInitRange;
if (initSegment) {
const MediaByteRange& range = mParser->mInitRange;
MSE_DEBUG("MP4ContainerParser(%p)::ParseStartAndEndTimestamps: Stashed init of %u bytes.",
this, range.mEnd - range.mStart);
@ -251,11 +257,10 @@ public:
range.mEnd - range.mStart);
}
// Persist the timescale for when it is absent in later chunks
mTimescale = parser.mMdhd.mTimescale;
mp4_demuxer::Interval<mp4_demuxer::Microseconds> compositionRange =
parser.GetCompositionRange();
mParser->GetCompositionRange(byteRanges);
mStream->DiscardBefore(mParser->mOffset);
if (compositionRange.IsNull()) {
return false;
@ -268,7 +273,8 @@ public:
}
private:
uint32_t mTimescale;
nsRefPtr<mp4_demuxer::BufferStream> mStream;
nsAutoPtr<mp4_demuxer::MoofParser> mParser;
};

View File

@ -307,9 +307,9 @@ MediaEngineTabVideoSource::Draw() {
return;
}
nsRefPtr<gfxContext> context = new gfxContext(dt);
gfxPoint pt(0, 0);
context->Translate(pt);
context->Scale(scale * size.width / srcW, scale * size.height / srcH);
context->SetMatrix(
context->CurrentMatrix().Scale(scale * size.width / srcW,
scale * size.height / srcH));
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS_VOID(rv);

View File

@ -91,7 +91,9 @@
#include "nsSHistory.h"
#include "nsDocShellEditorData.h"
#include "GeckoProfiler.h"
#ifdef MOZ_ENABLE_PROFILER_SPS
#include "ProfilerMarkers.h"
#endif
// Helper Classes
#include "nsError.h"
@ -2800,6 +2802,7 @@ unsigned long nsDocShell::gProfileTimelineRecordingsCount = 0;
NS_IMETHODIMP
nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
bool currentValue;
GetRecordProfileTimelineMarkers(&currentValue);
if (currentValue != aValue) {
@ -2814,6 +2817,9 @@ nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
}
return NS_OK;
#else
return NS_ERROR_FAILURE;
#endif
}
NS_IMETHODIMP
@ -2827,6 +2833,7 @@ nsresult
nsDocShell::PopProfileTimelineMarkers(JSContext* aCx,
JS::MutableHandle<JS::Value> aProfileTimelineMarkers)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
// Looping over all markers gathered so far at the docShell level, whenever a
// START marker is found, look for the corresponding END marker and build a
// {name,start,end} JS object.
@ -2881,6 +2888,9 @@ nsDocShell::PopProfileTimelineMarkers(JSContext* aCx,
ClearProfileTimelineMarkers();
return NS_OK;
#else
return NS_ERROR_FAILURE;
#endif
}
float
@ -2893,6 +2903,7 @@ void
nsDocShell::AddProfileTimelineMarker(const char* aName,
TracingMetadata aMetaData)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
if (!mProfileTimelineStartTime.IsNull()) {
float delta = GetProfileTimelineDelta();
ProfilerMarkerTracing* payload = new ProfilerMarkerTracing("Timeline",
@ -2900,6 +2911,7 @@ nsDocShell::AddProfileTimelineMarker(const char* aName,
mProfileTimelineMarkers.AppendElement(
new InternalProfileTimelineMarker(aName, payload, delta));
}
#endif
}
void
@ -2907,6 +2919,7 @@ nsDocShell::AddProfileTimelineMarker(const char* aName,
ProfilerBacktrace* aCause,
TracingMetadata aMetaData)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
if (!mProfileTimelineStartTime.IsNull()) {
float delta = GetProfileTimelineDelta();
ProfilerMarkerTracing* payload = new ProfilerMarkerTracing("Timeline",
@ -2915,16 +2928,19 @@ nsDocShell::AddProfileTimelineMarker(const char* aName,
mProfileTimelineMarkers.AppendElement(
new InternalProfileTimelineMarker(aName, payload, delta));
}
#endif
}
void
nsDocShell::ClearProfileTimelineMarkers()
{
#ifdef MOZ_ENABLE_PROFILER_SPS
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
delete mProfileTimelineMarkers[i]->mPayload;
mProfileTimelineMarkers[i]->mPayload = nullptr;
}
mProfileTimelineMarkers.Clear();
#endif
}
nsIDOMStorageManager*

View File

@ -642,6 +642,12 @@ public:
JS::Handle<jsid> id, JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
virtual bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id) const MOZ_OVERRIDE;
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE {
return false;
}
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE {
return false;
}
// Derived traps
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
@ -694,8 +700,6 @@ const js::Class OuterWindowProxyClass =
"Proxy",
0, /* additional slots */
0, /* additional class flags */
nullptr, /* call */
nullptr, /* construct */
PROXY_MAKE_EXT(
nullptr, /* outerObject */
js::proxy_innerObject,
@ -1055,7 +1059,7 @@ NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> parent, bool isChrome)
JSObject *obj = js::Wrapper::New(cx, parent, parent,
isChrome ? &nsChromeOuterWindowProxy::singleton
: &nsOuterWindowProxy::singleton,
&options);
options);
NS_ASSERTION(js::GetObjectClass(obj)->ext.innerObject, "bad class");
return obj;

View File

@ -481,21 +481,17 @@ class CGDOMProxyJSClass(CGThing):
# HTMLAllCollection. So just hardcode it here.
if self.descriptor.interface.identifier.name == "HTMLAllCollection":
flags.append("JSCLASS_EMULATES_UNDEFINED")
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
return fill(
"""
static const DOMJSClass Class = {
PROXY_CLASS_DEF("${name}",
0, /* extra slots */
${flags},
${call}, /* call */
nullptr /* construct */),
${flags}),
$*{descriptor}
};
""",
name=self.descriptor.interface.identifier.name,
flags=" | ".join(flags),
call=callHook,
descriptor=DOMClass(self.descriptor))
@ -10641,6 +10637,33 @@ class CGDOMJSProxyHandler_getInstance(ClassMethod):
""")
class CGDOMJSProxyHandler_call(ClassMethod):
def __init__(self):
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('const JS::CallArgs&', 'args')]
ClassMethod.__init__(self, "call", "bool", args, virtual=True, override=True, const=True)
def getBody(self):
return fill(
"""
return js::ForwardToNative(cx, ${legacyCaller}, args);
""",
legacyCaller=LEGACYCALLER_HOOK_NAME)
class CGDOMJSProxyHandler_isCallable(ClassMethod):
def __init__(self):
ClassMethod.__init__(self, "isCallable", "bool", [Argument('JSObject*', 'obj')],
virtual=True, override=True, const=True)
def getBody(self):
return dedent("""
return true;
""")
class CGDOMJSProxyHandler(CGClass):
def __init__(self, descriptor):
assert (descriptor.supportsIndexedProperties() or
@ -10672,6 +10695,9 @@ class CGDOMJSProxyHandler(CGClass):
(descriptor.operations['NamedSetter'] is not None and
descriptor.interface.getExtendedAttribute('OverrideBuiltins'))):
methods.append(CGDOMJSProxyHandler_setCustom(descriptor))
if descriptor.operations['LegacyCaller']:
methods.append(CGDOMJSProxyHandler_call())
methods.append(CGDOMJSProxyHandler_isCallable())
CGClass.__init__(self, 'DOMProxyHandler',
bases=[ClassBase('mozilla::dom::DOMProxyHandler')],

View File

@ -991,9 +991,10 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
if (!mTarget) {
mTarget = layerManager->CreateDrawTarget(size, format);
}
} else
} else {
mTarget = layerManager->CreateDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode;
}
} else {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode;
@ -3519,9 +3520,10 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
src.Scale(scale.width, scale.height);
nsRefPtr<gfxContext> context = new gfxContext(tempTarget);
context->SetMatrix(contextMatrix);
context->Scale(1.0 / contextScale.width, 1.0 / contextScale.height);
context->Translate(gfxPoint(dest.x - src.x, dest.y - src.y));
context->SetMatrix(contextMatrix.
Scale(1.0 / contextScale.width,
1.0 / contextScale.height).
Translate(dest.x - src.x, dest.y - src.y));
// FLAG_CLAMP is added for increased performance, since we never tile here.
uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
@ -3723,7 +3725,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
}
thebes = new gfxContext(drawDT);
thebes->Scale(matrix._11, matrix._22);
thebes->SetMatrix(gfxMatrix::Scaling(matrix._11, matrix._22));
}
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();

View File

@ -43,6 +43,7 @@
#if defined(XP_WIN)
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxTarget.h"
#include "nsDirectoryServiceDefs.h"
#elif defined(XP_LINUX)
#include "mozilla/Sandbox.h"
#endif
@ -923,6 +924,69 @@ ContentChild::AllocPBackgroundChild(Transport* aTransport,
return BackgroundChild::Alloc(aTransport, aOtherProcess);
}
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
static void
SetUpSandboxEnvironment()
{
// Set up a low integrity temp directory. This only makes sense if the
// delayed integrity level for the content process is INTEGRITY_LEVEL_LOW.
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIFile> lowIntegrityTemp;
rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Undefine returns a failure if the property is not already set.
unused << directoryService->Undefine(NS_OS_TEMP_DIR);
rv = directoryService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Set TEMP and TMP environment variables.
nsAutoString lowIntegrityTempPath;
rv = lowIntegrityTemp->GetPath(lowIntegrityTempPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool setOK = SetEnvironmentVariableW(L"TEMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TEMP to low integrity temp path");
setOK = SetEnvironmentVariableW(L"TMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TMP to low integrity temp path");
}
void
ContentChild::CleanUpSandboxEnvironment()
{
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIFile> lowIntegrityTemp;
rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Don't check the return value as the directory will only have been created
// if it has been used.
unused << lowIntegrityTemp->Remove(/* aRecursive */ true);
}
#endif
bool
ContentChild::RecvSetProcessSandbox()
{
@ -947,6 +1011,7 @@ ContentChild::RecvSetProcessSandbox()
if (contentSandboxPref.EqualsLiteral("on")
|| contentSandboxPref.EqualsLiteral("warn")) {
mozilla::SandboxTarget::Instance()->StartSandbox();
SetUpSandboxEnvironment();
}
#endif
#endif

View File

@ -118,6 +118,11 @@ public:
AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
// Cleans up any resources used by the process when sandboxed.
void CleanUpSandboxEnvironment();
#endif
virtual bool RecvSetProcessSandbox() MOZ_OVERRIDE;
PBackgroundChild*

View File

@ -34,6 +34,9 @@ ContentProcess::Init()
void
ContentProcess::CleanUp()
{
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
mContent.CleanUpSandboxEnvironment();
#endif
mXREEmbed.Stop();
}

View File

@ -2172,7 +2172,8 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
// Renderer::Draw() draws a rectangle with top-left at the aContext origin.
gfxContextAutoSaveRestore autoSR(aContext);
aContext->Translate(pluginRect.TopLeft());
aContext->SetMatrix(
aContext->CurrentMatrix().Translate(pluginRect.TopLeft()));
Renderer renderer(window, this, pluginSize, pluginDirtyRect);

View File

@ -960,7 +960,7 @@ public:
*/
virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType) = 0;
const Matrix &GetTransform() const { return mTransform; }
Matrix GetTransform() const { return mTransform; }
/**
* Set a transform on the surface, this transform is applied at drawing time

View File

@ -62,7 +62,7 @@ Matrix::TransformBounds(const Rect &aRect) const
return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
}
void
Matrix&
Matrix::NudgeToIntegers()
{
NudgeToInteger(&_11);
@ -71,6 +71,7 @@ Matrix::NudgeToIntegers()
NudgeToInteger(&_22);
NudgeToInteger(&_31);
NudgeToInteger(&_32);
return *this;
}
Rect

View File

@ -211,6 +211,15 @@ public:
return *this;
}
/**
* Multiplies in the opposite order to operator=*.
*/
Matrix &PreMultiply(const Matrix &aMatrix)
{
*this = aMatrix * *this;
return *this;
}
/* Returns true if the other matrix is fuzzy-equal to this matrix.
* Note that this isn't a cheap comparison!
*/
@ -291,7 +300,7 @@ public:
return Determinant() == 0;
}
GFX2D_API void NudgeToIntegers();
GFX2D_API Matrix &NudgeToIntegers();
bool IsTranslation() const
{
@ -729,7 +738,7 @@ public:
return (__33 * det) < 0;
}
void NudgeToIntegersFixedEpsilon()
Matrix4x4 &NudgeToIntegersFixedEpsilon()
{
static const float error = 1e-5f;
NudgeToInteger(&_11, error);
@ -748,6 +757,7 @@ public:
NudgeToInteger(&_42, error);
NudgeToInteger(&_43, error);
NudgeToInteger(&_44, error);
return *this;
}
Point4D TransposedVector(int aIndex) const

View File

@ -1280,7 +1280,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
// Make a local copy of the tree manager pointer and check that it's not
// null before calling DispatchFling(). This is necessary because Destroy(),
// which nulls out mTreeManager, could be called concurrently.
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
treeManagerLocal->DispatchFling(this,
flingVelocity,
CurrentTouchBlock()->GetOverscrollHandoffChain(),
@ -1452,8 +1452,7 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
bool
AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut)
{
APZCTreeManager* treeManagerLocal = mTreeManager;
if (treeManagerLocal) {
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
Matrix4x4 transformToGecko = treeManagerLocal->GetApzcToGeckoTransform(this);
Point result = transformToGecko * Point(aPoint.x, aPoint.y);
// NOTE: This isn't *quite* LayoutDevicePoint, we just don't have a name
@ -1709,7 +1708,7 @@ static void TransformVector(const Matrix4x4& aTransform,
void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const {
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this);
transform.Invert();
TransformVector(transform, aVector, aAnchor);
@ -1718,7 +1717,7 @@ void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector,
void AsyncPanZoomController::ToLocalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const {
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this);
TransformVector(transform, aVector, aAnchor);
}
@ -1964,16 +1963,16 @@ bool AsyncPanZoomController::OverscrollBy(const CSSPoint& aOverscroll) {
}
nsRefPtr<const OverscrollHandoffChain> AsyncPanZoomController::BuildOverscrollHandoffChain() {
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
return treeManagerLocal->BuildOverscrollHandoffChain(this);
} else {
}
// This APZC IsDestroyed(). To avoid callers having to special-case this
// scenario, just build a 1-element chain containing ourselves.
OverscrollHandoffChain* result = new OverscrollHandoffChain;
result->Add(this);
return result;
}
}
void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity,
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
@ -2007,7 +2006,7 @@ bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity,
void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity,
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain) {
APZCTreeManager* treeManagerLocal = mTreeManager;
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this,
aVelocity,
aOverscrollHandoffChain,
@ -2056,7 +2055,7 @@ bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint,
// Make a local copy of the tree manager pointer and check if it's not
// null before calling DispatchScroll(). This is necessary because
// Destroy(), which nulls out mTreeManager, could be called concurrently.
APZCTreeManager* treeManagerLocal = mTreeManager;
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
return treeManagerLocal
&& treeManagerLocal->DispatchScroll(this, aStartPoint, aEndPoint,
aOverscrollHandoffChain,
@ -2725,6 +2724,11 @@ const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() const {
return mFrameMetrics;
}
APZCTreeManager* AsyncPanZoomController::GetApzcTreeManager() const {
mMonitor.AssertNotCurrentThreadIn();
return mTreeManager;
}
void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
if (!aRect.IsFinite()) {
NS_WARNING("ZoomToRect got called with a non-finite rect; ignoring...\n");

View File

@ -572,6 +572,13 @@ protected:
*/
const FrameMetrics& GetFrameMetrics() const;
/**
* Gets the pointer to the apzc tree manager. All the access to tree manager
* should be made via this method and not via private variable since this method
* ensures that no lock is set.
*/
APZCTreeManager* GetApzcTreeManager() const;
/**
* Timeout function for mozbrowserasyncscroll event. Because we throttle
* mozbrowserasyncscroll events in some conditions, this function ensures

View File

@ -69,7 +69,7 @@ ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
deviceRect.RoundOut();
gfxMatrix currentMatrix = aContext->CurrentMatrix();
aContext->IdentityMatrix();
aContext->SetMatrix(gfxMatrix());
aContext->NewPath();
aContext->Rectangle(deviceRect);
aContext->Clip();

View File

@ -209,7 +209,7 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
if (ctx) {
NS_ASSERTION(GetEffectiveOpacity() == 1.0, "Should only read back opaque layers");
NS_ASSERTION(!GetMaskLayer(), "Should only read back layers without masks");
ctx->Translate(gfxPoint(offset.x, offset.y));
ctx->SetMatrix(ctx->CurrentMatrix().Translate(offset.x, offset.y));
mContentClient->DrawTo(this, ctx->GetDrawTarget(), 1.0,
CompositionOpForOp(ctx->CurrentOperator()),
nullptr, nullptr);

View File

@ -163,8 +163,9 @@ SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile,
// do the drawing
RefPtr<gfxContext> ctxt = new gfxContext(drawTarget);
ctxt->Scale(mResolution, mResolution);
ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
ctxt->SetMatrix(
ctxt->CurrentMatrix().Scale(mResolution, mResolution).
Translate(-aTileOrigin.x, -aTileOrigin.y));
mCallback(mThebesLayer, ctxt,
drawRegion,

View File

@ -929,8 +929,9 @@ ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
}
ctxt->NewPath();
ctxt->Scale(mResolution, mResolution);
ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
ctxt->SetMatrix(
ctxt->CurrentMatrix().Scale(mResolution, mResolution).
Translate(-bounds.x, -bounds.y));
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 3) {
printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
@ -1300,8 +1301,10 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
ctxt->NewPath();
ctxt->Clip(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
ctxt->Translate(gfxPoint(-unscaledTileOrigin.x, -unscaledTileOrigin.y));
ctxt->Scale(mResolution, mResolution);
ctxt->SetMatrix(
ctxt->CurrentMatrix().Translate(-unscaledTileOrigin.x,
-unscaledTileOrigin.y).
Scale(mResolution, mResolution));
mCallback(mThebesLayer, ctxt,
tileRegion.GetBounds(),
DrawRegionClip::CLIP_NONE,

View File

@ -36,7 +36,9 @@
#include "TextRenderer.h" // for TextRenderer
#include <vector>
#include "GeckoProfiler.h" // for GeckoProfiler
#ifdef MOZ_ENABLE_PROFILER_SPS
#include "ProfilerMarkers.h" // for ProfilerMarkers
#endif
#define CULLING_LOG(...)
// #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
@ -117,6 +119,7 @@ static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
static void PrintUniformityInfo(Layer* aLayer)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
if (!profiler_is_active()) {
return;
}
@ -135,6 +138,7 @@ static void PrintUniformityInfo(Layer* aLayer)
Point translation = transform.As2D().GetTranslation();
LayerTranslationPayload* payload = new LayerTranslationPayload(aLayer, translation);
PROFILER_MARKER_PAYLOAD("LayerTranslation", payload);
#endif
}
/* all of the per-layer prepared data we need to maintain */

View File

@ -80,7 +80,8 @@ public:
update->mSequenceCounter);
if (ctx) {
ctx->Translate(gfxPoint(offset.x, offset.y));
ctx->SetMatrix(
ctx->CurrentMatrix().Translate(offset.x, offset.y));
ctx->SetSource(sourceSurface, gfxPoint(mTask->mOrigin.x,
mTask->mOrigin.y));
ctx->Paint();

View File

@ -396,7 +396,8 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
nsRefPtr<gfxContext> context = new gfxContext(mDrawTarget);
context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
context->SetMatrix(
context->CurrentMatrix().Translate(-visibleRect.x, -visibleRect.y));
if (aMode == SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA) {
nsIntRegionRectIterator iter(aRegion);
const nsIntRect *iterRect;

View File

@ -535,7 +535,7 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
nsRefPtr<gfxContext> context = new gfxContext(dt);
context->Translate(gfxPoint(-bounds.x, -bounds.y));
context->SetMatrix(context->CurrentMatrix().Translate(-bounds.x, -bounds.y));
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
cbInfo.Callback(this, context, aRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), cbInfo.CallbackData);
@ -548,7 +548,7 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
update.mSequenceCounter);
if (ctx) {
ctx->Translate(gfxPoint(offset.x, offset.y));
ctx->SetMatrix(ctx->CurrentMatrix().Translate(offset.x, offset.y));
ctx->SetSource(destinationSurface, gfxPoint(bounds.x, bounds.y));
ctx->Paint();
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);

View File

@ -405,7 +405,8 @@ nsDeviceContext::CreateRenderingContext()
pContext->Init(this, dt);
pContext->ThebesContext()->SetFlag(gfxContext::FLAG_DISABLE_SNAPPING);
pContext->Scale(mPrintingScale, mPrintingScale);
pContext->ThebesContext()->SetMatrix(gfxMatrix::Scaling(mPrintingScale,
mPrintingScale));
return pContext.forget();
}

View File

@ -85,18 +85,6 @@ nsRenderingContext::Init(nsDeviceContext* aContext,
// graphics state
//
void
nsRenderingContext::PushState()
{
mThebes->Save();
}
void
nsRenderingContext::PopState()
{
mThebes->Restore();
}
void
nsRenderingContext::IntersectClip(const nsRect& aRect)
{
@ -124,7 +112,7 @@ nsRenderingContext::SetClip(const nsIntRegion& aRegion)
// an existing clip.
gfxMatrix mat = mThebes->CurrentMatrix();
mThebes->IdentityMatrix();
mThebes->SetMatrix(gfxMatrix());
mThebes->ResetClip();
@ -170,18 +158,6 @@ nsRenderingContext::SetColor(nscolor aColor)
mThebes->SetColor(gfxRGBA(aColor));
}
void
nsRenderingContext::Translate(const nsPoint& aPt)
{
mThebes->Translate(gfxPoint(FROM_TWIPS(aPt.x), FROM_TWIPS(aPt.y)));
}
void
nsRenderingContext::Scale(float aSx, float aSy)
{
mThebes->Scale(aSx, aSy);
}
//
// shapes
//
@ -209,7 +185,7 @@ nsRenderingContext::DrawLine(nscoord aX0, nscoord aY0,
p0.Round();
p1.Round();
mThebes->IdentityMatrix();
mThebes->SetMatrix(gfxMatrix());
mThebes->NewPath();
@ -332,7 +308,7 @@ nsRenderingContext::FillRect(const nsRect& aRect)
if (!ConditionRect(r))
return;
mThebes->IdentityMatrix();
mThebes->SetMatrix(gfxMatrix());
mThebes->NewPath();
mThebes->Rectangle(r, true);

View File

@ -51,27 +51,10 @@ public:
// Graphics state
void PushState(void);
void PopState(void);
void IntersectClip(const nsRect& aRect);
void SetClip(const nsIntRegion& aRegion);
void SetLineStyle(nsLineStyle aLineStyle);
void SetColor(nscolor aColor);
void Translate(const nsPoint& aPt);
void Scale(float aSx, float aSy);
class AutoPushTranslation {
nsRenderingContext* mCtx;
public:
AutoPushTranslation(nsRenderingContext* aCtx, const nsPoint& aPt)
: mCtx(aCtx) {
mCtx->PushState();
mCtx->Translate(aPt);
}
~AutoPushTranslation() {
mCtx->PopState();
}
};
// Shapes

View File

@ -75,7 +75,7 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect,
gfxPoint topleft(irect.TopLeft().x, irect.TopLeft().y);
mContext = new gfxContext(dt);
mContext->Translate(-topleft);
mContext->SetMatrix(gfxMatrix::Translation(-topleft));
return mContext;
}

View File

@ -430,67 +430,24 @@ gfxContext::DrawSurface(gfxASurface *surface, const gfxSize& size)
}
// transform stuff
void
gfxContext::Translate(const gfxPoint& pt)
{
Matrix newMatrix = mTransform;
ChangeTransform(newMatrix.PreTranslate(Float(pt.x), Float(pt.y)));
}
void
gfxContext::Scale(gfxFloat x, gfxFloat y)
{
Matrix newMatrix = mTransform;
ChangeTransform(newMatrix.PreScale(Float(x), Float(y)));
}
void
gfxContext::Rotate(gfxFloat angle)
{
Matrix rotation = Matrix::Rotation(Float(angle));
ChangeTransform(rotation * mTransform);
}
void
gfxContext::Multiply(const gfxMatrix& matrix)
{
ChangeTransform(ToMatrix(matrix) * mTransform);
}
void
gfxContext::MultiplyAndNudgeToIntegers(const gfxMatrix& matrix)
{
Matrix transform = ToMatrix(matrix) * mTransform;
transform.NudgeToIntegers();
ChangeTransform(transform);
}
void
gfxContext::SetMatrix(const gfxMatrix& matrix)
{
ChangeTransform(ToMatrix(matrix));
}
void
gfxContext::IdentityMatrix()
{
ChangeTransform(Matrix());
}
gfxMatrix
gfxContext::CurrentMatrix() const
{
return ThebesMatrix(mTransform);
}
void
gfxContext::NudgeCurrentMatrixToIntegers()
{
gfxMatrix matrix = ThebesMatrix(mTransform);
matrix.NudgeToIntegers();
ChangeTransform(ToMatrix(matrix));
}
gfxPoint
gfxContext::DeviceToUser(const gfxPoint& point) const
{
@ -1093,7 +1050,7 @@ static gfxRect
GetRoundOutDeviceClipExtents(gfxContext* aCtx)
{
gfxContextMatrixAutoSaveRestore save(aCtx);
aCtx->IdentityMatrix();
aCtx->SetMatrix(gfxMatrix());
gfxRect r = aCtx->GetClipExtents();
r.RoundOut();
return r;

View File

@ -239,61 +239,23 @@ public:
** Transformation Matrix manipulation
**/
/**
* Adds a translation to the current matrix. This translation takes place
* before the previously set transformations.
*/
void Translate(const gfxPoint& pt);
/**
* Adds a scale to the current matrix. This scaling takes place before the
* previously set transformations.
*/
void Scale(gfxFloat x, gfxFloat y);
/**
* Adds a rotation around the origin to the current matrix. This rotation
* takes place before the previously set transformations.
*
* @param angle The angle in radians.
*/
void Rotate(gfxFloat angle);
/**
* Post-multiplies 'other' onto the current CTM, i.e. this
* matrix's transformation will take place before the previously set
* transformations.
*/
void Multiply(const gfxMatrix& other);
/**
* As "Multiply", but also nudges any entries in the resulting matrix that
* are close to an integer to that integer, to correct for
* compounded rounding errors.
*/
void MultiplyAndNudgeToIntegers(const gfxMatrix& other);
/**
* Replaces the current transformation matrix with matrix.
*/
void SetMatrix(const gfxMatrix& matrix);
/**
* Sets the transformation matrix to the identity matrix.
*/
void IdentityMatrix();
/**
* Returns the current transformation matrix.
*/
gfxMatrix CurrentMatrix() const;
/**
* Snap components of the current matrix that are close to integers
* to integers. In particular, components that are integral when
* converted to single precision are set to those integers.
*/
void NudgeCurrentMatrixToIntegers();
/**
* Converts a point from device to user coordinates using the inverse
* transformation matrix.

View File

@ -3577,8 +3577,9 @@ gfxFont::RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint, DrawMode aDrawMod
GetAdjustedSize() / GetFontEntry()->UnitsPerEm();
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
aContext->Translate(gfxPoint(aPoint.x, aPoint.y));
aContext->Scale(devUnitsPerSVGUnit, devUnitsPerSVGUnit);
aContext->SetMatrix(
aContext->CurrentMatrix().Translate(aPoint.x, aPoint.y).
Scale(devUnitsPerSVGUnit, devUnitsPerSVGUnit));
aContextPaint->InitStrokeGeometry(aContext, devUnitsPerSVGUnit);
@ -4361,7 +4362,7 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, bool aNeedTi
gfxGlyphExtents *aExtents)
{
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
aContext->IdentityMatrix();
aContext->SetMatrix(gfxMatrix());
gfxRect svgBounds;
if (mFontEntry->TryGetSVGData(this) && mFontEntry->HasSVGGlyph(aGlyphID) &&

View File

@ -214,13 +214,13 @@ gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext *aContext,
gfxFloat halfGap = HEX_CHAR_GAP / 2.0;
gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
aContext->SetDeviceColor(currentColor);
aContext->Translate(center);
// We always want integer scaling, otherwise the "bitmap" glyphs will look
// even uglier than usual when zoomed
int32_t scale =
std::max<int32_t>(1, nsDeviceContext::AppUnitsPerCSSPixel() /
aAppUnitsPerDevPixel);
aContext->Scale(gfxFloat(scale), gfxFloat(scale));
aContext->SetMatrix(
aContext->CurrentMatrix().Translate(center).Scale(scale, scale));
if (aChar < 0x10000) {
if (aRect.Width() >= 2 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {

View File

@ -23,21 +23,21 @@ gfxMatrix::Invert()
return cairo_matrix_invert(CAIRO_MATRIX(this)) == CAIRO_STATUS_SUCCESS;
}
const gfxMatrix&
gfxMatrix&
gfxMatrix::Scale(gfxFloat x, gfxFloat y)
{
cairo_matrix_scale(CAIRO_MATRIX(this), x, y);
return *this;
}
const gfxMatrix&
gfxMatrix&
gfxMatrix::Translate(const gfxPoint& pt)
{
cairo_matrix_translate(CAIRO_MATRIX(this), pt.x, pt.y);
return *this;
}
const gfxMatrix&
gfxMatrix&
gfxMatrix::Rotate(gfxFloat radians)
{
cairo_matrix_rotate(CAIRO_MATRIX(this), radians);
@ -51,7 +51,7 @@ gfxMatrix::operator *= (const gfxMatrix& m)
return *this;
}
const gfxMatrix&
gfxMatrix&
gfxMatrix::PreMultiply(const gfxMatrix& m)
{
cairo_matrix_multiply(CAIRO_MATRIX(this), CONST_CAIRO_MATRIX(&m), CAIRO_MATRIX(this));
@ -147,7 +147,7 @@ static void NudgeToInteger(double *aVal)
*aVal = f;
}
void
gfxMatrix&
gfxMatrix::NudgeToIntegers(void)
{
NudgeToInteger(&_11);
@ -156,4 +156,5 @@ gfxMatrix::NudgeToIntegers(void)
NudgeToInteger(&_22);
NudgeToInteger(&_31);
NudgeToInteger(&_32);
return *this;
}

View File

@ -127,13 +127,17 @@ public:
* Scales this matrix. The scale is pre-multiplied onto this matrix,
* i.e. the scaling takes place before the other transformations.
*/
const gfxMatrix& Scale(gfxFloat x, gfxFloat y);
gfxMatrix& Scale(gfxFloat x, gfxFloat y);
/**
* Translates this matrix. The translation is pre-multiplied onto this matrix,
* i.e. the translation takes place before the other transformations.
*/
const gfxMatrix& Translate(const gfxPoint& pt);
gfxMatrix& Translate(const gfxPoint& pt);
gfxMatrix& Translate(gfxFloat x, gfxFloat y) {
return Translate(gfxPoint(x, y));
}
/**
* Rotates this matrix. The rotation is pre-multiplied onto this matrix,
@ -141,14 +145,14 @@ public:
*
* @param radians Angle in radians.
*/
const gfxMatrix& Rotate(gfxFloat radians);
gfxMatrix& Rotate(gfxFloat radians);
/**
* Multiplies the current matrix with m.
* This is a pre-multiplication, i.e. the transformations of m are
* applied _before_ the existing transformations.
*/
const gfxMatrix& PreMultiply(const gfxMatrix& m);
gfxMatrix& PreMultiply(const gfxMatrix& m);
static gfxMatrix Translation(gfxFloat aX, gfxFloat aY)
{
@ -280,7 +284,7 @@ public:
* to integers. In particular, components that are integral when
* converted to single precision are set to those integers.
*/
void NudgeToIntegers(void);
gfxMatrix& NudgeToIntegers(void);
/**
* Returns true if matrix is multiple of 90 degrees rotation with flipping,

View File

@ -450,7 +450,7 @@ struct MOZ_STACK_CLASS AutoCairoPixmanBugWorkaround
// Clip the rounded-out-to-device-pixels bounds of the
// transformed fill area. This is the area for the group we
// want to push.
mContext->IdentityMatrix();
mContext->SetMatrix(gfxMatrix());
gfxRect bounds = currentMatrix.TransformBounds(aFill);
bounds.RoundOut();
mContext->Clip(bounds);

View File

@ -271,7 +271,8 @@ gfxWindowsNativeDrawing::PaintToContext()
gfxImageFormat::ARGB32);
mContext->Save();
mContext->Translate(mNativeRect.TopLeft());
mContext->SetMatrix(
mContext->CurrentMatrix().Translate(mNativeRect.TopLeft()));
mContext->NewPath();
mContext->Rectangle(gfxRect(gfxPoint(0.0, 0.0), mNativeRect.Size()));

View File

@ -288,9 +288,10 @@ SVGDrawingCallback::operator()(gfxContext* aContext,
if (!matrix.Invert()) {
return false;
}
aContext->Multiply(matrix);
aContext->Scale(double(mSize.width) / mViewport.width,
double(mSize.height) / mViewport.height);
aContext->SetMatrix(
aContext->CurrentMatrix().PreMultiply(matrix).
Scale(double(mSize.width) / mViewport.width,
double(mSize.height) / mViewport.height));
nsPresContext* presContext = presShell->GetPresContext();
MOZ_ASSERT(presContext, "pres shell w/out pres context");

View File

@ -312,6 +312,18 @@ nsresult imgFrame::Optimize()
return NS_OK;
}
DrawableFrameRef
imgFrame::DrawableRef()
{
return DrawableFrameRef(this);
}
RawAccessFrameRef
imgFrame::RawAccessRef()
{
return RawAccessFrameRef(this);
}
imgFrame::SurfaceWithFormat
imgFrame::SurfaceForDrawing(bool aDoPadding,
bool aDoPartialDecode,

View File

@ -8,6 +8,7 @@
#define imgFrame_h
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/Mutex.h"
#include "mozilla/VolatileBuffer.h"
#include "gfxDrawable.h"
@ -17,6 +18,8 @@ namespace mozilla {
namespace image {
class ImageRegion;
class DrawableFrameRef;
class RawAccessFrameRef;
class imgFrame
{
@ -36,6 +39,9 @@ public:
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, SurfaceFormat aFormat, uint8_t aPaletteDepth = 0);
nsresult Optimize();
DrawableFrameRef DrawableRef();
RawAccessFrameRef RawAccessRef();
bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
const nsIntMargin& aPadding, GraphicsFilter aFilter,
uint32_t aImageFlags);
@ -165,31 +171,165 @@ private: // data
/** Have we called DiscardTracker::InformAllocation()? */
bool mInformedDiscardTracker;
friend class DrawableFrameRef;
friend class RawAccessFrameRef;
};
// An RAII class to ensure it's easy to balance locks and unlocks on
// imgFrames.
class AutoFrameLocker
/**
* A reference to an imgFrame that holds the imgFrame's surface in memory,
* allowing drawing. If you have a DrawableFrameRef |ref| and |if (ref)| returns
* true, then calls to Draw() and GetSurface() are guaranteed to succeed.
*/
class DrawableFrameRef MOZ_FINAL
{
// Implementation details for safe boolean conversion.
typedef void (DrawableFrameRef::* ConvertibleToBool)(float*****, double*****);
void nonNull(float*****, double*****) {}
public:
explicit AutoFrameLocker(imgFrame* frame)
: mFrame(frame)
, mSucceeded(NS_SUCCEEDED(frame->LockImageData()))
DrawableFrameRef() { }
explicit DrawableFrameRef(imgFrame* aFrame)
: mFrame(aFrame)
, mRef(aFrame->mVBuf)
{
if (mRef.WasBufferPurged()) {
mFrame = nullptr;
mRef = nullptr;
}
}
DrawableFrameRef(DrawableFrameRef&& aOther)
: mFrame(aOther.mFrame.forget())
, mRef(Move(aOther.mRef))
{ }
~AutoFrameLocker()
DrawableFrameRef& operator=(DrawableFrameRef&& aOther)
{
if (mSucceeded) {
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
mFrame = aOther.mFrame.forget();
mRef = Move(aOther.mRef);
return *this;
}
operator ConvertibleToBool() const
{
return bool(mFrame) ? &DrawableFrameRef::nonNull : 0;
}
imgFrame* operator->()
{
MOZ_ASSERT(mFrame);
return mFrame;
}
const imgFrame* operator->() const
{
MOZ_ASSERT(mFrame);
return mFrame;
}
imgFrame* get() { return mFrame; }
const imgFrame* get() const { return mFrame; }
void reset()
{
mFrame = nullptr;
mRef = nullptr;
}
private:
nsRefPtr<imgFrame> mFrame;
VolatileBufferPtr<uint8_t> mRef;
};
/**
* A reference to an imgFrame that holds the imgFrame's surface in memory in a
* format appropriate for access as raw data. If you have a RawAccessFrameRef
* |ref| and |if (ref)| is true, then calls to GetImageData(), GetPaletteData(),
* and GetDrawTarget() are guaranteed to succeed. This guarantee is stronger
* than DrawableFrameRef, so everything that a valid DrawableFrameRef guarantees
* is also guaranteed by a valid RawAccessFrameRef.
*
* This may be considerably more expensive than is necessary just for drawing,
* so only use this when you need to read or write the raw underlying image data
* that the imgFrame holds.
*/
class RawAccessFrameRef MOZ_FINAL
{
// Implementation details for safe boolean conversion.
typedef void (RawAccessFrameRef::* ConvertibleToBool)(float*****, double*****);
void nonNull(float*****, double*****) {}
public:
RawAccessFrameRef() { }
explicit RawAccessFrameRef(imgFrame* aFrame)
: mFrame(aFrame)
{
MOZ_ASSERT(mFrame, "Need a frame");
if (NS_FAILED(mFrame->LockImageData())) {
mFrame->UnlockImageData();
mFrame = nullptr;
}
}
RawAccessFrameRef(RawAccessFrameRef&& aOther)
: mFrame(aOther.mFrame.forget())
{ }
~RawAccessFrameRef()
{
if (mFrame) {
mFrame->UnlockImageData();
}
}
// Whether the lock request succeeded.
bool Succeeded() { return mSucceeded; }
RawAccessFrameRef& operator=(RawAccessFrameRef&& aOther)
{
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
if (mFrame) {
mFrame->UnlockImageData();
}
mFrame = aOther.mFrame.forget();
return *this;
}
operator ConvertibleToBool() const
{
return bool(mFrame) ? &RawAccessFrameRef::nonNull : 0;
}
imgFrame* operator->()
{
MOZ_ASSERT(mFrame);
return mFrame.get();
}
const imgFrame* operator->() const
{
MOZ_ASSERT(mFrame);
return mFrame;
}
imgFrame* get() { return mFrame; }
const imgFrame* get() const { return mFrame; }
void reset()
{
if (mFrame) {
mFrame->UnlockImageData();
}
mFrame = nullptr;
}
private:
nsRefPtr<imgFrame> mFrame;
bool mSucceeded;
};
} // namespace image

View File

@ -1319,50 +1319,60 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
return true;
}
bool imgLoader::SetHasNoProxies(ImageURL *key, imgCacheEntry *entry)
bool imgLoader::SetHasNoProxies(imgRequest *aRequest, imgCacheEntry *aEntry)
{
nsRefPtr<ImageURL> uri;
aRequest->GetURI(getter_AddRefs(uri));
#if defined(PR_LOGGING)
nsAutoCString spec;
key->GetSpec(spec);
uri->GetSpec(spec);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::SetHasNoProxies", "uri", spec.get());
#endif
if (entry->Evicted())
aEntry->SetHasNoProxies(true);
if (aEntry->Evicted())
return false;
imgCacheQueue &queue = GetCacheQueue(key);
imgCacheQueue &queue = GetCacheQueue(uri);
nsresult addrv = NS_OK;
if (mCacheTracker)
addrv = mCacheTracker->AddObject(entry);
addrv = mCacheTracker->AddObject(aEntry);
if (NS_SUCCEEDED(addrv)) {
queue.Push(entry);
entry->SetHasNoProxies(true);
queue.Push(aEntry);
}
imgCacheTable &cache = GetCache(key);
imgCacheTable &cache = GetCache(uri);
CheckCacheLimits(cache, queue);
return true;
}
bool imgLoader::SetHasProxies(ImageURL *key)
bool imgLoader::SetHasProxies(imgRequest *aRequest)
{
VerifyCacheSizes();
imgCacheTable &cache = GetCache(key);
nsRefPtr<ImageURL> uri;
aRequest->GetURI(getter_AddRefs(uri));
imgCacheTable &cache = GetCache(uri);
nsAutoCString spec;
key->GetSpec(spec);
uri->GetSpec(spec);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::SetHasProxies", "uri", spec.get());
nsRefPtr<imgCacheEntry> entry;
if (cache.Get(spec, getter_AddRefs(entry)) && entry && entry->HasNoProxies()) {
imgCacheQueue &queue = GetCacheQueue(key);
if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
// Make sure the cache entry is for the right request
nsRefPtr<imgRequest> entryRequest = entry->GetRequest();
if (entryRequest == aRequest && entry->HasNoProxies()) {
imgCacheQueue &queue = GetCacheQueue(uri);
queue.Remove(entry);
if (mCacheTracker)
@ -1372,6 +1382,7 @@ bool imgLoader::SetHasProxies(ImageURL *key)
return true;
}
}
return false;
}

View File

@ -329,8 +329,8 @@ public:
// HasObservers(). The request's cache entry will be re-set before this
// happens, by calling imgRequest::SetCacheEntry() when an entry with no
// observers is re-requested.
bool SetHasNoProxies(ImageURL *key, imgCacheEntry *entry);
bool SetHasProxies(ImageURL *key);
bool SetHasNoProxies(imgRequest *aRequest, imgCacheEntry *aEntry);
bool SetHasProxies(imgRequest *aRequest);
private: // methods

View File

@ -177,7 +177,7 @@ void imgRequest::AddProxy(imgRequestProxy *proxy)
if (statusTracker->ConsumerCount() == 0) {
NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
if (mLoader) {
mLoader->SetHasProxies(mURI);
mLoader->SetHasProxies(this);
}
}
@ -209,7 +209,7 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri.");
if (mLoader) {
mLoader->SetHasNoProxies(mURI, mCacheEntry);
mLoader->SetHasNoProxies(this, mCacheEntry);
}
}
#if defined(PR_LOGGING)

View File

@ -87,6 +87,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
nsTArray<JSParam> *outparams) {
return Answer::AnswerCallOrConstruct(objId, argv, construct, rs, result, outparams);
}
bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasInstance(objId, v, rs, bp);
}
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) {
return Answer::AnswerObjectClassIs(objId, classValue, result);
@ -169,6 +172,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
nsTArray<JSParam> *outparams) {
return Base::CallCallOrConstruct(objId, argv, construct, rs, result, outparams);
}
bool CallHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Base::CallHasInstance(objId, v, rs, bp);
}
bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) {
return Base::CallObjectClassIs(objId, classValue, result);

View File

@ -37,6 +37,7 @@ both:
rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
rpc HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
rpc ClassName(uint64_t objId) returns (nsString name);

View File

@ -486,6 +486,30 @@ WrapperAnswer::AnswerCallOrConstruct(const ObjectId &objId,
return ok(rs);
}
bool
WrapperAnswer::AnswerHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj)
return fail(cx, rs);
JSAutoCompartment comp(cx, obj);
LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));
RootedValue val(cx);
if (!fromVariant(cx, vVar, &val))
return fail(cx, rs);
if (!JS_HasInstance(cx, obj, val, bp))
return fail(cx, rs);
return ok(rs);
}
bool
WrapperAnswer::AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result)

View File

@ -48,6 +48,7 @@ class WrapperAnswer : public virtual JavaScriptShared
bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams);
bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result);
bool AnswerClassName(const ObjectId &objId, nsString *result);

View File

@ -78,10 +78,14 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, HandleObject proxy,
MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
JSContext *cx) const MOZ_OVERRIDE;
virtual const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
static const char family;
static const CPOWProxyHandler singleton;
@ -568,6 +572,30 @@ WrapperOwner::callOrConstruct(JSContext *cx, HandleObject proxy, const CallArgs
return true;
}
bool
CPOWProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp) const
{
FORWARD(hasInstance, (cx, proxy, v, bp));
}
bool
WrapperOwner::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
{
ObjectId objId = idOf(proxy);
JSVariant vVar;
if (!toVariant(cx, v, &vVar))
return false;
ReturnStatus status;
JSVariant result;
if (!CallHasInstance(objId, vVar, &status, bp))
return ipcfail(cx);
LOG_STACK();
return ok(cx, status);
}
bool
CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx) const
@ -620,6 +648,25 @@ CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy) const
OwnerOf(proxy)->drop(proxy);
}
bool
CPOWProxyHandler::isCallable(JSObject *obj) const
{
return OwnerOf(obj)->isCallable(obj);
}
bool
CPOWProxyHandler::isConstructor(JSObject *obj) const
{
return isCallable(obj);
}
bool
WrapperOwner::isCallable(JSObject *obj)
{
ObjectId objId = idOf(obj);
return !!(objId & OBJECT_IS_CALLABLE);
}
void
WrapperOwner::drop(JSObject *obj)
{
@ -837,19 +884,14 @@ WrapperOwner::fromRemoteObjectVariant(JSContext *cx, RemoteObject objVar)
return nullptr;
}
bool callable = !!(objId & OBJECT_IS_CALLABLE);
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
RootedValue v(cx, UndefinedValue());
ProxyOptions options;
options.selectDefaultClass(callable);
obj = NewProxyObject(cx,
&CPOWProxyHandler::singleton,
v,
nullptr,
global,
options);
global);
if (!obj)
return nullptr;

View File

@ -57,8 +57,11 @@ class WrapperOwner : public virtual JavaScriptShared
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
bool construct);
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
const char* className(JSContext *cx, JS::HandleObject proxy);
bool isCallable(JSObject *obj);
// isConstructable is implemented here as isCallable.
nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
@ -129,6 +132,8 @@ class WrapperOwner : public virtual JavaScriptShared
virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) = 0;
virtual bool CallHasInstance(const ObjectId &objId, const JSVariant &v,
ReturnStatus *rs, bool *bp) = 0;
virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) = 0;
virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;

View File

@ -482,7 +482,8 @@ struct Class
return flags & JSCLASS_EMULATES_UNDEFINED;
}
bool isCallable() const {
bool nonProxyCallable() const {
MOZ_ASSERT(!isProxy());
return this == js::FunctionClassPtr || call;
}

View File

@ -8764,16 +8764,40 @@ CodeGenerator::visitProfilerStackOp(LProfilerStackOp *lir)
}
}
class OutOfLineIsCallable : public OutOfLineCodeBase<CodeGenerator>
{
LIsCallable *ins_;
public:
OutOfLineIsCallable(LIsCallable *ins)
: ins_(ins)
{ }
bool accept(CodeGenerator *codegen) {
return codegen->visitOutOfLineIsCallable(this);
}
LIsCallable *ins() const {
return ins_;
}
};
bool
CodeGenerator::visitIsCallable(LIsCallable *ins)
{
Register object = ToRegister(ins->object());
Register output = ToRegister(ins->output());
OutOfLineIsCallable *ool = new(alloc()) OutOfLineIsCallable(ins);
if (!addOutOfLineCode(ool, ins->mir()))
return false;
Label notFunction, done;
masm.loadObjClass(object, output);
// An object is callable iff (is<JSFunction>() || getClass()->call).
Label notFunction, done, notCall;
// Just skim proxies off. Their notion of isCallable() is more complicated.
masm.branchTestClassIsProxy(true, output, ool->entry());
// An object is callable iff (is<JSFunction>() || getClass()->call.
masm.branchPtr(Assembler::NotEqual, output, ImmPtr(&JSFunction::class_), &notFunction);
masm.move32(Imm32(1), output);
masm.jump(&done);
@ -8781,6 +8805,28 @@ CodeGenerator::visitIsCallable(LIsCallable *ins)
masm.bind(&notFunction);
masm.cmpPtrSet(Assembler::NonZero, Address(output, offsetof(js::Class, call)), ImmPtr(nullptr), output);
masm.bind(&done);
masm.bind(ool->rejoin());
return true;
}
bool
CodeGenerator::visitOutOfLineIsCallable(OutOfLineIsCallable *ool)
{
LIsCallable *ins = ool->ins();
Register object = ToRegister(ins->object());
Register output = ToRegister(ins->output());
saveVolatile(output);
masm.setupUnalignedABICall(1, output);
masm.passABIArg(object);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ObjectIsCallable));
masm.storeCallResult(output);
// C++ compilers like to only use the bottom byte for bools, but we need to maintain the entire
// register.
masm.and32(Imm32(0xFF), output);
restoreVolatile(output);
masm.jump(ool->rejoin());
return true;
}

View File

@ -43,6 +43,7 @@ class OutOfLineLoadTypedArray;
class OutOfLineNewGCThingPar;
class OutOfLineUpdateCache;
class OutOfLineCallPostWriteBarrier;
class OutOfLineIsCallable;
class CodeGenerator : public CodeGeneratorSpecific
{
@ -296,6 +297,7 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitCallDOMNative(LCallDOMNative *lir);
bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
bool visitIsCallable(LIsCallable *lir);
bool visitOutOfLineIsCallable(OutOfLineIsCallable *ool);
bool visitIsObject(LIsObject *lir);
bool visitHaveSameClass(LHaveSameClass *lir);
bool visitHasClass(LHasClass *lir);

View File

@ -1567,16 +1567,6 @@ GetPropertyIC::tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript
return tryAttachGenericProxy(cx, outerScript, ion, obj, name, returnAddr, emitted);
}
static void
GenerateProxyClassGuards(MacroAssembler &masm, Register object, Register scratchReg,
Label *failures)
{
masm.loadObjClass(object, scratchReg);
masm.branchTest32(Assembler::Zero,
Address(scratchReg, Class::offsetOfFlags()),
Imm32(JSCLASS_IS_PROXY), failures);
}
bool
GetPropertyIC::tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandlePropertyName name, void *returnAddr,
@ -1602,7 +1592,7 @@ GetPropertyIC::tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, Io
Register scratchReg = output().valueReg().scratchReg();
GenerateProxyClassGuards(masm, object(), scratchReg, &failures);
masm.branchTestObjectIsProxy(false, object(), scratchReg, &failures);
// Ensure that the incoming object is not a DOM proxy, so that we can get to
// the specialized stubs
@ -2181,7 +2171,7 @@ SetPropertyIC::attachGenericProxy(JSContext *cx, HandleScript outerScript, IonSc
Register scratch = regSet.takeGeneral();
masm.push(scratch);
GenerateProxyClassGuards(masm, object(), scratch, &proxyFailures);
masm.branchTestObjectIsProxy(false, object(), scratch, &proxyFailures);
// Remove the DOM proxies. They'll take care of themselves so this stub doesn't
// catch too much. The failure case is actually Equal. Fall through to the failure code.

View File

@ -982,12 +982,25 @@ class MacroAssembler : public MacroAssemblerSpecific
loadObjClass(objReg, scratch);
Address flags(scratch, Class::offsetOfFlags());
branchTest32(Assembler::NonZero, flags, Imm32(JSCLASS_IS_PROXY), slowCheck);
branchTestClassIsProxy(true, scratch, slowCheck);
Condition cond = truthy ? Assembler::Zero : Assembler::NonZero;
branchTest32(cond, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), checked);
}
void branchTestClassIsProxy(bool proxy, Register clasp, Label *label)
{
branchTest32(proxy ? Assembler::NonZero : Assembler::Zero,
Address(clasp, Class::offsetOfFlags()),
Imm32(JSCLASS_IS_PROXY), label);
}
void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label *label)
{
loadObjClass(object, scratch);
branchTestClassIsProxy(proxy, scratch, label);
}
private:
// These two functions are helpers used around call sites throughout the
// assembler. They are called from the above call wrappers to emit the

View File

@ -128,25 +128,6 @@ class LMoveGroup : public LInstructionHelper<0, 0, 0>
}
};
// Constructs a SIMD value with 4 components (e.g. int32x4, float32x4).
class LSimdValueX4 : public LInstructionHelper<1, 4, 0>
{
public:
LIR_HEADER(SimdValueX4)
LSimdValueX4(const LAllocation &x, const LAllocation &y,
const LAllocation &z, const LAllocation &w)
{
setOperand(0, x);
setOperand(1, y);
setOperand(2, z);
setOperand(3, w);
}
MSimdValueX4 *mir() const {
return mir_->toSimdValueX4();
}
};
// Constructs a SIMD value with 4 equal components (e.g. int32x4, float32x4).
class LSimdSplatX4 : public LInstructionHelper<1, 1, 0>
{

View File

@ -16,7 +16,6 @@
_(Pointer) \
_(Double) \
_(Float32) \
_(SimdValueX4) \
_(SimdSplatX4) \
_(Int32x4) \
_(Float32x4) \

View File

@ -3686,17 +3686,6 @@ LIRGenerator::visitRecompileCheck(MRecompileCheck *ins)
return assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitSimdValueX4(MSimdValueX4 *ins)
{
LAllocation x = useRegisterAtStart(ins->getOperand(0));
LAllocation y = useRegisterAtStart(ins->getOperand(1));
LAllocation z = useRegisterAtStart(ins->getOperand(2));
LAllocation w = useRegisterAtStart(ins->getOperand(3));
return define(new(alloc()) LSimdValueX4(x, y, z, w), ins);
}
bool
LIRGenerator::visitSimdConstant(MSimdConstant *ins)
{

View File

@ -273,7 +273,6 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitSimdBinaryComp(MSimdBinaryComp *ins);
bool visitSimdBinaryArith(MSimdBinaryArith *ins);
bool visitSimdBinaryBitwise(MSimdBinaryBitwise *ins);
bool visitSimdValueX4(MSimdValueX4 *ins);
bool visitSimdConstant(MSimdConstant *ins);
bool visitPhi(MPhi *ins);
bool visitBeta(MBeta *ins);

View File

@ -1982,9 +1982,9 @@ IonBuilder::inlineIsCallable(CallInfo &callInfo)
} else {
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
const Class *clasp = types ? types->getKnownClass() : nullptr;
if (clasp) {
if (clasp && !clasp->isProxy()) {
isCallableKnown = true;
isCallableConstant = clasp->isCallable();
isCallableConstant = clasp->nonProxyCallable();
}
}

View File

@ -1239,6 +1239,12 @@ TypedObjectProto(JSObject *obj)
return &typedObj.typedProto();
}
bool
ObjectIsCallable(JSObject *obj)
{
return obj->isCallable();
}
void
MarkValueFromIon(JSRuntime *rt, Value *vp)
{

View File

@ -747,6 +747,8 @@ IonMarkFunction(MIRType type)
}
}
bool ObjectIsCallable(JSObject *obj);
} // namespace jit
} // namespace js

View File

@ -229,7 +229,6 @@ class CodeGeneratorARM : public CodeGeneratorShared
public:
// Unimplemented SIMD instructions
bool visitSimdValueX4(LSimdValueX4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdSplatX4(LSimdSplatX4 *lir) { MOZ_CRASH("NYI"); }
bool visitInt32x4(LInt32x4 *ins) { MOZ_CRASH("NYI"); }
bool visitFloat32x4(LFloat32x4 *ins) { MOZ_CRASH("NYI"); }

View File

@ -561,4 +561,10 @@ LIRGeneratorARM::visitSimdSplatX4(MSimdSplatX4 *ins)
MOZ_CRASH("NYI");
}
bool
LIRGeneratorARM::visitSimdValueX4(MSimdValueX4 *ins)
{
MOZ_CRASH("NYI");
}
//__aeabi_uidiv

View File

@ -93,6 +93,7 @@ class LIRGeneratorARM : public LIRGeneratorShared
bool visitForkJoinGetSlice(MForkJoinGetSlice *ins);
bool visitSimdTernaryBitwise(MSimdTernaryBitwise *ins);
bool visitSimdSplatX4(MSimdSplatX4 *ins);
bool visitSimdValueX4(MSimdValueX4 *ins);
};
typedef LIRGeneratorARM LIRGeneratorSpecific;

View File

@ -1411,18 +1411,18 @@ class AssemblerX86Shared : public AssemblerShared
JS_ASSERT(HasSSE2());
masm.unpcklps_rr(src.code(), dest.code());
}
void pinsrd(Register src, FloatRegister dest) {
void pinsrd(unsigned lane, Register src, FloatRegister dest) {
JS_ASSERT(HasSSE2());
masm.pinsrd_rr(src.code(), dest.code());
masm.pinsrd_irr(lane, src.code(), dest.code());
}
void pinsrd(const Operand &src, FloatRegister dest) {
void pinsrd(unsigned lane, const Operand &src, FloatRegister dest) {
JS_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::REG:
masm.pinsrd_rr(src.reg(), dest.code());
masm.pinsrd_irr(lane, src.reg(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.pinsrd_mr(src.disp(), src.base(), dest.code());
masm.pinsrd_imr(lane, src.disp(), src.base(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");

View File

@ -348,7 +348,7 @@ private:
OP3_ROUNDSS_VsdWsd = 0x0A,
OP3_ROUNDSD_VsdWsd = 0x0B,
OP3_PTEST_VdVd = 0x17,
OP3_PINSRD_VsdWsd = 0x22
OP3_PINSRD_VdqEdIb = 0x22
} ThreeByteOpcodeID;
typedef enum {
@ -3562,23 +3562,25 @@ public:
m_formatter.immediate8(mode); // modes are the same for roundsd and roundss
}
void pinsrd_rr(RegisterID src, XMMRegisterID dst)
void pinsrd_irr(unsigned lane, RegisterID src, XMMRegisterID dst)
{
spew("pinsrd $1, %s, %s",
nameIReg(src), nameFPReg(dst));
MOZ_ASSERT(lane < 4);
spew("pinsrd $%u, %s, %s",
lane, nameIReg(src), nameFPReg(dst));
m_formatter.prefix(PRE_SSE_66);
m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, ESCAPE_PINSRD, (RegisterID)dst, (RegisterID)src);
m_formatter.immediate8(0x01); // the $1
m_formatter.threeByteOp(OP3_PINSRD_VdqEdIb, ESCAPE_PINSRD, (RegisterID)dst, (RegisterID)src);
m_formatter.immediate8(uint8_t(lane));
}
void pinsrd_mr(int offset, RegisterID base, XMMRegisterID dst)
void pinsrd_imr(unsigned lane, int offset, RegisterID base, XMMRegisterID dst)
{
spew("pinsrd $1, %s0x%x(%s), %s",
PRETTY_PRINT_OFFSET(offset),
MOZ_ASSERT(lane < 4);
spew("pinsrd $%u, %s0x%x(%s), %s",
lane, PRETTY_PRINT_OFFSET(offset),
nameIReg(base), nameFPReg(dst));
m_formatter.prefix(PRE_SSE_66);
m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, ESCAPE_PINSRD, (RegisterID)dst, base, offset);
m_formatter.immediate8(0x01); // the $1
m_formatter.threeByteOp(OP3_PINSRD_VdqEdIb, ESCAPE_PINSRD, (RegisterID)dst, base, offset);
m_formatter.immediate8(uint8_t(lane));
}
void minsd_rr(XMMRegisterID src, XMMRegisterID dst)

View File

@ -2119,37 +2119,48 @@ CodeGeneratorX86Shared::visitFloat32x4(LFloat32x4 *ins)
}
bool
CodeGeneratorX86Shared::visitSimdValueX4(LSimdValueX4 *ins)
CodeGeneratorX86Shared::visitSimdValueInt32x4(LSimdValueInt32x4 *ins)
{
FloatRegister output = ToFloatRegister(ins->output());
MSimdValueX4 *mir = ins->mir();
JS_ASSERT(IsSimdType(mir->type()));
JS_STATIC_ASSERT(sizeof(float) == sizeof(int32_t));
MOZ_ASSERT(mir->type() == MIRType_Int32x4);
FloatRegister output = ToFloatRegister(ins->output());
if (AssemblerX86Shared::HasSSE41()) {
masm.movd(ToRegister(ins->getOperand(0)), output);
for (size_t i = 1; i < 4; ++i) {
Register r = ToRegister(ins->getOperand(i));
masm.pinsrd(i, r, output);
}
return true;
}
masm.reserveStack(Simd128DataSize);
// TODO see bug 1051860 for possible optimizations.
switch (mir->type()) {
case MIRType_Int32x4: {
for (size_t i = 0; i < 4; ++i) {
Register r = ToRegister(ins->getOperand(i));
masm.store32(r, Address(StackPointer, i * sizeof(int32_t)));
}
masm.loadAlignedInt32x4(Address(StackPointer, 0), output);
break;
}
case MIRType_Float32x4: {
for (size_t i = 0; i < 4; ++i) {
FloatRegister r = ToFloatRegister(ins->getOperand(i));
masm.storeFloat32(r, Address(StackPointer, i * sizeof(float)));
}
masm.loadAlignedFloat32x4(Address(StackPointer, 0), output);
break;
}
default: MOZ_CRASH("Unknown SIMD kind");
masm.freeStack(Simd128DataSize);
return true;
}
masm.freeStack(Simd128DataSize);
bool
CodeGeneratorX86Shared::visitSimdValueFloat32x4(LSimdValueFloat32x4 *ins)
{
MSimdValueX4 *mir = ins->mir();
MOZ_ASSERT(mir->type() == MIRType_Float32x4);
FloatRegister output = ToFloatRegister(ins->output());
FloatRegister r0 = ToFloatRegister(ins->getOperand(0));
MOZ_ASSERT(r0 == output); // defineReuseInput(0)
FloatRegister r1 = ToFloatRegister(ins->getTemp(0));
FloatRegister r2 = ToFloatRegister(ins->getOperand(2));
FloatRegister r3 = ToFloatRegister(ins->getOperand(3));
masm.unpcklps(r3, r1);
masm.unpcklps(r2, r0);
masm.unpcklps(r1, r0);
return true;
}

View File

@ -206,7 +206,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
bool visitNegF(LNegF *lir);
// SIMD operators
bool visitSimdValueX4(LSimdValueX4 *lir);
bool visitSimdValueInt32x4(LSimdValueInt32x4 *lir);
bool visitSimdValueFloat32x4(LSimdValueFloat32x4 *lir);
bool visitSimdSplatX4(LSimdSplatX4 *lir);
bool visitInt32x4(LInt32x4 *ins);
bool visitFloat32x4(LFloat32x4 *ins);

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