mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 02:09:28 +00:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
e393d7ab02
3
.gitignore
vendored
3
.gitignore
vendored
@ -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
|
||||
|
@ -11,6 +11,9 @@
|
||||
^\.sw.$
|
||||
.[^/]*\.sw.$
|
||||
|
||||
# Emacs directory variable files.
|
||||
\.dir-locals\.el
|
||||
|
||||
# User files that may appear at the root
|
||||
^\.mozconfig
|
||||
^mozconfig*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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`.");
|
||||
})
|
||||
}
|
||||
|
||||
];
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,7 +2303,47 @@ 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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">
|
||||
|
@ -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'):
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -159,7 +159,7 @@ let AboutHome = {
|
||||
if (userData) {
|
||||
window.openPreferences("paneSync");
|
||||
} else {
|
||||
window.loadURI("about:accounts");
|
||||
window.loadURI("about:accounts?entrypoint=abouthome");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -6,4 +6,6 @@
|
||||
|
||||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
@ -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
|
||||
|
@ -6,4 +6,6 @@
|
||||
|
||||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
BIN
browser/themes/shared/e10s-64@2x.png
Normal file
BIN
browser/themes/shared/e10s-64@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@ -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
|
||||
|
@ -6,4 +6,6 @@
|
||||
|
||||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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']:
|
||||
|
10
configure.in
10
configure.in
@ -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 ========================================================
|
||||
|
@ -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;
|
||||
@ -267,8 +272,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mTimescale;
|
||||
private:
|
||||
nsRefPtr<mp4_demuxer::BufferStream> mStream;
|
||||
nsAutoPtr<mp4_demuxer::MoofParser> mParser;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(¤tValue);
|
||||
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*
|
||||
|
@ -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;
|
||||
|
@ -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')],
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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*
|
||||
|
@ -34,6 +34,9 @@ ContentProcess::Init()
|
||||
void
|
||||
ContentProcess::CleanUp()
|
||||
{
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
mContent.CleanUpSandboxEnvironment();
|
||||
#endif
|
||||
mXREEmbed.Stop();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,15 +1963,15 @@ 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;
|
||||
}
|
||||
|
||||
// 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,
|
||||
@ -2001,13 +2000,13 @@ bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity,
|
||||
false /* do not allow overscroll */);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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) &&
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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,32 +171,166 @@ 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
|
||||
{
|
||||
public:
|
||||
explicit AutoFrameLocker(imgFrame* frame)
|
||||
: mFrame(frame)
|
||||
, mSucceeded(NS_SUCCEEDED(frame->LockImageData()))
|
||||
{}
|
||||
/**
|
||||
* 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*****) {}
|
||||
|
||||
~AutoFrameLocker()
|
||||
{
|
||||
if (mSucceeded) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
public:
|
||||
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))
|
||||
{ }
|
||||
|
||||
DrawableFrameRef& operator=(DrawableFrameRef&& aOther)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
RawAccessFrameRef& operator=(RawAccessFrameRef&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
|
||||
|
||||
if (mFrame) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
|
||||
// Whether the lock request succeeded.
|
||||
bool Succeeded() { return mSucceeded; }
|
||||
mFrame = aOther.mFrame.forget();
|
||||
|
||||
private:
|
||||
nsRefPtr<imgFrame> mFrame;
|
||||
bool mSucceeded;
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
@ -1319,58 +1319,69 @@ 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);
|
||||
queue.Remove(entry);
|
||||
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)
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
|
||||
entry->SetHasNoProxies(false);
|
||||
entry->SetHasNoProxies(false);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_), ¬Function);
|
||||
masm.move32(Imm32(1), output);
|
||||
masm.jump(&done);
|
||||
@ -8781,6 +8805,28 @@ CodeGenerator::visitIsCallable(LIsCallable *ins)
|
||||
masm.bind(¬Function);
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -16,7 +16,6 @@
|
||||
_(Pointer) \
|
||||
_(Double) \
|
||||
_(Float32) \
|
||||
_(SimdValueX4) \
|
||||
_(SimdSplatX4) \
|
||||
_(Int32x4) \
|
||||
_(Float32x4) \
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1239,6 +1239,12 @@ TypedObjectProto(JSObject *obj)
|
||||
return &typedObj.typedProto();
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectIsCallable(JSObject *obj)
|
||||
{
|
||||
return obj->isCallable();
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueFromIon(JSRuntime *rt, Value *vp)
|
||||
{
|
||||
|
@ -747,6 +747,8 @@ IonMarkFunction(MIRType type)
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectIsCallable(JSObject *obj);
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -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"); }
|
||||
|
@ -561,4 +561,10 @@ LIRGeneratorARM::visitSimdSplatX4(MSimdSplatX4 *ins)
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGeneratorARM::visitSimdValueX4(MSimdValueX4 *ins)
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
//__aeabi_uidiv
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -2119,40 +2119,51 @@ 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);
|
||||
|
||||
masm.reserveStack(Simd128DataSize);
|
||||
// TODO see bug 1051860 for possible optimizations.
|
||||
switch (mir->type()) {
|
||||
case MIRType_Int32x4: {
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
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.store32(r, Address(StackPointer, i * sizeof(int32_t)));
|
||||
masm.pinsrd(i, r, output);
|
||||
}
|
||||
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");
|
||||
return true;
|
||||
}
|
||||
|
||||
masm.reserveStack(Simd128DataSize);
|
||||
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);
|
||||
masm.freeStack(Simd128DataSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitSimdSplatX4(LSimdSplatX4 *ins)
|
||||
{
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user