MozReview-Commit-ID: AVhTkLAYIv7
This commit is contained in:
Wes Kocher 2017-05-18 17:13:28 -07:00
Родитель 1e6c284b5a 9461e33846
Коммит 0174ce8ebb
88 изменённых файлов: 2348 добавлений и 1067 удалений

Просмотреть файл

@ -1282,8 +1282,6 @@ pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
// (This is intentionally on the high side; see bug 746055.)
pref("image.mem.max_decoded_image_kb", 256000);
pref("social.sidebar.unload_timeout_ms", 10000);
// Activation from inside of share panel is possible if activationPanelEnabled
// is true. Pref'd off for release while usage testing is done through beta.
pref("social.share.activationPanelEnabled", true);

Просмотреть файл

@ -996,6 +996,35 @@ function serializeInputStream(aStream) {
return data;
}
/**
* Handles URIs when we want to deal with them in chrome code rather than pass
* them down to a content browser. This can avoid unnecessary process switching
* for the browser.
* @param aBrowser the browser that is attempting to load the URI
* @param aUri the nsIURI that is being loaded
* @returns true if the URI is handled, otherwise false
*/
function handleUriInChrome(aBrowser, aUri) {
if (aUri.scheme == "file") {
try {
let mimeType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
.getTypeFromURI(aUri);
if (mimeType == "application/x-xpinstall") {
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
AddonManager.getInstallForURL(aUri.spec, install => {
AddonManager.installAddonFromWebpage(mimeType, aBrowser, systemPrincipal,
install);
}, mimeType);
return true;
}
} catch (e) {
return false;
}
}
return false;
}
// A shared function used by both remote and non-remote browser XBL bindings to
// load a URI or redirect it to the correct process.
function _loadURIWithFlags(browser, uri, params) {
@ -1016,8 +1045,33 @@ function _loadURIWithFlags(browser, uri, params) {
let postData = params.postData;
let currentRemoteType = browser.remoteType;
let requiredRemoteType =
E10SUtils.getRemoteTypeForURI(uri, gMultiProcessBrowser, currentRemoteType);
let requiredRemoteType;
try {
let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_NONE;
if (flags & Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
fixupFlags |= Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
}
if (flags & Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
fixupFlags |= Ci.nsIURIFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS;
}
let uriObject = Services.uriFixup.createFixupURI(uri, fixupFlags);
if (handleUriInChrome(browser, uriObject)) {
// If we've handled the URI in Chrome then just return here.
return;
}
// Note that I had thought that we could set uri = uriObject.spec here, to
// save on fixup later on, but that changes behavior and breaks tests.
requiredRemoteType =
E10SUtils.getRemoteTypeForURIObject(uriObject, gMultiProcessBrowser,
currentRemoteType, browser.currentURI);
} catch (e) {
// createFixupURI throws if it can't create a URI. If that's the case then
// we still need to pass down the uri because docshell handles this case.
requiredRemoteType = gMultiProcessBrowser ? E10SUtils.DEFAULT_REMOTE_TYPE
: E10SUtils.NOT_REMOTE;
}
let mustChangeProcess = requiredRemoteType != currentRemoteType;
// !requiredRemoteType means we're loading in the parent/this process.
@ -1052,6 +1106,7 @@ function _loadURIWithFlags(browser, uri, params) {
flags,
referrer: referrer ? referrer.spec : null,
referrerPolicy,
remoteType: requiredRemoteType,
postData
}
@ -1097,6 +1152,18 @@ function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) {
// Called when a docshell has attempted to load a page in an incorrect process.
// This function is responsible for loading the page in the correct process.
function RedirectLoad({ target: browser, data }) {
if (data.loadOptions.reloadInFreshProcess) {
// Convert the fresh process load option into a large allocation remote type
// to use common processing from this point.
data.loadOptions.remoteType = E10SUtils.LARGE_ALLOCATION_REMOTE_TYPE;
data.loadOptions.newFrameloader = true;
} else if (browser.remoteType == E10SUtils.LARGE_ALLOCATION_REMOTE_TYPE) {
// If we're in a Large-Allocation process, we prefer switching back into a
// normal content process, as that way we can clean up the L-A process.
data.loadOptions.remoteType =
E10SUtils.getRemoteTypeForURI(data.loadOptions.uri, gMultiProcessBrowser);
}
// We should only start the redirection if the browser window has finished
// starting up. Otherwise, we should wait until the startup is done.
if (gBrowserInit.delayedStartupFinished) {
@ -1136,17 +1203,47 @@ addEventListener("DOMContentLoaded", function onDCL() {
let initBrowser =
document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
// The window's first argument is a tab if and only if we are swapping tabs.
// We must set the browser's usercontextid before updateBrowserRemoteness(),
// so that the newly created remote tab child has the correct usercontextid.
// remoteType and sameProcessAsFrameLoader are passed through to
// updateBrowserRemoteness as part of an options object, which itself defaults
// to an empty object. So defaulting them to undefined here will cause the
// default behavior in updateBrowserRemoteness if they don't get set.
let isRemote = gMultiProcessBrowser;
let remoteType;
let sameProcessAsFrameLoader;
if (window.arguments) {
let tabToOpen = window.arguments[0];
if (tabToOpen instanceof XULElement && tabToOpen.hasAttribute("usercontextid")) {
initBrowser.setAttribute("usercontextid", tabToOpen.getAttribute("usercontextid"));
let argToLoad = window.arguments[0];
if (argToLoad instanceof XULElement) {
// The window's first argument is a tab if and only if we are swapping tabs.
// We must set the browser's usercontextid before updateBrowserRemoteness(),
// so that the newly created remote tab child has the correct usercontextid.
if (argToLoad.hasAttribute("usercontextid")) {
initBrowser.setAttribute("usercontextid",
argToLoad.getAttribute("usercontextid"));
}
let linkedBrowser = argToLoad.linkedBrowser;
if (linkedBrowser) {
remoteType = linkedBrowser.remoteType;
isRemote = remoteType != E10SUtils.NOT_REMOTE;
sameProcessAsFrameLoader = linkedBrowser.frameLoader;
}
} else if (argToLoad instanceof String) {
// argToLoad is String, so should be a URL.
remoteType = E10SUtils.getRemoteTypeForURI(argToLoad, gMultiProcessBrowser);
isRemote = remoteType != E10SUtils.NOT_REMOTE;
} else if (argToLoad instanceof Ci.nsIArray) {
// argToLoad is nsIArray, so should be an array of URLs, set the remote
// type for the initial browser to match the first one.
let urisstring = argToLoad.queryElementAt(0, Ci.nsISupportsString);
remoteType = E10SUtils.getRemoteTypeForURI(urisstring.data,
gMultiProcessBrowser);
isRemote = remoteType != E10SUtils.NOT_REMOTE;
}
}
gBrowser.updateBrowserRemoteness(initBrowser, gMultiProcessBrowser);
gBrowser.updateBrowserRemoteness(initBrowser, isRemote, {
remoteType, sameProcessAsFrameLoader
});
});
let _resolveDelayedStartup;

Просмотреть файл

@ -1753,10 +1753,13 @@
}
// NB: This works with the hack in the browser constructor that
// turns this normal property into a field. When switching remote
// type copying related browser would stop the switch and the
// previously related browser will no longer be relevant.
if (!aShouldBeRemote || currentRemoteType == aOptions.remoteType) {
// turns this normal property into a field.
if (aOptions.sameProcessAsFrameLoader) {
// Always set sameProcessAsFrameLoader when passed in aOptions.
aBrowser.sameProcessAsFrameLoader = aOptions.sameProcessAsFrameLoader;
} else if (!aShouldBeRemote || currentRemoteType == aOptions.remoteType) {
// Only copy existing sameProcessAsFrameLoader when not switching
// remote type otherwise it would stop the switch.
aBrowser.sameProcessAsFrameLoader = sameProcessAsFrameLoader;
}
@ -1841,20 +1844,13 @@
if (!gMultiProcessBrowser)
return this.updateBrowserRemoteness(aBrowser, false);
// If we're in a LargeAllocation process, we prefer switching back
// into a normal content process, as that way we can clean up the
// L-A process.
let currentRemoteType = aBrowser.getAttribute("remoteType") || null;
let preferredRemoteType = currentRemoteType;
if (currentRemoteType == E10SUtils.LARGE_ALLOCATION_REMOTE_TYPE) {
preferredRemoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
}
aOptions.remoteType =
E10SUtils.getRemoteTypeForURI(aURL,
gMultiProcessBrowser,
preferredRemoteType,
aOptions.freshProcess);
currentRemoteType,
aBrowser.currentURI);
// If this URL can't load in the current browser then flip it to the
// correct type.
@ -3604,21 +3600,19 @@
<![CDATA[
// Swap the dropped tab with a new one we create and then close
// it in the other window (making it seem to have moved between
// windows).
let params = { eventDetail: { adoptedTab: aTab } };
// windows). We also ensure that the tab we create to swap into has
// the same remote type and process as the one we're swapping in.
// This makes sure we don't get a short-lived process for the new tab.
let linkedBrowser = aTab.linkedBrowser;
let params = { eventDetail: { adoptedTab: aTab },
preferredRemoteType: linkedBrowser.remoteType,
sameProcessAsFrameLoader: linkedBrowser.frameLoader };
if (aTab.hasAttribute("usercontextid")) {
// new tab must have the same usercontextid as the old one
params.userContextId = aTab.getAttribute("usercontextid");
}
let newTab = this.addTab("about:blank", params);
let newBrowser = this.getBrowserForTab(newTab);
let newURL = aTab.linkedBrowser.currentURI.spec;
// If we're an e10s browser window, an exception will be thrown
// if we attempt to drag a non-remote browser in, so we need to
// ensure that the remoteness of the newly created browser is
// appropriate for the URL of the tab being dragged in.
this.updateBrowserRemotenessByURL(newBrowser, newURL);
// Stop the about:blank load.
newBrowser.stop();

Просмотреть файл

@ -3,6 +3,19 @@
const TEST_FILE = "dummy_page.html";
const TEST_HTTP = "http://example.org/";
const TEST_CROSS_ORIGIN = "http://example.com/";
function CheckBrowserInPid(browser, expectedPid, message) {
return ContentTask.spawn(browser, { expectedPid, message }, (arg) => {
is(Services.appinfo.processID, arg.expectedPid, arg.message);
});
}
function CheckBrowserNotInPid(browser, unExpectedPid, message) {
return ContentTask.spawn(browser, { unExpectedPid, message }, (arg) => {
isnot(Services.appinfo.processID, arg.unExpectedPid, arg.message);
});
}
// Test for bug 1343184.
add_task(async function() {
@ -11,29 +24,115 @@ add_task(async function() {
dir.append(TEST_FILE);
const uriString = Services.io.newFileURI(dir).spec;
await BrowserTestUtils.withNewTab(uriString, async function(fileBrowser) {
// Set prefs to ensure file content process and to allow linked web content
// in file URI process.
// Set prefs to ensure file content process, to allow linked web content
// in file URI process and allow more that one file content process.
await SpecialPowers.pushPrefEnv(
{set: [["browser.tabs.remote.separateFileUriProcess", true],
["browser.tabs.remote.allowLinkedWebInFileUriProcess", true]]});
["browser.tabs.remote.allowLinkedWebInFileUriProcess", true],
["dom.ipc.processCount.file", 2]]});
// Open new http tab from JavaScript in file:// page.
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, TEST_HTTP);
// Get the file:// URI pid for comparison later.
let filePid = await ContentTask.spawn(fileBrowser, null, () => {
return Services.appinfo.processID;
});
// Check that http tab opened from JS in file:// page is in same process.
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, TEST_HTTP, true);
await ContentTask.spawn(fileBrowser, TEST_HTTP, uri => {
content.open(uri, "_blank");
});
let httpTab = await promiseTabOpened;
let httpBrowser = httpTab.linkedBrowser;
registerCleanupFunction(async function() {
await BrowserTestUtils.removeTab(httpTab);
});
await CheckBrowserInPid(httpBrowser, filePid,
"Check that new http tab opened from file loaded in file content process.");
// Ensure that http browser is running in the same process as the file:// one.
let filePid = await ContentTask.spawn(fileBrowser, null, () => {
// Check that reload doesn't break the file content process affinity.
if (httpTab != gBrowser.selectedTab) {
httpTab = await BrowserTestUtils.switchTab(gBrowser, httpTab);
httpBrowser = httpTab.linkedBrowser;
}
let promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
document.getElementById("reload-button").doCommand();
await promiseLoad;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after reload.");
// Check that same-origin load doesn't break the affinity.
promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
httpBrowser.loadURI(TEST_HTTP + "foo");
await promiseLoad;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after same origin load.");
// Check that history back doesn't break the affinity.
let promiseLocation =
BrowserTestUtils.waitForLocationChange(gBrowser, TEST_HTTP);
httpBrowser.goBack();
await promiseLocation;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after history back.");
// Check that history forward doesn't break the affinity.
promiseLocation =
BrowserTestUtils.waitForLocationChange(gBrowser, TEST_HTTP + "foo");
promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
httpBrowser.goForward();
await promiseLocation;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after history forward.");
// Check that goto history index doesn't break the affinity.
promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, TEST_HTTP);
httpBrowser.gotoIndex(0);
await promiseLocation;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after history gotoIndex.");
// Check that file:// URI load doesn't break the affinity.
promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
httpBrowser.loadURI(uriString);
await promiseLoad;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after file:// load.");
// Check that location change doesn't break the affinity.
promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
await ContentTask.spawn(httpBrowser, TEST_HTTP, uri => {
content.location = uri;
});
await promiseLoad;
await CheckBrowserInPid(httpBrowser, filePid,
"Check that http tab still in file content process after location change.");
// Check that cross-origin load does break the affinity.
promiseLoad = BrowserTestUtils.browserLoaded(httpBrowser);
httpBrowser.loadURI(TEST_CROSS_ORIGIN);
await promiseLoad;
await CheckBrowserNotInPid(httpBrowser, filePid,
"Check that http tab not in file content process after cross origin load.");
is(httpBrowser.remoteType, E10SUtils.WEB_REMOTE_TYPE,
"Check that tab now has web remote type.");
// Check that history back now remains in the web content process.
let httpPid = await ContentTask.spawn(httpBrowser, null, () => {
return Services.appinfo.processID;
});
await ContentTask.spawn(httpTab.linkedBrowser, filePid, (expectedPid) => {
is(Services.appinfo.processID, expectedPid,
"Check that new http page opened from file loaded in file content process.");
});
promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, TEST_HTTP);
httpBrowser.goBack();
await promiseLocation;
await CheckBrowserInPid(httpBrowser, httpPid,
"Check that http tab still in web content process after process switch and history back.");
// Check that history back to file:// URI switches to file content process.
promiseLocation = BrowserTestUtils.waitForLocationChange(gBrowser, uriString);
httpBrowser.goBack();
await promiseLocation;
await CheckBrowserNotInPid(httpBrowser, httpPid,
"Check that history back to file:// URI switches to file content process.");
is(httpBrowser.remoteType, E10SUtils.FILE_REMOTE_TYPE,
"Check that tab now has file remote type.");
});
});

Просмотреть файл

@ -2887,7 +2887,8 @@ var SessionStoreInternal = {
// We want to make sure that this information is passed to restoreTab
// whether or not a historyIndex is passed in. Thus, we extract it from
// the loadArguments.
reloadInFreshProcess: !!recentLoadArguments.reloadInFreshProcess,
newFrameloader: recentLoadArguments.newFrameloader,
remoteType: recentLoadArguments.remoteType,
// Make sure that SessionStore knows that this restoration is due
// to a navigation, as opposed to us restoring a closed window or tab.
restoreContentReason: RESTORE_TAB_CONTENT_REASON.NAVIGATE_AND_RESTORE,
@ -3536,18 +3537,14 @@ var SessionStoreInternal = {
NS_ASSERT(!tab.linkedBrowser.__SS_restoreState,
"must reset tab before calling restoreTab()");
let restoreImmediately = options.restoreImmediately;
let loadArguments = options.loadArguments;
let browser = tab.linkedBrowser;
let window = tab.ownerGlobal;
let tabbrowser = window.gBrowser;
let forceOnDemand = options.forceOnDemand;
let reloadInFreshProcess = options.reloadInFreshProcess;
let restoreContentReason = options.restoreContentReason;
let willRestoreImmediately = restoreImmediately ||
tabbrowser.selectedBrowser == browser ||
loadArguments;
let willRestoreImmediately = options.restoreImmediately ||
tabbrowser.selectedBrowser == browser;
let isBrowserInserted = browser.isConnected;
@ -3666,8 +3663,7 @@ var SessionStoreInternal = {
// This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but
// it ensures each window will have its selected tab loaded.
if (willRestoreImmediately) {
this.restoreTabContent(tab, loadArguments, reloadInFreshProcess,
restoreContentReason);
this.restoreTabContent(tab, options);
} else if (!forceOnDemand) {
TabRestoreQueue.add(tab);
this.restoreNextTab();
@ -3709,18 +3705,12 @@ var SessionStoreInternal = {
*
* @param aTab
* the tab to restore
* @param aLoadArguments
* optional load arguments used for loadURI()
* @param aReloadInFreshProcess
* true if we want to reload into a fresh process
* @param aReason
* The reason for why this tab content is being restored.
* Should be one of the values within RESTORE_TAB_CONTENT_REASON.
* Defaults to RESTORE_TAB_CONTENT_REASON.SET_STATE.
* @param aOptions
* optional arguments used when performing process switch during load
*/
restoreTabContent(aTab, aLoadArguments = null, aReloadInFreshProcess = false,
aReason = RESTORE_TAB_CONTENT_REASON.SET_STATE) {
if (aTab.hasAttribute("customizemode") && !aLoadArguments) {
restoreTabContent(aTab, aOptions = {}) {
let loadArguments = aOptions.loadArguments;
if (aTab.hasAttribute("customizemode") && !loadArguments) {
return;
}
@ -3731,10 +3721,10 @@ var SessionStoreInternal = {
let activeIndex = tabData.index - 1;
let activePageData = tabData.entries[activeIndex] || null;
let uri = activePageData ? activePageData.url || null : null;
if (aLoadArguments) {
uri = aLoadArguments.uri;
if (aLoadArguments.userContextId) {
browser.setAttribute("usercontextid", aLoadArguments.userContextId);
if (loadArguments) {
uri = loadArguments.uri;
if (loadArguments.userContextId) {
browser.setAttribute("usercontextid", loadArguments.userContextId);
}
}
@ -3744,16 +3734,25 @@ var SessionStoreInternal = {
// flip the remoteness of any browser that is not being displayed.
this.markTabAsRestoring(aTab);
// We need a new frameloader either if we are reloading into a fresh
// process, or we have a browser with a grouped session history (as we don't
// support restoring into browsers with grouped session histories directly).
// We need a new frameloader if we are reloading into a browser with a
// grouped session history (as we don't support restoring into browsers
// with grouped session histories directly).
let newFrameloader =
aReloadInFreshProcess || !!browser.frameLoader.groupedSHistory;
let isRemotenessUpdate =
tabbrowser.updateBrowserRemotenessByURL(browser, uri, {
freshProcess: aReloadInFreshProcess,
newFrameloader,
});
aOptions.newFrameloader || !!browser.frameLoader.groupedSHistory;
let isRemotenessUpdate;
if (aOptions.remoteType !== undefined) {
// We already have a selected remote type so we update to that.
isRemotenessUpdate =
tabbrowser.updateBrowserRemoteness(browser, !!aOptions.remoteType,
{ remoteType: aOptions.remoteType,
newFrameloader });
} else {
isRemotenessUpdate =
tabbrowser.updateBrowserRemotenessByURL(browser, uri, {
newFrameloader,
});
}
if (isRemotenessUpdate) {
// We updated the remoteness, so we need to send the history down again.
@ -3766,7 +3765,7 @@ var SessionStoreInternal = {
this._sendRestoreHistory(browser, {
tabData,
epoch,
loadArguments: aLoadArguments,
loadArguments,
isRemotenessUpdate,
});
}
@ -3778,8 +3777,10 @@ var SessionStoreInternal = {
}
browser.messageManager.sendAsyncMessage("SessionStore:restoreTabContent",
{loadArguments: aLoadArguments, isRemotenessUpdate,
reason: aReason, requestTime: Services.telemetry.msSystemNow()});
{loadArguments, isRemotenessUpdate,
reason: aOptions.restoreContentReason ||
RESTORE_TAB_CONTENT_REASON.SET_STATE,
requestTime: Services.telemetry.msSystemNow()});
},
/**

Просмотреть файл

@ -0,0 +1,20 @@
no_sccache=1
ac_add_options --with-l10n-base=../../l10n
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --with-branding=browser/branding/aurora
. $topsrcdir/build/unix/mozconfig.linux32
export MOZILLA_OFFICIAL=1
# Enable Telemetry
export MOZ_TELEMETRY_REPORTING=1
ac_add_options --disable-stdcxx-compat
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
# Bug 1283438
mk_add_options AUTOCLOBBER=
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -0,0 +1,20 @@
no_sccache=1
ac_add_options --with-l10n-base=../../l10n
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --with-branding=browser/branding/aurora
. $topsrcdir/build/unix/mozconfig.linux
export MOZILLA_OFFICIAL=1
# Enable Telemetry
export MOZ_TELEMETRY_REPORTING=1
ac_add_options --disable-stdcxx-compat
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
# Bug 1283438
mk_add_options AUTOCLOBBER=
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -0,0 +1,22 @@
. "$topsrcdir/browser/config/mozconfigs/common"
. "$topsrcdir/build/macosx/mozconfig.common"
ac_add_options --with-l10n-base=../../l10n
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --with-branding=browser/branding/aurora
if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then
ac_add_options --with-macbundlename-prefix=Firefox
fi
export MOZILLA_OFFICIAL=1
# Enable Telemetry
export MOZ_TELEMETRY_REPORTING=1
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
# Bug 1283438
mk_add_options AUTOCLOBBER=
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"

Просмотреть файл

@ -0,0 +1,19 @@
. "$topsrcdir/browser/config/mozconfigs/common"
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --with-l10n-base=../../l10n
ac_add_options --with-windows-version=603
ac_add_options --with-branding=browser/branding/aurora
export MOZILLA_OFFICIAL=1
# Enable Telemetry
export MOZ_TELEMETRY_REPORTING=1
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
# Bug 1283438
mk_add_options AUTOCLOBBER=
. $topsrcdir/build/win32/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -0,0 +1,20 @@
. "$topsrcdir/browser/config/mozconfigs/common"
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --with-l10n-base=../../l10n
ac_add_options --with-windows-version=603
ac_add_options --with-branding=browser/branding/aurora
export MOZILLA_OFFICIAL=1
# Enable Telemetry
export MOZ_TELEMETRY_REPORTING=1
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
# Bug 1283438
mk_add_options AUTOCLOBBER=
. $topsrcdir/build/win64/mozconfig.vs-latest
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,5 +1,5 @@
This is the PDF.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.8.346
Current extension version is: 1.8.363
Taken from upstream commit: 15425d5b
Taken from upstream commit: 658fb03d

Просмотреть файл

@ -12,8 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils,
PdfjsContentUtils, PdfStreamConverter */
"use strict";

Просмотреть файл

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, Services */
"use strict";

Просмотреть файл

@ -13,7 +13,6 @@
* limitations under the License.
*/
/* eslint max-len: ["error", 100] */
/* globals Components, Services */
"use strict";

Просмотреть файл

@ -12,8 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
dump, NetworkManager, PdfJsTelemetry, PdfjsContentUtils */
"use strict";

Просмотреть файл

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, Services, XPCOMUtils */
"use strict";

Просмотреть файл

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, Services, XPCOMUtils */
"use strict";

Просмотреть файл

@ -1199,78 +1199,73 @@ exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_R
var _util = __w_pdfjs_require__(0);
var DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
function DOMCanvasFactory() {}
DOMCanvasFactory.prototype = {
create: function DOMCanvasFactory_create(width, height) {
class DOMCanvasFactory {
create(width, height) {
(0, _util.assert)(width > 0 && height > 0, 'invalid canvas size');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
return {
canvas,
context
};
},
reset: function DOMCanvasFactory_reset(canvasAndContextPair, width, height) {
(0, _util.assert)(canvasAndContextPair.canvas, 'canvas is not specified');
}
reset(canvasAndContext, width, height) {
(0, _util.assert)(canvasAndContext.canvas, 'canvas is not specified');
(0, _util.assert)(width > 0 && height > 0, 'invalid canvas size');
canvasAndContextPair.canvas.width = width;
canvasAndContextPair.canvas.height = height;
},
destroy: function DOMCanvasFactory_destroy(canvasAndContextPair) {
(0, _util.assert)(canvasAndContextPair.canvas, 'canvas is not specified');
canvasAndContextPair.canvas.width = 0;
canvasAndContextPair.canvas.height = 0;
canvasAndContextPair.canvas = null;
canvasAndContextPair.context = null;
canvasAndContext.canvas.width = width;
canvasAndContext.canvas.height = height;
}
};
var DOMCMapReaderFactory = function DOMCMapReaderFactoryClosure() {
function DOMCMapReaderFactory(params) {
this.baseUrl = params.baseUrl || null;
this.isCompressed = params.isCompressed || false;
destroy(canvasAndContext) {
(0, _util.assert)(canvasAndContext.canvas, 'canvas is not specified');
canvasAndContext.canvas.width = 0;
canvasAndContext.canvas.height = 0;
canvasAndContext.canvas = null;
canvasAndContext.context = null;
}
DOMCMapReaderFactory.prototype = {
fetch(params) {
var name = params.name;
if (!name) {
return Promise.reject(new Error('CMap name must be specified.'));
}
class DOMCMapReaderFactory {
constructor({ baseUrl = null, isCompressed = false }) {
this.baseUrl = baseUrl;
this.isCompressed = isCompressed;
}
fetch({ name }) {
if (!name) {
return Promise.reject(new Error('CMap name must be specified.'));
}
return new Promise((resolve, reject) => {
let url = this.baseUrl + name + (this.isCompressed ? '.bcmap' : '');
let request = new XMLHttpRequest();
request.open('GET', url, true);
if (this.isCompressed) {
request.responseType = 'arraybuffer';
}
return new Promise((resolve, reject) => {
var url = this.baseUrl + name + (this.isCompressed ? '.bcmap' : '');
var request = new XMLHttpRequest();
request.open('GET', url, true);
if (this.isCompressed) {
request.responseType = 'arraybuffer';
request.onreadystatechange = () => {
if (request.readyState !== XMLHttpRequest.DONE) {
return;
}
request.onreadystatechange = () => {
if (request.readyState !== XMLHttpRequest.DONE) {
if (request.status === 200 || request.status === 0) {
let data;
if (this.isCompressed && request.response) {
data = new Uint8Array(request.response);
} else if (!this.isCompressed && request.responseText) {
data = (0, _util.stringToBytes)(request.responseText);
}
if (data) {
resolve({
cMapData: data,
compressionType: this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE
});
return;
}
if (request.status === 200 || request.status === 0) {
var data;
if (this.isCompressed && request.response) {
data = new Uint8Array(request.response);
} else if (!this.isCompressed && request.responseText) {
data = (0, _util.stringToBytes)(request.responseText);
}
if (data) {
resolve({
cMapData: data,
compressionType: this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE
});
return;
}
}
reject(new Error('Unable to load ' + (this.isCompressed ? 'binary ' : '') + 'CMap at: ' + url));
};
request.send(null);
});
}
};
return DOMCMapReaderFactory;
}();
}
reject(new Error('Unable to load ' + (this.isCompressed ? 'binary ' : '') + 'CMap at: ' + url));
};
request.send(null);
});
}
}
var CustomStyle = function CustomStyleClosure() {
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
var _cache = Object.create(null);
@ -3328,7 +3323,12 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
}
var params = this.params;
this.gfx = new _canvas.CanvasGraphics(params.canvasContext, this.commonObjs, this.objs, this.canvasFactory, params.imageLayer);
this.gfx.beginDrawing(params.transform, params.viewport, transparency);
this.gfx.beginDrawing({
transform: params.transform,
viewport: params.viewport,
transparency,
background: params.background
});
this.operatorListIdx = 0;
this.graphicsReady = true;
if (this.graphicsReadyCallback) {
@ -3405,8 +3405,8 @@ var _UnsupportedManager = function UnsupportedManagerClosure() {
}();
var version, build;
{
exports.version = version = '1.8.346';
exports.build = build = '15425d5b';
exports.version = version = '1.8.363';
exports.build = build = '658fb03d';
}
exports.getDocument = getDocument;
exports.LoopbackPort = LoopbackPort;
@ -4408,8 +4408,8 @@ if (!_util.globalScope.PDFJS) {
}
var PDFJS = _util.globalScope.PDFJS;
{
PDFJS.version = '1.8.346';
PDFJS.build = '15425d5b';
PDFJS.version = '1.8.363';
PDFJS.build = '658fb03d';
}
PDFJS.pdfBug = false;
if (PDFJS.verbosity !== undefined) {
@ -5060,11 +5060,11 @@ var CanvasGraphics = function CanvasGraphicsClosure() {
var NORMAL_CLIP = {};
var EO_CLIP = {};
CanvasGraphics.prototype = {
beginDrawing: function CanvasGraphics_beginDrawing(transform, viewport, transparency) {
beginDrawing({ transform, viewport, transparency, background = null }) {
var width = this.ctx.canvas.width;
var height = this.ctx.canvas.height;
this.ctx.save();
this.ctx.fillStyle = 'rgb(255, 255, 255)';
this.ctx.fillStyle = background || 'rgb(255, 255, 255)';
this.ctx.fillRect(0, 0, width, height);
this.ctx.restore();
if (transparency) {
@ -6723,8 +6723,8 @@ exports.TilingPattern = TilingPattern;
"use strict";
var pdfjsVersion = '1.8.346';
var pdfjsBuild = '15425d5b';
var pdfjsVersion = '1.8.363';
var pdfjsBuild = '658fb03d';
var pdfjsSharedUtil = __w_pdfjs_require__(0);
var pdfjsDisplayGlobal = __w_pdfjs_require__(8);
var pdfjsDisplayAPI = __w_pdfjs_require__(3);

Просмотреть файл

@ -16738,6 +16738,12 @@ var PartialEvaluator = function PartialEvaluatorClosure() {
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE && !softMask && !mask && image instanceof JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources)) {
operatorList.addOp(OPS.paintJpegXObject, args);
this.handler.send('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]);
if (cacheKey) {
imageCache[cacheKey] = {
fn: OPS.paintJpegXObject,
args
};
}
return;
}
var nativeImageDecoder = null;
@ -36639,8 +36645,8 @@ exports.Type1Parser = Type1Parser;
"use strict";
var pdfjsVersion = '1.8.346';
var pdfjsBuild = '15425d5b';
var pdfjsVersion = '1.8.363';
var pdfjsBuild = '658fb03d';
var pdfjsCoreWorker = __w_pdfjs_require__(17);
;
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;

Просмотреть файл

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, PdfJs, Services */
"use strict";

Просмотреть файл

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Components, PdfjsContentUtils */
"use strict";

Просмотреть файл

@ -4852,16 +4852,15 @@ var PDFPageView = function PDFPageViewClosure() {
getPagePoint: function PDFPageView_getPagePoint(x, y) {
return this.viewport.convertToPdfPoint(x, y);
},
draw: function PDFPageView_draw() {
draw() {
if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) {
console.error('Must be in new state before drawing');
this.reset();
}
this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
var self = this;
var pdfPage = this.pdfPage;
var div = this.div;
var canvasWrapper = document.createElement('div');
let pdfPage = this.pdfPage;
let div = this.div;
let canvasWrapper = document.createElement('div');
canvasWrapper.style.width = div.style.width;
canvasWrapper.style.height = div.style.height;
canvasWrapper.classList.add('canvasWrapper');
@ -4870,10 +4869,9 @@ var PDFPageView = function PDFPageViewClosure() {
} else {
div.appendChild(canvasWrapper);
}
var textLayerDiv = null;
var textLayer = null;
let textLayer = null;
if (this.textLayerFactory) {
textLayerDiv = document.createElement('div');
let textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
@ -4885,13 +4883,13 @@ var PDFPageView = function PDFPageViewClosure() {
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.enhanceTextSelection);
}
this.textLayer = textLayer;
var renderContinueCallback = null;
let renderContinueCallback = null;
if (this.renderingQueue) {
renderContinueCallback = function renderContinueCallback(cont) {
if (!self.renderingQueue.isHighestPriority(self)) {
self.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED;
self.resume = function resumeCallback() {
self.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
renderContinueCallback = cont => {
if (!this.renderingQueue.isHighestPriority(this)) {
this.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED;
this.resume = () => {
this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
cont();
};
return;
@ -4899,28 +4897,28 @@ var PDFPageView = function PDFPageViewClosure() {
cont();
};
}
var finishPaintTask = function finishPaintTask(error) {
if (paintTask === self.paintTask) {
self.paintTask = null;
let finishPaintTask = error => {
if (paintTask === this.paintTask) {
this.paintTask = null;
}
if (error instanceof _pdfjs.RenderingCancelledException) {
self.error = null;
this.error = null;
return Promise.resolve(undefined);
}
self.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED;
if (self.loadingIconDiv) {
div.removeChild(self.loadingIconDiv);
delete self.loadingIconDiv;
this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED;
if (this.loadingIconDiv) {
div.removeChild(this.loadingIconDiv);
delete this.loadingIconDiv;
}
self._resetZoomLayer(true);
self.error = error;
self.stats = pdfPage.stats;
if (self.onAfterDraw) {
self.onAfterDraw();
this._resetZoomLayer(true);
this.error = error;
this.stats = pdfPage.stats;
if (this.onAfterDraw) {
this.onAfterDraw();
}
self.eventBus.dispatch('pagerendered', {
source: self,
pageNumber: self.id,
this.eventBus.dispatch('pagerendered', {
source: this,
pageNumber: this.id,
cssTransform: false
});
if (error) {
@ -4928,10 +4926,10 @@ var PDFPageView = function PDFPageViewClosure() {
}
return Promise.resolve(undefined);
};
var paintTask = this.renderer === _ui_utils.RendererType.SVG ? this.paintOnSvg(canvasWrapper) : this.paintOnCanvas(canvasWrapper);
let paintTask = this.renderer === _ui_utils.RendererType.SVG ? this.paintOnSvg(canvasWrapper) : this.paintOnCanvas(canvasWrapper);
paintTask.onRenderContinue = renderContinueCallback;
this.paintTask = paintTask;
var resultPromise = paintTask.promise.then(function () {
let resultPromise = paintTask.promise.then(function () {
return finishPaintTask(null).then(function () {
if (textLayer) {
pdfPage.getTextContent({ normalizeWhitespace: true }).then(function textContentResolved(textContent) {
@ -5024,16 +5022,16 @@ var PDFPageView = function PDFPageViewClosure() {
cont();
}
};
renderTask.promise.then(function pdfPageRenderCallback() {
renderTask.promise.then(function () {
showCanvas();
renderCapability.resolve(undefined);
}, function pdfPageRenderError(error) {
}, function (error) {
showCanvas();
renderCapability.reject(error);
});
return result;
},
paintOnSvg: function PDFPageView_paintOnSvg(wrapper) {
paintOnSvg(wrapper) {
return {
promise: Promise.reject(new Error('SVG rendering is not supported.')),
onRenderContinue(cont) {},
@ -5845,53 +5843,52 @@ var PDFThumbnailView = function PDFThumbnailViewClosure() {
this.canvas.height = 0;
delete this.canvas;
},
draw: function PDFThumbnailView_draw() {
draw() {
if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) {
console.error('Must be in new state before drawing');
return Promise.resolve(undefined);
}
this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
var renderCapability = (0, _pdfjs.createPromiseCapability)();
var self = this;
function thumbnailDrawCallback(error) {
if (renderTask === self.renderTask) {
self.renderTask = null;
let renderCapability = (0, _pdfjs.createPromiseCapability)();
let finishRenderTask = error => {
if (renderTask === this.renderTask) {
this.renderTask = null;
}
if (error instanceof _pdfjs.RenderingCancelledException) {
renderCapability.resolve(undefined);
return;
}
self.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED;
self._convertCanvasToImage();
this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED;
this._convertCanvasToImage();
if (!error) {
renderCapability.resolve(undefined);
} else {
renderCapability.reject(error);
}
}
var ctx = this._getPageDrawContext();
var drawViewport = this.viewport.clone({ scale: this.scale });
var renderContinueCallback = function renderContinueCallback(cont) {
if (!self.renderingQueue.isHighestPriority(self)) {
self.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED;
self.resume = function resumeCallback() {
self.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
};
let ctx = this._getPageDrawContext();
let drawViewport = this.viewport.clone({ scale: this.scale });
let renderContinueCallback = cont => {
if (!this.renderingQueue.isHighestPriority(this)) {
this.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED;
this.resume = () => {
this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING;
cont();
};
return;
}
cont();
};
var renderContext = {
let renderContext = {
canvasContext: ctx,
viewport: drawViewport
};
var renderTask = this.renderTask = this.pdfPage.render(renderContext);
let renderTask = this.renderTask = this.pdfPage.render(renderContext);
renderTask.onContinue = renderContinueCallback;
renderTask.promise.then(function pdfPageRenderCallback() {
thumbnailDrawCallback(null);
}, function pdfPageRenderError(error) {
thumbnailDrawCallback(error);
renderTask.promise.then(function () {
finishRenderTask(null);
}, function (error) {
finishRenderTask(error);
});
return renderCapability.promise;
},

Просмотреть файл

@ -46,7 +46,7 @@ const EXTENSION_REMOTE_TYPE = "extension";
const LARGE_ALLOCATION_REMOTE_TYPE = "webLargeAllocation";
const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
function validatedWebRemoteType(aPreferredRemoteType) {
function validatedWebRemoteType(aPreferredRemoteType, aTargetUri, aCurrentUri) {
if (!aPreferredRemoteType) {
return WEB_REMOTE_TYPE;
}
@ -57,7 +57,20 @@ function validatedWebRemoteType(aPreferredRemoteType) {
if (allowLinkedWebInFileUriProcess &&
aPreferredRemoteType == FILE_REMOTE_TYPE) {
return aPreferredRemoteType;
// If aCurrentUri is passed then we should only allow FILE_REMOTE_TYPE
// when it is same origin as target.
if (aCurrentUri) {
const sm = Services.scriptSecurityManager;
try {
// checkSameOriginURI throws when not same origin.
sm.checkSameOriginURI(aCurrentUri, aTargetUri, false);
return FILE_REMOTE_TYPE;
} catch (e) {
return WEB_REMOTE_TYPE;
}
}
return FILE_REMOTE_TYPE;
}
return WEB_REMOTE_TYPE;
@ -79,15 +92,11 @@ this.E10SUtils = {
getRemoteTypeForURI(aURL, aMultiProcess,
aPreferredRemoteType = DEFAULT_REMOTE_TYPE,
aLargeAllocation = false) {
aCurrentUri) {
if (!aMultiProcess) {
return NOT_REMOTE;
}
if (aLargeAllocation) {
return LARGE_ALLOCATION_REMOTE_TYPE;
}
// loadURI in browser.xml treats null as about:blank
if (!aURL) {
aURL = "about:blank";
@ -95,7 +104,7 @@ this.E10SUtils = {
let uri;
try {
uri = Services.io.newURI(aURL);
uri = Services.uriFixup.createFixupURI(aURL, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
} catch (e) {
// If we have an invalid URI, it's still possible that it might get
// fixed-up into a valid URI later on. However, we don't want to return
@ -105,11 +114,12 @@ this.E10SUtils = {
}
return this.getRemoteTypeForURIObject(uri, aMultiProcess,
aPreferredRemoteType);
aPreferredRemoteType, aCurrentUri);
},
getRemoteTypeForURIObject(aURI, aMultiProcess,
aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
aPreferredRemoteType = DEFAULT_REMOTE_TYPE,
aCurrentUri) {
if (!aMultiProcess) {
return NOT_REMOTE;
}
@ -182,10 +192,11 @@ this.E10SUtils = {
if (aURI instanceof Ci.nsINestedURI) {
let innerURI = aURI.QueryInterface(Ci.nsINestedURI).innerURI;
return this.getRemoteTypeForURIObject(innerURI, aMultiProcess,
aPreferredRemoteType);
aPreferredRemoteType,
aCurrentUri);
}
return validatedWebRemoteType(aPreferredRemoteType);
return validatedWebRemoteType(aPreferredRemoteType, aURI, aCurrentUri);
}
},
@ -210,6 +221,22 @@ this.E10SUtils = {
return false;
}
// Allow history load if loaded in this process before.
let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation);
let sessionHistory = webNav.sessionHistory;
let requestedIndex = sessionHistory.requestedIndex;
if (requestedIndex >= 0) {
if (sessionHistory.getEntryAtIndex(requestedIndex, false).loadedInThisProcess) {
return true;
}
// If not originally loaded in this process allow it if the URI would
// normally be allowed to load in this process by default.
let remoteType = Services.appinfo.remoteType;
return remoteType ==
this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI);
}
// If the URI can be loaded in the current process then continue
return this.shouldLoadURIInThisProcess(aURI);
},

Просмотреть файл

@ -275,9 +275,9 @@ menuitem.bookmark-item {
--urlbar-border-color: rgba(0,0,0,.3);
}
%ifdef MOZ_PHOTON_THEME
%include ../shared/urlbar-searchbar.inc.css
%include ../shared/location-search-bar.inc.css
%ifdef MOZ_PHOTON_THEME
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
@ -347,10 +347,6 @@ menuitem.bookmark-item {
opacity: 0;
}
#urlbar-container {
-moz-box-align: center;
}
%ifndef MOZ_PHOTON_THEME
@conditionalForwardWithUrlbar@ > #urlbar {
border-inline-start: none;
@ -435,15 +431,6 @@ menuitem.bookmark-item {
background-color: var(--arrowpanel-dimmed-further);
}
#urlbar-search-splitter {
/* The splitter width should equal the location and search bars' combined
neighboring margin and border width. */
width: 8px;
margin: 0 -4px;
position: relative;
-moz-appearance: none;
}
#urlbar-display-box {
margin-top: -1px;
margin-bottom: -1px;

Просмотреть файл

@ -520,6 +520,8 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
/* ::::: nav-bar-inner ::::: */
%include ../shared/urlbar-searchbar.inc.css
%ifdef MOZ_PHOTON_THEME
#main-window {
@ -528,8 +530,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
--urlbar-background-color: -moz-field;
}
%include ../shared/location-search-bar.inc.css
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
border-color: -moz-mac-focusring;
@ -583,10 +583,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
box-shadow: var(--focus-ring-box-shadow);
}
#urlbar-container {
-moz-box-align: center;
}
#urlbar {
border-radius: var(--toolbarbutton-border-radius);
}
@ -755,14 +751,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
background-color: var(--arrowpanel-dimmed-further);
}
#urlbar-search-splitter {
min-width: 8px;
width: 8px;
background-image: none;
margin: 0 -4px;
position: relative;
}
#search-container {
min-width: calc(54px + 11ch);
}

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
%ifdef MOZ_PHOTON_THEME
#urlbar,
.searchbar-textbox {
-moz-appearance: none;
@ -11,7 +13,7 @@
border-radius: var(--toolbarbutton-border-radius);
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);
padding: 0;
margin: 0 2px;
margin: 0 5px;
min-height: 30px;
}
@ -34,6 +36,20 @@
box-shadow: 0 1px 6px hsla(0, 0%, 0%, .1), 0 0 1px 0 rgba(0, 0, 0, .1);
}
%endif
#urlbar-container {
-moz-box-align: center;
}
#urlbar-search-splitter {
/* The splitter width should equal the location and search bars' combined
neighboring margin and border width. */
min-width: 12px;
margin: 0 -6px;
position: relative;
border: none;
background: transparent;
-moz-appearance: none;
}

Просмотреть файл

@ -662,6 +662,8 @@ toolbar[brighttext] #close-button {
--urlbar-border-color: var(--toolbarbutton-hover-bordercolor);
}
%include ../shared/urlbar-searchbar.inc.css
%ifdef MOZ_PHOTON_THEME
@media (-moz-windows-default-theme) {
@ -672,7 +674,10 @@ toolbar[brighttext] #close-button {
}
}
%include ../shared/location-search-bar.inc.css
#urlbar,
.searchbar-textbox {
font-size: 1.15em;
}
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
@ -752,9 +757,7 @@ toolbar[brighttext] #close-button {
#urlbar,
.searchbar-textbox {
font-size: 1.15em;
%ifndef MOZ_PHOTON_THEME
min-height: 28px;
%endif
}
:root {
@ -827,10 +830,6 @@ html|*.urlbar-input:-moz-lwtheme::placeholder,
color: #777;
}
#urlbar-container {
-moz-box-align: center;
}
.urlbar-textbox-container {
-moz-box-align: stretch;
}
@ -903,16 +902,6 @@ html|*.urlbar-input:-moz-lwtheme::placeholder,
background-color: var(--arrowpanel-dimmed-further);
}
#urlbar-search-splitter {
/* The splitter width should equal the location and search bars' combined
neighboring margin and border width. */
min-width: 8px;
margin: 0 -4px;
position: relative;
border: none;
background: transparent;
}
.urlbar-display {
margin-top: 0;
margin-bottom: 0;

Просмотреть файл

@ -328,6 +328,12 @@ interface nsISHEntry : nsISupports
*/
attribute boolean scrollRestorationIsManual;
/**
* Flag to indicate that the history entry was originally loaded in the
* current process. This flag does not survive a browser process switch.
*/
readonly attribute boolean loadedInThisProcess;
/**
* Set the session history it belongs to. It's only set on root entries.
*/

Просмотреть файл

@ -37,6 +37,7 @@ nsSHEntry::nsSHEntry()
, mURIWasModified(false)
, mIsSrcdocEntry(false)
, mScrollRestorationIsManual(false)
, mLoadedInThisProcess(false)
{
}
@ -60,6 +61,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
, mURIWasModified(aOther.mURIWasModified)
, mIsSrcdocEntry(aOther.mIsSrcdocEntry)
, mScrollRestorationIsManual(false)
, mLoadedInThisProcess(aOther.mLoadedInThisProcess)
{
}
@ -460,6 +462,8 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
mIsSrcdocEntry = false;
mSrcdocData = NullString();
mLoadedInThisProcess = true;
return NS_OK;
}
@ -645,6 +649,13 @@ nsSHEntry::SetScrollRestorationIsManual(bool aIsManual)
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLoadedInThisProcess(bool* aLoadedInThisProcess)
{
*aLoadedInThisProcess = mLoadedInThisProcess;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetChildCount(int32_t* aCount)
{

Просмотреть файл

@ -64,6 +64,7 @@ private:
bool mURIWasModified;
bool mIsSrcdocEntry;
bool mScrollRestorationIsManual;
bool mLoadedInThisProcess;
};
#endif /* nsSHEntry_h */

Просмотреть файл

@ -116,14 +116,14 @@
// trace these and resolve a promise with the path taken by the
// script loader.
//
// Setting dom.script_loader.force_bytecode_cache causes the
// Setting dom.script_loader.bytecode_cache.eager causes the
// nsScriptLoadRequest to force all the conditions necessary to make a
// script be saved as bytecode in the alternate data storage provided
// by the channel (necko cache).
await SpecialPowers.pushPrefEnv({set: [
['dom.script_loader.bytecode_cache.enabled', true],
['dom.expose_test_interfaces', true],
['dom.script_loader.force_bytecode_cache', true]
['dom.script_loader.bytecode_cache.eager', true]
]});
// Load the test page, and verify that the code path taken by the
@ -174,7 +174,7 @@
await SpecialPowers.pushPrefEnv({set: [
['dom.script_loader.bytecode_cache.enabled', true],
['dom.expose_test_interfaces', true],
['dom.script_loader.force_bytecode_cache', true]
['dom.script_loader.bytecode_cache.eager', true]
]});
// The test page add a new script which generate a "ping" event, which

Просмотреть файл

@ -372,10 +372,11 @@ HTMLOptionElement::GetSelect()
already_AddRefed<HTMLOptionElement>
HTMLOptionElement::Option(const GlobalObject& aGlobal,
const Optional<nsAString>& aText,
const nsAString& aText,
const Optional<nsAString>& aValue,
const Optional<bool>& aDefaultSelected,
const Optional<bool>& aSelected, ErrorResult& aError)
bool aDefaultSelected,
bool aSelected,
ErrorResult& aError)
{
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aGlobal.GetAsSupports());
nsIDocument* doc;
@ -391,45 +392,43 @@ HTMLOptionElement::Option(const GlobalObject& aGlobal,
RefPtr<HTMLOptionElement> option = new HTMLOptionElement(nodeInfo);
if (aText.WasPassed()) {
if (!aText.IsEmpty()) {
// Create a new text node and append it to the option
RefPtr<nsTextNode> textContent =
new nsTextNode(option->NodeInfo()->NodeInfoManager());
textContent->SetText(aText.Value(), false);
textContent->SetText(aText, false);
aError = option->AppendChildTo(textContent, false);
if (aError.Failed()) {
return nullptr;
}
}
if (aValue.WasPassed()) {
// Set the value attribute for this element. We're calling SetAttr
// directly because we want to pass aNotify == false.
aError = option->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
aValue.Value(), false);
if (aError.Failed()) {
return nullptr;
}
if (aValue.WasPassed()) {
// Set the value attribute for this element. We're calling SetAttr
// directly because we want to pass aNotify == false.
aError = option->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
aValue.Value(), false);
if (aError.Failed()) {
return nullptr;
}
}
if (aDefaultSelected.WasPassed()) {
if (aDefaultSelected.Value()) {
// We're calling SetAttr directly because we want to pass
// aNotify == false.
aError = option->SetAttr(kNameSpaceID_None, nsGkAtoms::selected,
EmptyString(), false);
if (aError.Failed()) {
return nullptr;
}
}
if (aDefaultSelected) {
// We're calling SetAttr directly because we want to pass
// aNotify == false.
aError = option->SetAttr(kNameSpaceID_None, nsGkAtoms::selected,
EmptyString(), false);
if (aError.Failed()) {
return nullptr;
}
}
if (aSelected.WasPassed()) {
option->SetSelected(aSelected.Value(), aError);
if (aError.Failed()) {
return nullptr;
}
}
}
if (aSelected) {
option->SetSelected(true, aError);
if (aError.Failed()) {
return nullptr;
}
}

Просмотреть файл

@ -25,10 +25,11 @@ public:
static already_AddRefed<HTMLOptionElement>
Option(const GlobalObject& aGlobal,
const Optional<nsAString>& aText,
const nsAString& aText,
const Optional<nsAString>& aValue,
const Optional<bool>& aDefaultSelected,
const Optional<bool>& aSelected, ErrorResult& aError);
bool aDefaultSelected,
bool aSelected,
ErrorResult& aError);
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLOptionElement, option)

Просмотреть файл

@ -6,6 +6,9 @@ support-files =
file_bug649778.html^headers^
file_fullscreen-api-keys.html
file_content_contextmenu.html
form_data_file.bin
form_data_file.txt
form_submit_server.sjs
head.js
[browser_bug592641.js]
@ -19,6 +22,7 @@ support-files =
file_bug1108547-3.html
[browser_content_contextmenu_userinput.js]
[browser_DOMDocElementInserted.js]
[browser_form_post_from_file_to_http.js]
[browser_fullscreen-api-keys.js]
tags = fullscreen
[browser_fullscreen-contextmenu-esc.js]

Просмотреть файл

@ -0,0 +1,105 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
const TEST_HTTP_POST =
"http://example.org/browser/dom/html/test/form_submit_server.sjs";
// Test for bug 1351358.
add_task(async function() {
// Create file URI and test data file paths.
let testFile = getChromeDir(getResolvedURI(gTestPath));
testFile.append("dummy_page.html");
const fileUriString = Services.io.newFileURI(testFile).spec;
let filePaths = [];
testFile.leafName = "form_data_file.txt";
filePaths.push(testFile.path);
testFile.leafName = "form_data_file.bin";
filePaths.push(testFile.path);
// Open file:// page tab in which to run the test.
await BrowserTestUtils.withNewTab(fileUriString, async function(fileBrowser) {
// Create a form to post to server that writes posted data into body as JSON.
let promiseLoad = BrowserTestUtils.browserLoaded(fileBrowser, false,
TEST_HTTP_POST);
await ContentTask.spawn(fileBrowser, [TEST_HTTP_POST, filePaths],
([actionUri, filePaths]) => {
Components.utils.importGlobalProperties(["File"]);
let doc = content.document;
let form = doc.body.appendChild(doc.createElement("form"));
form.action = actionUri;
form.method = "POST";
form.enctype = "multipart/form-data";
let inputText = form.appendChild(doc.createElement("input"));
inputText.type = "text";
inputText.name = "text";
inputText.value = "posted";
let inputCheckboxOn = form.appendChild(doc.createElement("input"));
inputCheckboxOn.type = "checkbox";
inputCheckboxOn.name = "checked";
inputCheckboxOn.checked = true;
let inputCheckboxOff = form.appendChild(doc.createElement("input"));
inputCheckboxOff.type = "checkbox";
inputCheckboxOff.name = "unchecked";
inputCheckboxOff.checked = false;
let inputFile = form.appendChild(doc.createElement("input"));
inputFile.type = "file";
inputFile.name = "file";
let fileList = [];
let promises = [];
for (let path of filePaths) {
promises.push(File.createFromFileName(path).then(file => {
fileList.push(file);
}));
}
Promise.all(promises).then(() => {
inputFile.mozSetFileArray(fileList);
form.submit();
});
});
let href = await promiseLoad;
is(href, TEST_HTTP_POST,
"Check that the loaded page is the one to which we posted.");
let binContentType;
if (AppConstants.platform == "macosx") {
binContentType = "application/macbinary";
} else {
binContentType = "application/octet-stream";
}
await ContentTask.spawn(fileBrowser, { binContentType }, (args) => {
let data = JSON.parse(content.document.body.textContent);
is(data[0].headers["Content-Disposition"], "form-data; name=\"text\"",
"Check text input Content-Disposition");
is(data[0].body, "posted", "Check text input body");
is(data[1].headers["Content-Disposition"], "form-data; name=\"checked\"",
"Check checkbox input Content-Disposition");
is(data[1].body, "on", "Check checkbox input body");
// Note that unchecked checkbox details are not sent.
is(data[2].headers["Content-Disposition"],
"form-data; name=\"file\"; filename=\"form_data_file.txt\"",
"Check text file input Content-Disposition");
is(data[2].headers["Content-Type"], "text/plain",
"Check text file input Content-Type");
is(data[2].body, "1234\n", "Check text file input body");
is(data[3].headers["Content-Disposition"],
"form-data; name=\"file\"; filename=\"form_data_file.bin\"",
"Check binary file input Content-Disposition");
is(data[3].headers["Content-Type"], args.binContentType,
"Check binary file input Content-Type");
is(data[3].body, "\u0001\u0002\u0003\u0004\n",
"Check binary file input body");
});
});
});

Просмотреть файл

@ -0,0 +1 @@


Просмотреть файл

@ -0,0 +1 @@
1234

Просмотреть файл

@ -818,6 +818,21 @@ ScriptLoader::IsBytecodeCacheEnabled()
return sExposeTestInterfaceEnabled;
}
/* static */ bool
ScriptLoader::IsEagerBytecodeCache()
{
// When testing, we want to force use of the bytecode cache.
static bool sEagerBytecodeCache = false;
static bool sForceBytecodeCachePrefCached = false;
if (!sForceBytecodeCachePrefCached) {
sForceBytecodeCachePrefCached = true;
Preferences::AddBoolVarCache(&sEagerBytecodeCache,
"dom.script_loader.bytecode_cache.eager",
false);
}
return sEagerBytecodeCache;
}
nsresult
ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest)
{
@ -1864,19 +1879,10 @@ ScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
aOptions->setElement(&elementVal.toObject());
}
// When testing, we want to force use of the bytecode cache.
static bool sForceBytecodeCacheEnabled = false;
static bool sForceBytecodeCachePrefCached = false;
if (!sForceBytecodeCachePrefCached) {
sForceBytecodeCachePrefCached = true;
Preferences::AddBoolVarCache(&sForceBytecodeCacheEnabled,
"dom.script_loader.force_bytecode_cache",
false);
}
// At the moment, the bytecode cache is only triggered if a script is large
// enough to be parsed out of the main thread. Thus, for testing purposes, we
// force parsing any script out of the main thread.
if (sForceBytecodeCacheEnabled) {
if (IsEagerBytecodeCache()) {
aOptions->forceAsync = true;
}

Просмотреть файл

@ -471,6 +471,9 @@ private:
static bool
IsBytecodeCacheEnabled();
static bool
IsEagerBytecodeCache();
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);

Просмотреть файл

@ -345,6 +345,57 @@ function* largeAllocSuccessTests() {
});
});
// Opening a window from the large-allocation window should prevent the
// process switch with reload.
yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
info("Starting test 6a");
let pid1 = yield getPID(aBrowser);
is(false, yield getInLAProc(aBrowser));
let ready = Promise.all([expectProcessCreated(),
BrowserTestUtils.browserLoaded(aBrowser)]);
yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
content.document.location = TEST_URI;
});
yield ready;
let pid2 = yield getPID(aBrowser);
isnot(pid1, pid2, "PIDs 1 and 2 should not match");
is(true, yield getInLAProc(aBrowser));
let stopExpectNoProcess = expectNoProcess();
let firstTab = gBrowser.selectedTab;
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, "about:blank");
yield ContentTask.spawn(aBrowser, null, () => {
this.__newWindow = content.window.open("about:blank");
});
yield promiseTabOpened;
if (firstTab != gBrowser.selectedTab) {
firstTab = yield BrowserTestUtils.switchTab(gBrowser, firstTab);
aBrowser = firstTab.linkedBrowser;
}
let promiseLoad = BrowserTestUtils.browserLoaded(aBrowser);
document.getElementById("reload-button").doCommand();
yield promiseLoad;
let pid3 = yield getPID(aBrowser);
is(pid3, pid2, "PIDs 2 and 3 should match");
is(true, yield getInLAProc(aBrowser));
stopExpectNoProcess();
yield ContentTask.spawn(aBrowser, null, () => {
ok(this.__newWindow, "The window should have been stored");
this.__newWindow.close();
});
});
// Try dragging the tab into a new window when not at the maximum number of
// Large-Allocation processes.
yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {

Просмотреть файл

@ -11,7 +11,7 @@
* and create derivative works of this document.
*/
[HTMLConstructor, NamedConstructor=Option(optional DOMString text, optional DOMString value, optional boolean defaultSelected, optional boolean selected)]
[HTMLConstructor, NamedConstructor=Option(optional DOMString text = "", optional DOMString value, optional boolean defaultSelected = false, optional boolean selected = false)]
interface HTMLOptionElement : HTMLElement {
[SetterThrows]
attribute boolean disabled;

Просмотреть файл

@ -2948,7 +2948,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
mIsMappedArrayBuffer = false;
if (mResponseType == XMLHttpRequestResponseType::Arraybuffer &&
Preferences::GetBool("dom.mapped_arraybuffer.enabled", true)) {
IsMappedArrayBufferEnabled()) {
nsCOMPtr<nsIURI> uri;
nsAutoCString scheme;
@ -3049,6 +3049,40 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
return rv;
}
/* static */
bool
XMLHttpRequestMainThread::IsMappedArrayBufferEnabled()
{
static bool sMappedArrayBufferAdded = false;
static bool sIsMappedArrayBufferEnabled;
if (!sMappedArrayBufferAdded) {
Preferences::AddBoolVarCache(&sIsMappedArrayBufferEnabled,
"dom.mapped_arraybuffer.enabled",
true);
sMappedArrayBufferAdded = true;
}
return sIsMappedArrayBufferEnabled;
}
/* static */
bool
XMLHttpRequestMainThread::IsLowercaseResponseHeader()
{
static bool sLowercaseResponseHeaderAdded = false;
static bool sIsLowercaseResponseHeaderEnabled;
if (!sLowercaseResponseHeaderAdded) {
Preferences::AddBoolVarCache(&sIsLowercaseResponseHeaderEnabled,
"dom.xhr.lowercase_header.enabled",
false);
sLowercaseResponseHeaderAdded = true;
}
return sIsLowercaseResponseHeaderEnabled;
}
// http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-setrequestheader
NS_IMETHODIMP
XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
@ -3767,7 +3801,7 @@ NS_IMETHODIMP XMLHttpRequestMainThread::
nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
{
if (mXHR.IsSafeHeader(header, mHttpChannel)) {
if (!Preferences::GetBool("dom.xhr.lowercase_header.enabled", false)) {
if (!IsLowercaseResponseHeader()) {
if(!mHeaderList.InsertElementSorted(HeaderEntry(header, value),
fallible)) {
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -306,6 +306,14 @@ private:
void UnsuppressEventHandlingAndResume();
// Check pref "dom.mapped_arraybuffer.enabled" to make sure ArrayBuffer is
// supported.
static bool IsMappedArrayBufferEnabled();
// Check pref "dom.xhr.lowercase_header.enabled" to make sure lowercased
// response header is supported.
static bool IsLowercaseResponseHeader();
public:
virtual void
Send(JSContext* /*aCx*/, ErrorResult& aRv) override

Просмотреть файл

@ -31,6 +31,12 @@
#include "mozilla/DebugOnly.h"
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
#ifndef MOZ_ENABLE_FREETYPE
#define MOZ_ENABLE_FREETYPE
#endif
#endif
struct _cairo_surface;
typedef _cairo_surface cairo_surface_t;
@ -1618,6 +1624,9 @@ public:
static void SetFTLibrary(FT_Library aFTLibrary);
static FT_Library GetFTLibrary();
static FT_Library NewFTLibrary();
static void ReleaseFTLibrary(FT_Library aFTLibrary);
static FT_Face NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex);
static FT_Face NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex);
static void ReleaseFTFace(FT_Face aFace);

Просмотреть файл

@ -662,6 +662,22 @@ Factory::GetFTLibrary()
return mFTLibrary;
}
FT_Library
Factory::NewFTLibrary()
{
FT_Library library;
if (FT_Init_FreeType(&library) != FT_Err_Ok) {
return nullptr;
}
return library;
}
void
Factory::ReleaseFTLibrary(FT_Library aFTLibrary)
{
FT_Done_FreeType(aFTLibrary);
}
FT_Face
Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex)
{

Просмотреть файл

@ -14,9 +14,6 @@
#include <iostream>
#ifdef MOZ_ENABLE_FREETYPE
#include "ft2build.h"
#include FT_FREETYPE_H
#include "mozilla/ThreadLocal.h"
#endif
@ -56,17 +53,19 @@ static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
return false;
}
void* fontContext = nullptr;
#ifdef MOZ_ENABLE_FREETYPE
if (!sFTLibrary.init()) {
return false;
}
if (!sFTLibrary.get()) {
FT_Library library;
if (FT_Init_FreeType(&library) != FT_Err_Ok) {
FT_Library library = gfx::Factory::NewFTLibrary();
if (!library) {
return false;
}
sFTLibrary.set(library);
}
fontContext = sFTLibrary.get();
#endif
// In bindings.rs we allocate a buffer filled with opaque white.
@ -88,11 +87,7 @@ static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
InMemoryStreamBuffer streamBuffer(aBlob);
std::istream stream(&streamBuffer);
#ifdef MOZ_ENABLE_FREETYPE
gfx::InlineTranslator translator(dt, sFTLibrary.get());
#else
gfx::InlineTranslator translator(dt);
#endif
gfx::InlineTranslator translator(dt, fontContext);
auto ret = translator.TranslateRecording(stream);

Просмотреть файл

@ -37,10 +37,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
'RenderMacIOSurfaceTextureHostOGL.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3'):
DEFINES['MOZ_ENABLE_FREETYPE'] = True
CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -1070,13 +1070,21 @@ class HashTable : private AllocPolicy
bool rekeyed;
bool removed;
/* Not copyable. */
// Enum is movable but not copyable.
Enum(const Enum&) = delete;
void operator=(const Enum&) = delete;
public:
template<class Map> explicit
Enum(Map& map) : Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {}
template<class Map>
explicit Enum(Map& map)
: Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {}
MOZ_IMPLICIT Enum(Enum&& other)
: Range(other), table_(other.table_), rekeyed(other.rekeyed), removed(other.removed)
{
other.rekeyed = false;
other.removed = false;
}
// Removes the |front()| element from the table, leaving |front()|
// invalid until the next call to |popFront()|. For example:

Просмотреть файл

@ -28,6 +28,11 @@ const dataId = 11;
// User-defined section names
const nameName = "name";
// Name section name types
const nameTypeModule = 0;
const nameTypeFunction = 1;
const nameTypeLocal = 2;
// Type codes
const I32Code = 0x7f;
const I64Code = 0x7e;

Просмотреть файл

@ -232,20 +232,35 @@ function elemSection(elemArrays) {
return { name: elemId, body };
}
function nameSection(elems) {
function nameSection(moduleName, funcNames) {
var body = [];
body.push(...string(nameName));
body.push(...varU32(elems.length));
for (let fn of elems) {
body.push(...encodedString(fn.name, fn.nameLen));
if (!fn.locals) {
body.push(...varU32(0));
continue;
}
body.push(...varU32(fn.locals.length));
for (let local of fn.locals)
body.push(...encodedString(local.name, local.nameLen));
if (moduleName) {
body.push(...varU32(nameTypeModule));
var subsection = encodedString(moduleName);
body.push(...varU32(subsection.length));
body.push(...subsection);
}
if (funcNames) {
body.push(...varU32(nameTypeFunction));
var subsection = varU32(funcNames.length);
var funcIndex = 0;
for (let f of funcNames) {
subsection.push(...varU32(f.index ? f.index : funcIndex));
subsection.push(...encodedString(f.name, f.nameLen));
funcIndex++;
}
body.push(...varU32(subsection.length));
body.push(...subsection);
}
return { name: userDefinedId, body };
}
@ -380,7 +395,7 @@ wasmEval(moduleWithSections([tooBigNameSection]));
var customDefSec = customSection("wee", 42, 13);
var declSec = declSection([0]);
var bodySec = bodySection([v2vBody]);
var nameSec = nameSection([{name:'hi'}]);
var nameSec = nameSection(null, [{name:'hi'}]);
wasmEval(moduleWithSections([customDefSec, v2vSigSection, declSec, bodySec]));
wasmEval(moduleWithSections([v2vSigSection, customDefSec, declSec, bodySec]));
wasmEval(moduleWithSections([v2vSigSection, declSec, customDefSec, bodySec]));
@ -429,7 +444,7 @@ for (var i = FirstInvalidOpcode; i <= 0xff; i++) {
}
// Checking stack trace.
function runStackTraceTest(namesContent, expectedName) {
function runStackTraceTest(moduleName, funcNames, expectedName) {
var sections = [
sigSection([v2vSig]),
importSection([{sigIndex:0, module:"env", func:"callback"}]),
@ -439,8 +454,8 @@ function runStackTraceTest(namesContent, expectedName) {
customSection("whoa"),
customSection("wee", 42),
];
if (namesContent)
sections.push(nameSection(namesContent));
if (moduleName || funcNames)
sections.push(nameSection(moduleName, funcNames));
sections.push(customSection("yay", 13));
var result = "";
@ -452,16 +467,20 @@ function runStackTraceTest(namesContent, expectedName) {
assertEq(result, expectedName);
};
runStackTraceTest(null, 'wasm-function[1]');
runStackTraceTest([{name:'blah'}, {name: 'test'}], 'test');
runStackTraceTest([{name:'blah'}, {name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
runStackTraceTest([{name:'blah'}, {name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
runStackTraceTest([{name:'blah'}, {name: 'test1'}, {name: 'test2'}], 'test1');
runStackTraceTest([{name:'blah'}, {name: 'test☃'}], 'test☃');
runStackTraceTest([{name:'blah'}, {name: 'te\xE0\xFF'}], 'te\xE0\xFF');
runStackTraceTest([{name:'blah'}], 'wasm-function[1]');
runStackTraceTest([], 'wasm-function[1]');
runStackTraceTest(null, null, 'wasm-function[1]');
runStackTraceTest(null, [{name:'blah'}, {name:'test'}], 'test');
runStackTraceTest(null, [{name:'test', index:1}], 'test');
runStackTraceTest(null, [{name:'blah'}, {name:'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
runStackTraceTest(null, [{name:'blah'}, {name:'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
runStackTraceTest(null, [{name:'blah'}, {name:'test1'}], 'test1');
runStackTraceTest(null, [{name:'blah'}, {name:'test☃'}], 'test☃');
runStackTraceTest(null, [{name:'blah'}, {name:'te\xE0\xFF'}], 'te\xE0\xFF');
runStackTraceTest(null, [{name:'blah'}], 'wasm-function[1]');
runStackTraceTest(null, [], 'wasm-function[1]');
runStackTraceTest("", [{name:'blah'}, {name:'test'}], 'test');
runStackTraceTest("a", [{name:'blah'}, {name:'test'}], 'test');
// Notice that invalid names section content shall not fail the parsing
runStackTraceTest([{name:'blah'}, {nameLen: 100, name: 'test'}], 'wasm-function[1]'); // invalid name size
runStackTraceTest([{name:'blah'}, {name: 'test', locals: [{nameLen: 40, name: 'var1'}]}], 'wasm-function[1]'); // invalid variable name size
runStackTraceTest([{name:'blah'}, {name: ''}], 'wasm-function[1]'); // empty name
runStackTraceTest(null, [{name:'blah'}, {name:'test', index: 2}], 'wasm-function[1]'); // invalid index
runStackTraceTest(null, [{name:'blah'}, {name:'test', index: 100000}], 'wasm-function[1]'); // invalid index
runStackTraceTest(null, [{name:'blah'}, {name:'test', nameLen: 100}], 'wasm-function[1]'); // invalid name size
runStackTraceTest(null, [{name:'blah'}, {name:''}], 'wasm-function[1]'); // empty name

Просмотреть файл

@ -2,8 +2,11 @@
* 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/. */
#include "mozilla/Move.h"
#include "js/HashTable.h"
#include "js/Utility.h"
#include "jsapi-tests/tests.h"
//#define FUZZ
@ -388,3 +391,45 @@ BEGIN_TEST(testHashMapLookupWithDefaultOOM)
END_TEST(testHashMapLookupWithDefaultOOM)
#endif // defined(DEBUG)
BEGIN_TEST(testHashTableMovableEnum)
{
CHECK(set.init());
// Exercise returning a hash table Enum object from a function.
CHECK(set.put(1));
for (auto e = enumerateSet(); !e.empty(); e.popFront())
e.removeFront();
CHECK(set.count() == 0);
// Test moving an Enum object explicitly.
CHECK(set.put(1));
CHECK(set.put(2));
CHECK(set.put(3));
CHECK(set.count() == 3);
{
auto e1 = IntSet::Enum(set);
CHECK(!e1.empty());
e1.removeFront();
e1.popFront();
auto e2 = mozilla::Move(e1);
CHECK(!e2.empty());
e2.removeFront();
e2.popFront();
}
CHECK(set.count() == 1);
return true;
}
IntSet set;
IntSet::Enum enumerateSet()
{
return IntSet::Enum(set);
}
END_TEST(testHashTableMovableEnum)

Просмотреть файл

@ -879,6 +879,10 @@ case "$target" in
fi
;;
*-solaris*)
MOZ_FIX_LINK_PATHS=
;;
esac
dnl Only one oddball right now (QNX), but this gives us flexibility

Просмотреть файл

@ -158,7 +158,7 @@ JSONPrinter::property(const char* name, uint64_t value)
out_.printf("%" PRIu64, value);
}
#ifdef XP_DARWIN
#if defined(XP_DARWIN) || defined(__OpenBSD__)
void
JSONPrinter::property(const char* name, size_t value)
{

Просмотреть файл

@ -51,10 +51,10 @@ class JSONPrinter
void property(const char* name, uint32_t value);
void property(const char* name, int64_t value);
void property(const char* name, uint64_t value);
#ifdef XP_DARWIN
// On OSX, size_t is long unsigned, uint32_t is unsigned, and uint64_t is
// long long unsigned. Everywhere else, size_t matches either uint32_t or
// uint64_t.
#if defined(XP_DARWIN) || defined(__OpenBSD__)
// On OSX and OpenBSD, size_t is long unsigned, uint32_t is unsigned, and
// uint64_t is long long unsigned. Everywhere else, size_t matches either
// uint32_t or uint64_t.
void property(const char* name, size_t value);
#endif

Просмотреть файл

@ -27,9 +27,6 @@ namespace wasm {
static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
static const uint32_t EncodingVersion = 0x01;
static const char NameSectionName[] = "name";
static const char SourceMappingURLSectionName[] = "sourceMappingURL";
enum class SectionId
{
Custom = 0,
@ -432,6 +429,16 @@ enum class Op
Limit
};
static const char NameSectionName[] = "name";
static const char SourceMappingURLSectionName[] = "sourceMappingURL";
enum class NameType
{
Module = 0,
Function = 1,
Local = 2
};
// Telemetry sample values for the JS_AOT_USAGE key, indicating whether asm.js
// or WebAssembly is used.

Просмотреть файл

@ -274,7 +274,9 @@ struct NameInBytecode
uint32_t offset;
uint32_t length;
NameInBytecode() = default;
NameInBytecode()
: offset(UINT32_MAX), length(0)
{}
NameInBytecode(uint32_t offset, uint32_t length)
: offset(offset), length(length)
{}

Просмотреть файл

@ -202,6 +202,36 @@ Decoder::skipCustomSection(ModuleEnvironment* env)
return true;
}
bool
Decoder::startNameSubsection(NameType nameType, uint32_t* endOffset)
{
const uint8_t* initialPosition = cur_;
uint32_t nameTypeValue;
if (!readVarU32(&nameTypeValue))
return false;
if (nameTypeValue != uint8_t(nameType)) {
cur_ = initialPosition;
*endOffset = NotStarted;
return true;
}
uint32_t payloadLength;
if (!readVarU32(&payloadLength) || payloadLength > bytesRemain())
return false;
*endOffset = (cur_ - beg_) + payloadLength;
return true;
}
bool
Decoder::finishNameSubsection(uint32_t endOffset)
{
MOZ_ASSERT(endOffset != NotStarted);
return endOffset == uint32_t(cur_ - beg_);
}
// Misc helpers.
bool
@ -1560,60 +1590,81 @@ DecodeDataSection(Decoder& d, ModuleEnvironment* env)
return true;
}
static void
MaybeDecodeNameSectionBody(Decoder& d, ModuleEnvironment* env)
static bool
DecodeModuleNameSubsection(Decoder& d, ModuleEnvironment* env)
{
// For simplicity, ignore all failures, even OOM. Failure will simply result
// in the names section not being included for this module.
uint32_t endOffset;
if (!d.startNameSubsection(NameType::Module, &endOffset))
return false;
if (endOffset == Decoder::NotStarted)
return true;
uint32_t numFuncNames;
if (!d.readVarU32(&numFuncNames))
return;
// Don't use NameInBytecode for module name; instead store a copy of the
// string. This way supplying a module name doesn't need to save the whole
// bytecode. While function names are likely to be stripped in practice,
// module names aren't necessarily.
if (numFuncNames > MaxFuncs)
return;
uint32_t nameLength;
if (!d.readVarU32(&nameLength))
return false;
const uint8_t* bytes;
if (!d.readBytes(nameLength, &bytes))
return false;
// Do nothing with module name for now; a future patch will incorporate the
// module name into the callstack format.
return d.finishNameSubsection(endOffset);
}
static bool
DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
{
uint32_t endOffset;
if (!d.startNameSubsection(NameType::Function, &endOffset))
return false;
if (endOffset == Decoder::NotStarted)
return true;
uint32_t nameCount = 0;
if (!d.readVarU32(&nameCount) || nameCount > MaxFuncs)
return false;
// Use a local vector (and not env->funcNames) since it could result in a
// partially initialized result in case of failure in the middle.
NameInBytecodeVector funcNames;
if (!funcNames.resize(numFuncNames))
return;
for (uint32_t i = 0; i < numFuncNames; i++) {
uint32_t numBytes;
if (!d.readVarU32(&numBytes))
return;
if (numBytes > MaxStringLength)
return;
for (uint32_t i = 0; i < nameCount; ++i) {
uint32_t funcIndex = 0;
if (!d.readVarU32(&funcIndex))
return false;
NameInBytecode name;
name.offset = d.currentOffset();
name.length = numBytes;
funcNames[i] = name;
// Names must refer to real functions and be given in ascending order.
if (funcIndex >= env->numFuncs() || funcIndex < funcNames.length())
return false;
if (!d.readBytes(numBytes))
return;
if (!funcNames.resize(funcIndex + 1))
return false;
// Skip local names for a function.
uint32_t numLocals;
if (!d.readVarU32(&numLocals))
return;
if (numLocals > MaxLocals)
return;
uint32_t nameLength = 0;
if (!d.readVarU32(&nameLength) || nameLength > MaxStringLength)
return false;
for (uint32_t j = 0; j < numLocals; j++) {
uint32_t numBytes;
if (!d.readVarU32(&numBytes))
return;
if (numBytes > MaxStringLength)
return;
NameInBytecode func;
func.offset = d.currentOffset();
func.length = nameLength;
funcNames[funcIndex] = func;
if (!d.readBytes(numBytes))
return;
}
if (!d.readBytes(nameLength))
return false;
}
if (!d.finishNameSubsection(endOffset))
return false;
// To encourage fully valid function names subsections; only save names if
// the entire subsection decoded correctly.
env->funcNames = Move(funcNames);
return true;
}
static bool
@ -1627,8 +1678,17 @@ DecodeNameSection(Decoder& d, ModuleEnvironment* env)
// Once started, custom sections do not report validation errors.
MaybeDecodeNameSectionBody(d, env);
if (!DecodeModuleNameSubsection(d, env))
goto finish;
if (!DecodeFunctionNameSubsection(d, env))
goto finish;
// The names we care about have already been extracted into 'env' so don't
// bother decoding the rest of the name section. finishCustomSection() will
// skip to the end of the name section (as it would for any other error).
finish:
d.finishCustomSection(sectionStart, sectionSize);
return true;
}

Просмотреть файл

@ -555,6 +555,11 @@ class Decoder
void finishCustomSection(uint32_t sectionStart, uint32_t sectionSize);
MOZ_MUST_USE bool skipCustomSection(ModuleEnvironment* env);
// The Name section has its own subsections. Like startSection, NotStart is
// returned as the endOffset if the given name subsection wasn't present.
MOZ_MUST_USE bool startNameSubsection(NameType nameType, uint32_t* endOffset);
MOZ_MUST_USE bool finishNameSubsection(uint32_t endOffset);
// The infallible "unchecked" decoding functions can be used when we are
// sure that the bytes are well-formed (by construction or due to previous

Просмотреть файл

@ -0,0 +1,28 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<head>
<title>Test of NS_FRAME_IS_NONDISPLAY / NS_FRAME_IS_DIRTY assertion</title>
<!-- reduced from layout/reftests/svg/svg-integration/conditions-outer-svg-01.xhtml
and modified to occur without bug 1308876 patches. -->
<style>
div { position: relative; height: 100px; width: 100px }
svg { position: absolute; top: 0; left: 0; height: 100%; width: 100% }
</style>
<script>
function run() {
var d = document.getElementById("d");
d.offsetHeight;
d.style.height = "50px";
}
</script>
</head>
<body onload="run()">
<div id="d">
<svg:svg systemLanguage="x"></svg:svg>
</div>
</body>
</html>

Просмотреть файл

@ -199,4 +199,5 @@ load 1182496-1.html
load 1209525-1.svg
load 1223281-1.svg
load 1348564.svg
load conditional-outer-svg-nondirty-reflow-assert.xhtml
load extref-test-1.xhtml

Просмотреть файл

@ -100,18 +100,19 @@ nsSVGContainerFrame::ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas)
* inherited font-size of an ancestor changes, or a delayed webfont loads and
* applies.
*
* We assume that any change that requires the anonymous kid of an
* SVGTextFrame to reflow will result in an NS_FRAME_IS_DIRTY reflow. When
* However, we only need to do this work if we were reflowed with
* NS_FRAME_IS_DIRTY, which implies that all descendants are dirty. When
* that reflow reaches an NS_FRAME_IS_NONDISPLAY frame it would normally
* stop, but this helper looks for any SVGTextFrame descendants of such
* frames and marks them NS_FRAME_IS_DIRTY so that the next time that they are
* painted their anonymous kid will first get the necessary reflow.
* frames and marks them NS_FRAME_IS_DIRTY so that the next time that they
* are painted their anonymous kid will first get the necessary reflow.
*/
/* static */ void
nsSVGContainerFrame::ReflowSVGNonDisplayText(nsIFrame* aContainer)
{
NS_ASSERTION(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY,
"expected aContainer to be NS_FRAME_IS_DIRTY");
if (!(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY)) {
return;
}
NS_ASSERTION((aContainer->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
!aContainer->IsFrameOfType(nsIFrame::eSVG),
"it is wasteful to call ReflowSVGNonDisplayText on a container "

Просмотреть файл

@ -209,6 +209,16 @@ pref("dom.keyboardevent.dispatch_during_composition", false);
// significantly increase the number of compartments in the system.
pref("dom.compartment_per_addon", true);
// Whether to enable the JavaScript start-up cache. This causes one of the first
// execution to record the bytecode of the JavaScript function used, and save it
// in the existing cache entry. On the following loads of the same script, the
// bytecode would be loaded from the cache instead of being generated once more.
pref("dom.script_loader.bytecode_cache.enabled", false); // Not tuned yet.
// Ignore the heuristics of the bytecode cache, and always record on the first
// visit. (used for testing purposes).
pref("dom.script_loader.bytecode_cache.eager", false);
// Fastback caching - if this pref is negative, then we calculate the number
// of content viewers to cache based on the amount of available memory.
pref("browser.sessionhistory.max_total_viewers", -1);
@ -3143,7 +3153,7 @@ pref("browser.tabs.remote.separateFileUriProcess", false);
// This has been added in case breaking any window references between these
// sorts of pages, which we have to do when we run them in the normal web
// content process, causes compatibility issues.
pref("browser.tabs.remote.allowLinkedWebInFileUriProcess", false);
pref("browser.tabs.remote.allowLinkedWebInFileUriProcess", true);
// Enable caching of Moz2D Path objects for SVG geometry elements
pref("svg.path-caching.enabled", true);

Просмотреть файл

@ -1191,6 +1191,10 @@ case "$target" in
fi
;;
*-solaris*)
MOZ_FIX_LINK_PATHS=
;;
esac
AC_SUBST_LIST(MMX_FLAGS)
@ -2019,7 +2023,7 @@ else
NSS_CFLAGS="-I${DIST}/include/nss"
case "${OS_ARCH}" in
# Only few platforms have been tested with GYP
WINNT|Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
WINNT|Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|SunOS)
;;
*)
AC_MSG_ERROR([building in-tree NSS is not supported on this platform. Use --with-system-nss])

Двоичные данные
other-licenses/7zstub/firefox/7zSD.sfx

Двоичный файл не отображается.

Просмотреть файл

@ -236,6 +236,20 @@ struct AutoLoadSystemDependencies
{
AutoLoadSystemDependencies()
{
HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
if (module) {
// SetDefaultDllDirectories is always available on Windows 8 and above. It
// is also available on Windows Vista, Windows Server 2008, and
// Windows 7 when MS KB2533623 has been applied.
typedef BOOL (WINAPI *SetDefaultDllDirectoriesType)(DWORD);
SetDefaultDllDirectoriesType setDefaultDllDirectories =
(SetDefaultDllDirectoriesType) GetProcAddress(module, "SetDefaultDllDirectories");
if (setDefaultDllDirectories) {
setDefaultDllDirectories(0x0800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ );
return;
}
}
static LPCWSTR delayDLLs[] = { L"dwmapi.dll", L"cryptbase.dll",
L"SHCore.dll", L"uxtheme.dll",
L"oleacc.dll", L"apphelp.dll" };

Просмотреть файл

@ -54,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98
# ADD LINK32 comctl32.lib kernel32.lib user32.lib shell32.lib oleaut32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /delayload:comctl32.dll /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "SFXSetup-moz - Win32 Debug"
@ -81,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept
# ADD LINK32 comctl32.lib kernel32.lib user32.lib shell32.lib oleaut32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept /delayload:comctl32.dll /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll
!ELSEIF "$(CFG)" == "SFXSetup-moz - Win32 ReleaseD"
@ -109,7 +109,7 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe"
# SUBTRACT BASE LINK32 /debug /nodefaultlib
# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"ReleaseD\7zSD.sfx" /opt:NOWIN98
# ADD LINK32 comctl32.lib kernel32.lib user32.lib shell32.lib oleaut32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"ReleaseD\7zSD.sfx" /delayload:comctl32.dll /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ENDIF

Просмотреть файл

@ -359,26 +359,48 @@ this.BrowserTestUtils = {
* The tabbrowser to look for the next new tab in.
* @param {string} url
* A string URL to look for in the new tab. If null, allows any non-blank URL.
* @param {boolean} waitForLoad
* True to wait for the page in the new tab to load. Defaults to false.
*
* @return {Promise}
* @resolves With the {xul:tab} when a tab is opened and its location changes to the given URL.
* @resolves With the {xul:tab} when a tab is opened and its location changes
* to the given URL and optionally that browser has loaded.
*
* NB: this method will not work if you open a new tab with e.g. BrowserOpenTab
* and the tab does not load a URL, because no onLocationChange will fire.
*/
waitForNewTab(tabbrowser, url) {
waitForNewTab(tabbrowser, url, waitForLoad = false) {
let urlMatches = url ? (urlToMatch) => urlToMatch == url
: (urlToMatch) => urlToMatch != "about:blank";
return new Promise((resolve, reject) => {
tabbrowser.tabContainer.addEventListener("TabOpen", function(openEvent) {
let newTab = openEvent.target;
let newBrowser = newTab.linkedBrowser;
let result;
if (waitForLoad) {
// If waiting for load, resolve with promise for that, which when load
// completes resolves to the new tab.
result = BrowserTestUtils.browserLoaded(newBrowser, false, urlMatches)
.then(() => newTab);
} else {
// If not waiting for load, just resolve with the new tab.
result = newTab;
}
let progressListener = {
onLocationChange(aBrowser) {
if (aBrowser != openEvent.target.linkedBrowser ||
(url && aBrowser.currentURI.spec != url) ||
(!url && aBrowser.currentURI.spec == "about:blank")) {
// Only interested in location changes on our browser.
if (aBrowser != newBrowser) {
return;
}
// Check that new location is the URL we want.
if (!urlMatches(aBrowser.currentURI.spec)) {
return;
}
tabbrowser.removeTabsProgressListener(progressListener);
resolve(openEvent.target);
resolve(result);
},
};
tabbrowser.addTabsProgressListener(progressListener);

Просмотреть файл

@ -0,0 +1,37 @@
config = {
"branch": "date",
"nightly_build": True,
"update_channel": "aurora-dev", # devedition uses aurora based branding
# l10n
"hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-beta",
# repositories
# staging beta dev releases use date repo for now
"mozilla_dir": "date",
"repos": [{
"vcs": "hg",
"repo": "https://hg.mozilla.org/build/tools",
"branch": "default",
"dest": "tools",
}, {
"vcs": "hg",
"repo": "https://hg.mozilla.org/projects/date",
"branch": "%(revision)s",
"dest": "date",
"clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
}],
# purge options
'is_automation': True,
'purge_minsize': 12,
'default_actions': [
"clobber",
"pull",
"clone-locales",
"list-locales",
"setup",
"repack",
"taskcluster-upload",
"summary",
],
}

Просмотреть файл

@ -0,0 +1 @@
linux_devedition.py

Просмотреть файл

@ -0,0 +1,104 @@
import os
config = {
"platform": "linux64",
"stage_product": "firefox",
"update_platform": "Linux_x86_64-gcc3",
"mozconfig": "%(branch)s/browser/config/mozconfigs/linux64/l10n-mozconfig-devedition",
"bootstrap_env": {
"MOZ_OBJDIR": "obj-l10n",
"EN_US_BINARY_URL": "%(en_us_binary_url)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
"MOZ_UPDATE_CHANNEL": "%(update_channel)s",
"DIST": "%(abs_objdir)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
"L10NBASEDIR": "../../l10n",
"MOZ_MAKE_COMPLETE_MAR": "1",
'TOOLTOOL_CACHE': '/builds/tooltool_cache',
'TOOLTOOL_HOME': '/builds',
'EN_US_PACKAGE_NAME': 'target.tar.bz2',
},
"ssh_key_dir": "/home/mock_mozilla/.ssh",
"log_name": "single_locale",
"objdir": "obj-l10n",
"js_src_dir": "js/src",
"vcs_share_base": "/builds/hg-shared",
# tooltool
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
'tooltool_script': ["/builds/tooltool.py"],
'tooltool_bootstrap': "setup.sh",
'tooltool_manifest_src': 'browser/config/tooltool-manifests/linux64/releng.manifest',
# balrog credential file:
'balrog_credentials_file': 'oauth.txt',
# l10n
"ignore_locales": ["en-US", "ja-JP-mac"],
"l10n_dir": "l10n",
"locales_file": "%(branch)s/browser/locales/all-locales",
"locales_dir": "browser/locales",
"hg_l10n_tag": "default",
"merge_locales": True,
# MAR
"previous_mar_dir": "dist/previous",
"current_mar_dir": "dist/current",
"update_mar_dir": "dist/update", # sure?
"previous_mar_filename": "previous.mar",
"current_work_mar_dir": "current.work",
"package_base_dir": "dist/l10n-stage",
"application_ini": "application.ini",
"buildid_section": 'App',
"buildid_option": "BuildID",
"unpack_script": "tools/update-packaging/unwrap_full_update.pl",
"incremental_update_script": "tools/update-packaging/make_incremental_update.sh",
"balrog_release_pusher_script": "scripts/updates/balrog-release-pusher.py",
"update_packaging_dir": "tools/update-packaging",
"local_mar_tool_dir": "dist/host/bin",
"mar": "mar",
"mbsdiff": "mbsdiff",
"current_mar_filename": "firefox-%(version)s.%(locale)s.linux-x86_64.complete.mar",
"complete_mar": "firefox-%(version)s.en-US.linux-x86_64.complete.mar",
"localized_mar": "firefox-%(version)s.%(locale)s.linux-x86_64.complete.mar",
"partial_mar": "firefox-%(version)s.%(locale)s.linux-x86_64.partial.%(from_buildid)s-%(to_buildid)s.mar",
"installer_file": "firefox-%(version)s.en-US.linux-x86_64.tar.bz2",
# Mock
'mock_target': 'mozilla-centos6-x86_64',
'mock_packages': [
'autoconf213', 'python', 'mozilla-python27', 'zip', 'mozilla-python27-mercurial',
'git', 'ccache', 'perl-Test-Simple', 'perl-Config-General',
'yasm', 'wget',
'mpfr', # required for system compiler
'xorg-x11-font*', # fonts required for PGO
'imake', # required for makedepend!?!
### <-- from releng repo
'gcc45_0moz3', 'gcc454_0moz1', 'gcc472_0moz1', 'gcc473_0moz1',
'yasm', 'ccache',
###
'valgrind', 'dbus-x11',
######## 64 bit specific ###########
'glibc-static', 'libstdc++-static',
'gtk2-devel', 'libnotify-devel',
'alsa-lib-devel', 'libcurl-devel', 'wireless-tools-devel',
'libX11-devel', 'libXt-devel', 'mesa-libGL-devel', 'gnome-vfs2-devel',
'GConf2-devel',
### from releng repo
'gcc45_0moz3', 'gcc454_0moz1', 'gcc472_0moz1', 'gcc473_0moz1',
'yasm', 'ccache',
###
'pulseaudio-libs-devel', 'gstreamer-devel',
'gstreamer-plugins-base-devel', 'freetype-2.3.11-6.el6_1.8.x86_64',
'freetype-devel-2.3.11-6.el6_1.8.x86_64'
],
'mock_files': [
('/home/cltbld/.ssh', '/home/mock_mozilla/.ssh'),
('/home/cltbld/.hgrc', '/builds/.hgrc'),
('/home/cltbld/.boto', '/builds/.boto'),
('/builds/gapi.data', '/builds/gapi.data'),
('/builds/relengapi.tok', '/builds/relengapi.tok'),
('/tools/tooltool.py', '/builds/tooltool.py'),
('/usr/local/lib/hgext', '/usr/local/lib/hgext'),
],
}

Просмотреть файл

@ -0,0 +1,124 @@
import os
config = {
"platform": "linux",
"stage_product": "firefox",
"update_platform": "Linux_x86-gcc3",
"mozconfig": "%(branch)s/browser/config/mozconfigs/linux32/l10n-mozconfig-devedition",
"bootstrap_env": {
"MOZ_OBJDIR": "obj-l10n",
"EN_US_BINARY_URL": "%(en_us_binary_url)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
"MOZ_UPDATE_CHANNEL": "%(update_channel)s",
"DIST": "%(abs_objdir)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
"L10NBASEDIR": "../../l10n",
"MOZ_MAKE_COMPLETE_MAR": "1",
'TOOLTOOL_CACHE': '/builds/tooltool_cache',
'TOOLTOOL_HOME': '/builds',
'EN_US_PACKAGE_NAME': 'target.tar.bz2',
},
"ssh_key_dir": "/home/mock_mozilla/.ssh",
"log_name": "single_locale",
"objdir": "obj-l10n",
"js_src_dir": "js/src",
"vcs_share_base": "/builds/hg-shared",
# tooltool
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
'tooltool_script': ["/builds/tooltool.py"],
'tooltool_bootstrap': "setup.sh",
'tooltool_manifest_src': 'browser/config/tooltool-manifests/linux32/releng.manifest',
# balrog credential file:
'balrog_credentials_file': 'oauth.txt',
# l10n
"ignore_locales": ["en-US", "ja-JP-mac"],
"l10n_dir": "l10n",
"locales_file": "%(branch)s/browser/locales/all-locales",
"locales_dir": "browser/locales",
"hg_l10n_tag": "default",
"merge_locales": True,
# MAR
"previous_mar_dir": "dist/previous",
"current_mar_dir": "dist/current",
"update_mar_dir": "dist/update", # sure?
"previous_mar_filename": "previous.mar",
"current_work_mar_dir": "current.work",
"package_base_dir": "dist/l10n-stage",
"application_ini": "application.ini",
"buildid_section": 'App',
"buildid_option": "BuildID",
"unpack_script": "tools/update-packaging/unwrap_full_update.pl",
"incremental_update_script": "tools/update-packaging/make_incremental_update.sh",
"balrog_release_pusher_script": "scripts/updates/balrog-release-pusher.py",
"update_packaging_dir": "tools/update-packaging",
"local_mar_tool_dir": "dist/host/bin",
"mar": "mar",
"mbsdiff": "mbsdiff",
"current_mar_filename": "firefox-%(version)s.%(locale)s.linux-i686.complete.mar",
"complete_mar": "firefox-%(version)s.en-US.linux-i686.complete.mar",
"localized_mar": "firefox-%(version)s.%(locale)s.linux-i686.complete.mar",
"partial_mar": "firefox-%(version)s.%(locale)s.linux-i686.partial.%(from_buildid)s-%(to_buildid)s.mar",
'installer_file': "firefox-%(version)s.en-US.linux-i686.tar.bz2",
# Mock
'mock_target': 'mozilla-centos6-x86_64',
'mock_packages': [
'autoconf213', 'python', 'mozilla-python27', 'zip', 'mozilla-python27-mercurial',
'git', 'ccache', 'perl-Test-Simple', 'perl-Config-General',
'yasm', 'wget',
'mpfr', # required for system compiler
'xorg-x11-font*', # fonts required for PGO
'imake', # required for makedepend!?!
### <-- from releng repo
'gcc45_0moz3', 'gcc454_0moz1', 'gcc472_0moz1', 'gcc473_0moz1',
'yasm', 'ccache',
###
'valgrind',
######## 32 bit specific ###########
'glibc-static.i686', 'libstdc++-static.i686',
'gtk2-devel.i686', 'libnotify-devel.i686',
'alsa-lib-devel.i686', 'libcurl-devel.i686',
'wireless-tools-devel.i686', 'libX11-devel.i686',
'libXt-devel.i686', 'mesa-libGL-devel.i686',
'gnome-vfs2-devel.i686', 'GConf2-devel.i686',
'pulseaudio-libs-devel.i686',
'gstreamer-devel.i686', 'gstreamer-plugins-base-devel.i686',
# Packages already installed in the mock environment, as x86_64
# packages.
'glibc-devel.i686', 'libgcc.i686', 'libstdc++-devel.i686',
# yum likes to install .x86_64 -devel packages that satisfy .i686
# -devel packages dependencies. So manually install the dependencies
# of the above packages.
'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686',
'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686',
'fontconfig-devel.i686', 'glib2-devel.i686',
'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686',
'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686',
'libXcursor-devel.i686', 'libXdamage-devel.i686',
'libXdmcp-devel.i686', 'libXext-devel.i686', 'libXfixes-devel.i686',
'libXft-devel.i686', 'libXi-devel.i686', 'libXinerama-devel.i686',
'libXrandr-devel.i686', 'libXrender-devel.i686',
'libXxf86vm-devel.i686', 'libdrm-devel.i686', 'libidn-devel.i686',
'libpng-devel.i686', 'libxcb-devel.i686', 'libxml2-devel.i686',
'pango-devel.i686', 'perl-devel.i686', 'pixman-devel.i686',
'zlib-devel.i686',
# Freetype packages need to be installed be version, because a newer
# version is available, but we don't want it for Firefox builds.
'freetype-2.3.11-6.el6_1.8.i686',
'freetype-devel-2.3.11-6.el6_1.8.i686',
'freetype-2.3.11-6.el6_1.8.x86_64',
######## 32 bit specific ###########
],
'mock_files': [
('/home/cltbld/.ssh', '/home/mock_mozilla/.ssh'),
('/home/cltbld/.hgrc', '/builds/.hgrc'),
('/home/cltbld/.boto', '/builds/.boto'),
('/builds/gapi.data', '/builds/gapi.data'),
('/builds/relengapi.tok', '/builds/relengapi.tok'),
('/tools/tooltool.py', '/builds/tooltool.py'),
('/usr/local/lib/hgext', '/usr/local/lib/hgext'),
],
}

Просмотреть файл

@ -0,0 +1,72 @@
import os
config = {
# mozconfig file to use, it depends on branch and platform names
"platform": "macosx64",
"stage_product": "firefox",
"update_platform": "Darwin_x86_64-gcc3",
"mozconfig": "%(branch)s/browser/config/mozconfigs/macosx64/l10n-mozconfig-devedition",
"bootstrap_env": {
"SHELL": '/bin/bash',
"MOZ_OBJDIR": "obj-l10n",
"EN_US_BINARY_URL": "%(en_us_binary_url)s",
"MOZ_UPDATE_CHANNEL": "%(update_channel)s",
"MOZ_PKG_PLATFORM": "mac",
# "IS_NIGHTLY": "yes",
"DIST": "%(abs_objdir)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
"L10NBASEDIR": "../../l10n",
"MOZ_MAKE_COMPLETE_MAR": "1",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
'TOOLTOOL_CACHE': '/builds/tooltool_cache',
'TOOLTOOL_HOME': '/builds',
},
"ssh_key_dir": "~/.ssh",
"log_name": "single_locale",
"objdir": "obj-l10n",
"js_src_dir": "js/src",
"vcs_share_base": "/builds/hg-shared",
"upload_env_extra": {
"MOZ_PKG_PLATFORM": "mac",
},
# tooltool
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
'tooltool_script': ["/builds/tooltool.py"],
'tooltool_bootstrap': "setup.sh",
'tooltool_manifest_src': 'browser/config/tooltool-manifests/macosx64/releng.manifest',
# balrog credential file:
'balrog_credentials_file': 'oauth.txt',
# l10n
"ignore_locales": ["en-US", "ja"],
"l10n_dir": "l10n",
"locales_file": "%(branch)s/browser/locales/all-locales",
"locales_dir": "browser/locales",
"hg_l10n_tag": "default",
"merge_locales": True,
# MAR
"previous_mar_dir": "dist/previous",
"current_mar_dir": "dist/current",
"update_mar_dir": "dist/update", # sure?
"previous_mar_filename": "previous.mar",
"current_work_mar_dir": "current.work",
"package_base_dir": "dist/l10n-stage",
"application_ini": "Contents/Resources/application.ini",
"buildid_section": 'App',
"buildid_option": "BuildID",
"unpack_script": "tools/update-packaging/unwrap_full_update.pl",
"incremental_update_script": "tools/update-packaging/make_incremental_update.sh",
"balrog_release_pusher_script": "scripts/updates/balrog-release-pusher.py",
"update_packaging_dir": "tools/update-packaging",
"local_mar_tool_dir": "dist/host/bin",
"mar": "mar",
"mbsdiff": "mbsdiff",
"current_mar_filename": "firefox-%(version)s.%(locale)s.mac.complete.mar",
"complete_mar": "firefox-%(version)s.en-US.mac.complete.mar",
"localized_mar": "firefox-%(version)s.%(locale)s.mac.complete.mar",
"partial_mar": "firefox-%(version)s.%(locale)s.mac.partial.%(from_buildid)s-%(to_buildid)s.mar",
'installer_file': "firefox-%(version)s.en-US.mac.dmg",
}

Просмотреть файл

@ -0,0 +1,37 @@
config = {
"nightly_build": True,
"branch": "mozilla-beta",
"en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-beta/",
"update_channel": "aurora", # devedition uses aurora based branding
# l10n
"hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-beta",
# repositories
"mozilla_dir": "mozilla-beta",
"repos": [{
"vcs": "hg",
"repo": "https://hg.mozilla.org/build/tools",
"branch": "default",
"dest": "tools",
}, {
"vcs": "hg",
"repo": "https://hg.mozilla.org/releases/mozilla-beta",
"revision": "%(revision)s",
"dest": "mozilla-beta",
"clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
}],
# purge options
'purge_minsize': 12,
'is_automation': True,
'default_actions': [
"clobber",
"pull",
"clone-locales",
"list-locales",
"setup",
"repack",
"taskcluster-upload",
"summary",
],
}

Просмотреть файл

@ -0,0 +1,76 @@
import os
import sys
config = {
"platform": "win32",
"stage_product": "firefox",
"update_platform": "WINNT_x86-msvc",
"mozconfig": "%(branch)s/browser/config/mozconfigs/win32/l10n-mozconfig-devedition",
"bootstrap_env": {
"MOZ_OBJDIR": "obj-l10n",
"EN_US_BINARY_URL": "%(en_us_binary_url)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s",
"MOZ_UPDATE_CHANNEL": "%(update_channel)s",
"DIST": "%(abs_objdir)s",
"L10NBASEDIR": "../../l10n",
"MOZ_MAKE_COMPLETE_MAR": "1",
"PATH": 'C:\\mozilla-build\\nsis-3.01;'
'%s' % (os.environ.get('path')),
'TOOLTOOL_CACHE': 'c:/builds/tooltool_cache',
'TOOLTOOL_HOME': '/c/builds',
},
"ssh_key_dir": "~/.ssh",
"log_name": "single_locale",
"objdir": "obj-l10n",
"js_src_dir": "js/src",
"vcs_share_base": "c:/builds/hg-shared",
# tooltool
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
'tooltool_script': [sys.executable,
'C:/mozilla-build/tooltool.py'],
'tooltool_bootstrap': "setup.sh",
'tooltool_manifest_src': 'browser/config/tooltool-manifests/win32/releng.manifest',
# balrog credential file:
'balrog_credentials_file': 'oauth.txt',
# l10n
"ignore_locales": ["en-US", "ja-JP-mac"],
"l10n_dir": "l10n",
"locales_file": "%(branch)s/browser/locales/all-locales",
"locales_dir": "browser/locales",
"hg_l10n_tag": "default",
"merge_locales": True,
# MAR
"previous_mar_dir": "dist\\previous",
"current_mar_dir": "dist\\current",
"update_mar_dir": "dist\\update", # sure?
"previous_mar_filename": "previous.mar",
"current_work_mar_dir": "current.work",
"package_base_dir": "dist\\l10n-stage",
"application_ini": "application.ini",
"buildid_section": 'App',
"buildid_option": "BuildID",
"unpack_script": "tools\\update-packaging\\unwrap_full_update.pl",
"incremental_update_script": "tools\\update-packaging\\make_incremental_update.sh",
"balrog_release_pusher_script": "scripts\\updates\\balrog-release-pusher.py",
"update_packaging_dir": "tools\\update-packaging",
"local_mar_tool_dir": "dist\\host\\bin",
"mar": "mar.exe",
"mbsdiff": "mbsdiff.exe",
"current_mar_filename": "firefox-%(version)s.%(locale)s.win32.complete.mar",
"complete_mar": "firefox-%(version)s.en-US.win32.complete.mar",
"localized_mar": "firefox-%(version)s.%(locale)s.win32.complete.mar",
"partial_mar": "firefox-%(version)s.%(locale)s.win32.partial.%(from_buildid)s-%(to_buildid)s.mar",
'installer_file': "firefox-%(version)s.en-US.win32.installer.exe",
# use mozmake?
"enable_mozmake": True,
'exes': {
'virtualenv': [
sys.executable,
'c:/mozilla-build/buildbotve/virtualenv.py'
],
}
}

Просмотреть файл

@ -0,0 +1,76 @@
import os
import sys
config = {
"platform": "win64",
"stage_product": "firefox",
"update_platform": "WINNT_x86_64-msvc",
"mozconfig": "%(branch)s/browser/config/mozconfigs/win64/l10n-mozconfig-devedition",
"bootstrap_env": {
"MOZ_OBJDIR": "obj-l10n",
"EN_US_BINARY_URL": "%(en_us_binary_url)s",
"MOZ_UPDATE_CHANNEL": "%(update_channel)s",
"DIST": "%(abs_objdir)s",
"LOCALE_MERGEDIR": "%(abs_merge_dir)s",
"L10NBASEDIR": "../../l10n",
"MOZ_MAKE_COMPLETE_MAR": "1",
"PATH": 'C:\\mozilla-build\\nsis-3.01;'
'%s' % (os.environ.get('path')),
'TOOLTOOL_CACHE': 'c:/builds/tooltool_cache',
'TOOLTOOL_HOME': '/c/builds',
},
"ssh_key_dir": "~/.ssh",
"log_name": "single_locale",
"objdir": "obj-l10n",
"js_src_dir": "js/src",
"vcs_share_base": "c:/builds/hg-shared",
# tooltool
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
'tooltool_script': [sys.executable,
'C:/mozilla-build/tooltool.py'],
'tooltool_bootstrap': "setup.sh",
'tooltool_manifest_src': 'browser/config/tooltool-manifests/win64/releng.manifest',
# balrog credential file:
'balrog_credentials_file': 'oauth.txt',
# l10n
"ignore_locales": ["en-US", "ja-JP-mac"],
"l10n_dir": "l10n",
"locales_file": "%(branch)s/browser/locales/all-locales",
"locales_dir": "browser/locales",
"hg_l10n_tag": "default",
"merge_locales": True,
# MAR
"previous_mar_dir": "dist\\previous",
"current_mar_dir": "dist\\current",
"update_mar_dir": "dist\\update", # sure?
"previous_mar_filename": "previous.mar",
"current_work_mar_dir": "current.work",
"package_base_dir": "dist\\l10n-stage",
"application_ini": "application.ini",
"buildid_section": 'App',
"buildid_option": "BuildID",
"unpack_script": "tools\\update-packaging\\unwrap_full_update.pl",
"incremental_update_script": "tools\\update-packaging\\make_incremental_update.sh",
"balrog_release_pusher_script": "scripts\\updates\\balrog-release-pusher.py",
"update_packaging_dir": "tools\\update-packaging",
"local_mar_tool_dir": "dist\\host\\bin",
"mar": "mar.exe",
"mbsdiff": "mbsdiff.exe",
"current_mar_filename": "firefox-%(version)s.%(locale)s.win64.complete.mar",
"complete_mar": "firefox-%(version)s.en-US.win64.complete.mar",
"localized_mar": "firefox-%(version)s.%(locale)s.win64.complete.mar",
"partial_mar": "firefox-%(version)s.%(locale)s.win64.partial.%(from_buildid)s-%(to_buildid)s.mar",
'installer_file': "firefox-%(version)s.en-US.win64.installer.exe",
# use mozmake?
"enable_mozmake": True,
'exes': {
'virtualenv': [
sys.executable,
'c:/mozilla-build/buildbotve/virtualenv.py'
],
}
}

Просмотреть файл

@ -84,16 +84,13 @@ function run_test() {
notEqual(endHangs.hangs[0].stack.length, 0);
equal(typeof endHangs.hangs[0].stack[0], "string");
// Native stack gathering is only enabled on Windows x86.
if (mozinfo.os == "win" && mozinfo.bits == 32) {
// Make sure one of the hangs is a permanent
// hang containing a native stack.
ok(endHangs.hangs.some((hang) => (
hang.nativeStack &&
Array.isArray(hang.nativeStack.memoryMap) &&
Array.isArray(hang.nativeStack.stacks)
)));
}
// Make sure one of the hangs is a permanent
// hang containing a native stack.
ok(endHangs.hangs.some((hang) => (
hang.nativeStack &&
Array.isArray(hang.nativeStack.memoryMap) &&
Array.isArray(hang.nativeStack.stacks)
)));
check_histogram(endHangs.hangs[0].histogram);

Просмотреть файл

@ -55,6 +55,7 @@ tags = addons
tags = addons
[test_TelemetrySession_activeTicks.js]
[test_ThreadHangStats.js]
skip-if = os == "android" || os == "linux" # BHR is disabled on linux (bug 1365309)
run-sequentially = Bug 1046307, test can fail intermittently when CPU load is high
[test_TelemetrySend.js]
[test_ChildHistograms.js]

Просмотреть файл

@ -57,6 +57,7 @@ support-files =
[browser_discovery_install.js]
[browser_eula.js]
skip-if = buildapp == 'mulet'
[browser_file_xpi_no_process_switch.js]
[browser_getmorethemes.js]
[browser_gmpProvider.js]
[browser_hotfix.js]

Просмотреть файл

@ -0,0 +1,101 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
const ADDON_INSTALL_ID = "addon-install-confirmation";
let fileurl1 = get_addon_file_url("browser_dragdrop1.xpi");
let fileurl2 = get_addon_file_url("browser_dragdrop2.xpi");
function promiseInstallNotification(aBrowser) {
return new Promise(resolve => {
function popupshown(event) {
if (event.target.getAttribute("popupid") != ADDON_INSTALL_ID) {
return;
}
let notification =
PopupNotifications.getNotification(ADDON_INSTALL_ID, aBrowser);
if (!notification) {
return;
}
PopupNotifications.panel.removeEventListener("popupshown", popupshown);
ok(true, `Got ${ADDON_INSTALL_ID} popup for browser`);
notification.remove();
resolve();
}
PopupNotifications.panel.addEventListener("popupshown", popupshown);
});
}
function waitForAnyNewTabAndInstallNotification() {
return new Promise((resolve) => {
gBrowser.tabContainer.addEventListener("TabOpen", function(openEvent) {
let newTab = openEvent.target;
resolve([newTab, promiseInstallNotification(newTab.linkedBrowser)]);
}, {once: true});
});
}
function CheckBrowserInPid(browser, expectedPid, message) {
return ContentTask.spawn(browser, { expectedPid, message }, (arg) => {
is(Services.appinfo.processID, arg.expectedPid, arg.message);
});
}
async function testOpenedAndDraggedXPI(aBrowser) {
// Get the current pid for browser for comparison later.
let browserPid = await ContentTask.spawn(aBrowser, null, () => {
return Services.appinfo.processID;
});
// No process switch for XPI file:// URI in the urlbar.
let promiseNotification = promiseInstallNotification(aBrowser);
let urlbar = document.getElementById("urlbar");
urlbar.value = fileurl1.spec;
urlbar.focus();
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" });
await promiseNotification;
await CheckBrowserInPid(aBrowser, browserPid,
"Check that browser has not switched process.");
// No process switch for XPI file:// URI dragged to tab.
let tab = gBrowser.getTabForBrowser(aBrowser);
promiseNotification = promiseInstallNotification(aBrowser);
let effect = EventUtils.synthesizeDrop(tab, tab,
[[{type: "text/uri-list", data: fileurl1.spec}]],
"move");
is(effect, "move", "Drag should be accepted");
await promiseNotification;
await CheckBrowserInPid(aBrowser, browserPid,
"Check that browser has not switched process.");
// No process switch for two XPI file:// URIs dragged to tab.
promiseNotification = promiseInstallNotification(aBrowser);
let promiseTabAndNotification = waitForAnyNewTabAndInstallNotification();
effect = EventUtils.synthesizeDrop(tab, tab,
[[{type: "text/uri-list", data: fileurl1.spec}],
[{type: "text/uri-list", data: fileurl2.spec}]],
"move");
is(effect, "move", "Drag should be accepted");
let [newTab, newTabInstallNotification] = await promiseTabAndNotification;
await promiseNotification;
if (gBrowser.selectedTab != newTab) {
await BrowserTestUtils.switchTab(gBrowser, newTab);
}
await newTabInstallNotification;
await BrowserTestUtils.removeTab(newTab);
await CheckBrowserInPid(aBrowser, browserPid,
"Check that browser has not switched process.");
}
// Test for bug 1175267.
add_task(async function() {
await SpecialPowers.pushPrefEnv({
set: [["xpinstall.customConfirmationUI", true]]
});
await BrowserTestUtils.withNewTab("http://example.com", testOpenedAndDraggedXPI);
await BrowserTestUtils.withNewTab("about:robots", testOpenedAndDraggedXPI);
});

Просмотреть файл

@ -67,7 +67,6 @@ const FILE_ACTIVE_UPDATE_XML = "active-update.xml";
const FILE_BACKUP_UPDATE_LOG = "backup-update.log";
const FILE_LAST_UPDATE_LOG = "last-update.log";
const FILE_UPDATES_XML = "updates.xml";
const FILE_UPDATE_LINK = "update.link";
const FILE_UPDATE_LOG = "update.log";
const FILE_UPDATE_MAR = "update.mar";
const FILE_UPDATE_STATUS = "update.status";
@ -101,7 +100,6 @@ const SERVICE_COULD_NOT_LOCK_UPDATER = 32;
const SERVICE_INSTALLDIR_ERROR = 33;
const WRITE_ERROR_ACCESS_DENIED = 35;
const WRITE_ERROR_CALLBACK_APP = 37;
const FILESYSTEM_MOUNT_READWRITE_ERROR = 43;
const SERVICE_COULD_NOT_COPY_UPDATER = 49;
const SERVICE_STILL_APPLYING_TERMINATED = 50;
const SERVICE_STILL_APPLYING_NO_EXIT_CODE = 51;
@ -148,10 +146,6 @@ const SERVICE_ERRORS = [SERVICE_UPDATER_COULD_NOT_BE_STARTED,
// Error codes 80 through 99 are reserved for nsUpdateService.js and are not
// defined in common/errors.h
const FOTA_GENERAL_ERROR = 80;
const FOTA_UNKNOWN_ERROR = 81;
const FOTA_FILE_OPERATION_ERROR = 82;
const FOTA_RECOVERY_ERROR = 83;
const INVALID_UPDATER_STATE_CODE = 98;
const INVALID_UPDATER_STATUS_CODE = 99;
@ -190,8 +184,6 @@ const APPID_TO_TOPIC = {
"{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "sessionstore-windows-restored",
// SeaMonkey
"{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": "sessionstore-windows-restored",
// Fennec
"{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "sessionstore-windows-restored",
// Thunderbird
"{3550f703-e582-4d05-9a08-453d09bdfdc6}": "mail-startup-done",
// Instantbird
@ -931,26 +923,7 @@ function readStringFromFile(file) {
function handleUpdateFailure(update, errorCode) {
update.errorCode = parseInt(errorCode);
if (update.errorCode == FOTA_GENERAL_ERROR ||
update.errorCode == FOTA_FILE_OPERATION_ERROR ||
update.errorCode == FOTA_RECOVERY_ERROR ||
update.errorCode == FOTA_UNKNOWN_ERROR) {
// In the case of FOTA update errors, don't reset the state to pending. This
// causes the FOTA update path to try again, which is not necessarily what
// we want.
update.statusText = gUpdateBundle.GetStringFromName("statusFailed");
Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt).
showUpdateError(update);
writeStatusFile(getUpdatesDir(), STATE_FAILED + ": " + errorCode);
cleanupActiveUpdate();
return true;
}
// Replace with Array.prototype.includes when it has stabilized.
if (WRITE_ERRORS.indexOf(update.errorCode) != -1 ||
update.errorCode == FILESYSTEM_MOUNT_READWRITE_ERROR) {
if (WRITE_ERRORS.includes(update.errorCode)) {
Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt).
showUpdateError(update);
@ -1000,7 +973,7 @@ function handleUpdateFailure(update, errorCode) {
update.QueryInterface(Ci.nsIWritablePropertyBag);
update.setProperty("patchingFailed", "elevationFailure");
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
createInstance(Ci.nsIUpdatePrompt);
prompter.showUpdateError(update);
} else {
writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
@ -1015,8 +988,7 @@ function handleUpdateFailure(update, errorCode) {
Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
}
// Replace with Array.prototype.includes when it has stabilized.
if (SERVICE_ERRORS.indexOf(update.errorCode) != -1) {
if (SERVICE_ERRORS.includes(update.errorCode)) {
var failCount = getPref("getIntPref",
PREF_APP_UPDATE_SERVICE_ERRORS, 0);
var maxFail = getPref("getIntPref",
@ -1073,7 +1045,7 @@ function handleFallbackToCompleteUpdate(update, postStaging) {
LOG("handleFallbackToCompleteUpdate - install of complete or " +
"only one patch offered failed. Notifying observers. topic: " +
"update-error, status: unknown, " +
"update.patchCount: " + update.patchCount +
"update.patchCount: " + update.patchCount + ", " +
"oldType: " + oldType);
Services.obs.notifyObservers(update, "update-error", "unknown");
}
@ -3881,14 +3853,8 @@ UpdatePrompt.prototype = {
return;
// In some cases, we want to just show a simple alert dialog.
// Replace with Array.prototype.includes when it has stabilized.
if (update.state == STATE_FAILED &&
(WRITE_ERRORS.indexOf(update.errorCode) != -1 ||
update.errorCode == FILESYSTEM_MOUNT_READWRITE_ERROR ||
update.errorCode == FOTA_GENERAL_ERROR ||
update.errorCode == FOTA_FILE_OPERATION_ERROR ||
update.errorCode == FOTA_RECOVERY_ERROR ||
update.errorCode == FOTA_UNKNOWN_ERROR)) {
WRITE_ERRORS.includes(update.errorCode)) {
var title = gUpdateBundle.GetStringFromName("updaterIOErrorTitle");
var text = gUpdateBundle.formatStringFromName("updaterIOErrorMsg",
[Services.appinfo.name,

Просмотреть файл

@ -130,7 +130,7 @@ public:
};
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
// BEGIN Sampler target specifics
// The only way to reliably interrupt a Linux thread and inspect its register
// and stack state is by sending a signal to it, and doing the work inside the
@ -199,7 +199,7 @@ struct SigHandlerCoordinator
ucontext_t mUContext; // Context at signal
};
struct SigHandlerCoordinator* SamplerThread::sSigHandlerCoordinator = nullptr;
struct SigHandlerCoordinator* Sampler::sSigHandlerCoordinator = nullptr;
static void
SigprofHandler(int aSignal, siginfo_t* aInfo, void* aContext)
@ -208,18 +208,18 @@ SigprofHandler(int aSignal, siginfo_t* aInfo, void* aContext)
int savedErrno = errno;
MOZ_ASSERT(aSignal == SIGPROF);
MOZ_ASSERT(SamplerThread::sSigHandlerCoordinator);
MOZ_ASSERT(Sampler::sSigHandlerCoordinator);
// By sending us this signal, the sampler thread has sent us message 1 in
// the comment above, with the meaning "|sSigHandlerCoordinator| is ready
// for use, please copy your register context into it."
SamplerThread::sSigHandlerCoordinator->mUContext =
Sampler::sSigHandlerCoordinator->mUContext =
*static_cast<ucontext_t*>(aContext);
// Send message 2: tell the sampler thread that the context has been copied
// into |sSigHandlerCoordinator->mUContext|. sem_post can never fail by
// being interrupted by a signal, so there's no loop around this call.
int r = sem_post(&SamplerThread::sSigHandlerCoordinator->mMessage2);
int r = sem_post(&Sampler::sSigHandlerCoordinator->mMessage2);
MOZ_ASSERT(r == 0);
// At this point, the sampler thread assumes we are suspended, so we must
@ -227,7 +227,7 @@ SigprofHandler(int aSignal, siginfo_t* aInfo, void* aContext)
// Wait for message 3: the sampler thread tells us to resume.
while (true) {
r = sem_wait(&SamplerThread::sSigHandlerCoordinator->mMessage3);
r = sem_wait(&Sampler::sSigHandlerCoordinator->mMessage3);
if (r == -1 && errno == EINTR) {
// Interrupted by a signal. Try again.
continue;
@ -240,33 +240,19 @@ SigprofHandler(int aSignal, siginfo_t* aInfo, void* aContext)
// Send message 4: tell the sampler thread that we are finished accessing
// |sSigHandlerCoordinator|. After this point it is not safe to touch
// |sSigHandlerCoordinator|.
r = sem_post(&SamplerThread::sSigHandlerCoordinator->mMessage4);
r = sem_post(&Sampler::sSigHandlerCoordinator->mMessage4);
MOZ_ASSERT(r == 0);
errno = savedErrno;
}
static void*
ThreadEntry(void* aArg)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->mSamplerTid = gettid();
thread->Run();
return nullptr;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
, mMyPid(getpid())
Sampler::Sampler(PSLockRef aLock)
: mMyPid(getpid())
// We don't know what the sampler thread's ID will be until it runs, so set
// mSamplerTid to a dummy value and fill it in for real in ThreadEntry().
// mSamplerTid to a dummy value and fill it in for real in
// SuspendAndSampleAndResumeThread().
, mSamplerTid(-1)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
#if defined(USE_EHABI_STACKWALK)
mozilla::EHABIStackWalkInit();
#elif defined(USE_LUL_STACKWALK)
@ -304,66 +290,29 @@ SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
}
}
#endif
// Start the sampling thread. It repeatedly sends a SIGPROF signal. Sending
// the signal ourselves instead of relying on itimer provides much better
// accuracy.
if (pthread_create(&mThread, nullptr, ThreadEntry, this) != 0) {
MOZ_CRASH("pthread_create failed");
}
}
SamplerThread::~SamplerThread()
{
pthread_join(mThread, nullptr);
}
void
SamplerThread::Stop(PSLockRef aLock)
Sampler::Disable(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Restore old signal handler. This is global state so it's important that
// we do it now, while gPSMutex is locked. It's safe to do this now even
// though this SamplerThread is still alive, because the next time the main
// loop of Run() iterates it won't get past the mActivityGeneration check,
// and so won't send any signals.
// we do it now, while gPSMutex is locked.
sigaction(SIGPROF, &mOldSigprofHandler, 0);
}
template<typename Func>
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
if (aMicroseconds >= 1000000) {
// Use usleep for larger intervals, because the nanosleep
// code below only supports intervals < 1 second.
MOZ_ALWAYS_TRUE(!::usleep(aMicroseconds));
return;
}
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = aMicroseconds * 1000UL;
int rv = ::nanosleep(&ts, &ts);
while (rv != 0 && errno == EINTR) {
// Keep waiting in case of interrupt.
// nanosleep puts the remaining time back into ts.
rv = ::nanosleep(&ts, &ts);
}
MOZ_ASSERT(!rv, "nanosleep call failed");
}
void
SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample)
Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample,
const Func& aDoSample)
{
// Only one sampler thread can be sampling at once. So we expect to have
// complete control over |sSigHandlerCoordinator|.
MOZ_ASSERT(!sSigHandlerCoordinator);
if (mSamplerTid == -1) {
mSamplerTid = gettid();
}
int sampleeTid = aSample.mThreadId;
MOZ_RELEASE_ASSERT(sampleeTid != mSamplerTid);
@ -410,7 +359,7 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
// Extract the current PC and sp.
FillInSample(aSample, &sSigHandlerCoordinator->mUContext);
Tick(aLock, ActivePS::Buffer(aLock), aSample);
aDoSample();
//----------------------------------------------------------------//
// Resume the target thread.
@ -440,6 +389,80 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
sSigHandlerCoordinator = nullptr;
}
// END Sampler target specifics
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
static void*
ThreadEntry(void* aArg)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return nullptr;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: Sampler(aLock)
, mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Start the sampling thread. It repeatedly sends a SIGPROF signal. Sending
// the signal ourselves instead of relying on itimer provides much better
// accuracy.
if (pthread_create(&mThread, nullptr, ThreadEntry, this) != 0) {
MOZ_CRASH("pthread_create failed");
}
}
SamplerThread::~SamplerThread()
{
pthread_join(mThread, nullptr);
}
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
if (aMicroseconds >= 1000000) {
// Use usleep for larger intervals, because the nanosleep
// code below only supports intervals < 1 second.
MOZ_ALWAYS_TRUE(!::usleep(aMicroseconds));
return;
}
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = aMicroseconds * 1000UL;
int rv = ::nanosleep(&ts, &ts);
while (rv != 0 && errno == EINTR) {
// Keep waiting in case of interrupt.
// nanosleep puts the remaining time back into ts.
rv = ::nanosleep(&ts, &ts);
}
MOZ_ASSERT(!rv, "nanosleep call failed");
}
void
SamplerThread::Stop(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Restore old signal handler. This is global state so it's important that
// we do it now, while gPSMutex is locked. It's safe to do this now even
// though this SamplerThread is still alive, because the next time the main
// loop of Run() iterates it won't get past the mActivityGeneration check,
// and so won't send any signals.
Sampler::Disable(aLock);
}
// END SamplerThread target specifics
////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -62,54 +62,22 @@ private:
};
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
// BEGIN Sampler target specifics
static void*
ThreadEntry(void* aArg)
Sampler::Sampler(PSLockRef aLock)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return nullptr;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
pthread_attr_t* attr_ptr = nullptr;
if (pthread_create(&mThread, attr_ptr, ThreadEntry, this) != 0) {
MOZ_CRASH("pthread_create failed");
}
}
SamplerThread::~SamplerThread()
{
pthread_join(mThread, nullptr);
}
void
SamplerThread::Stop(PSLockRef aLock)
Sampler::Disable(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
}
template<typename Func>
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
usleep(aMicroseconds);
// FIXME: the OSX 10.12 page for usleep says "The usleep() function is
// obsolescent. Use nanosleep(2) instead." This implementation could be
// merged with the linux-android version. Also, this doesn't handle the
// case where the usleep call is interrupted by a signal.
}
void
SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample)
Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample,
const Func& aDoSample)
{
thread_act_t samplee_thread = aSample.mPlatformData->ProfiledThread();
@ -166,7 +134,7 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
aSample.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
aSample.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
Tick(aLock, ActivePS::Buffer(aLock), aSample);
aDoSample();
}
#undef REGISTER_FIELD
@ -181,6 +149,58 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
}
// END Sampler target specifics
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
static void*
ThreadEntry(void* aArg)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return nullptr;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: Sampler(aLock)
, mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
pthread_attr_t* attr_ptr = nullptr;
if (pthread_create(&mThread, attr_ptr, ThreadEntry, this) != 0) {
MOZ_CRASH("pthread_create failed");
}
}
SamplerThread::~SamplerThread()
{
pthread_join(mThread, nullptr);
}
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
usleep(aMicroseconds);
// FIXME: the OSX 10.12 page for usleep says "The usleep() function is
// obsolescent. Use nanosleep(2) instead." This implementation could be
// merged with the linux-android version. Also, this doesn't handle the
// case where the usleep call is interrupted by a signal.
}
void
SamplerThread::Stop(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
Sampler::Disable(aLock);
}
// END SamplerThread target specifics
////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -79,105 +79,27 @@ GetThreadHandle(PlatformData* aData)
static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
// BEGIN Sampler target specifics
static unsigned int __stdcall
ThreadEntry(void* aArg)
Sampler::Sampler(PSLockRef aLock)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return 0;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// By default we'll not adjust the timer resolution which tends to be
// around 16ms. However, if the requested interval is sufficiently low
// we'll try to adjust the resolution to match.
if (mIntervalMicroseconds < 10*1000) {
::timeBeginPeriod(mIntervalMicroseconds / 1000);
}
// Create a new thread. It is important to use _beginthreadex() instead of
// the Win32 function CreateThread(), because the CreateThread() does not
// initialize thread-specific structures in the C runtime library.
mThread = reinterpret_cast<HANDLE>(
_beginthreadex(nullptr,
/* stack_size */ 0,
ThreadEntry,
this,
/* initflag */ 0,
nullptr));
if (mThread == 0) {
MOZ_CRASH("_beginthreadex failed");
}
}
SamplerThread::~SamplerThread()
{
WaitForSingleObject(mThread, INFINITE);
// Close our own handle for the thread.
if (mThread != kNoThread) {
CloseHandle(mThread);
}
}
void
SamplerThread::Stop(PSLockRef aLock)
Sampler::Disable(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Disable any timer resolution changes we've made. Do it now while
// gPSMutex is locked, i.e. before any other SamplerThread can be created
// and call ::timeBeginPeriod().
//
// It's safe to do this now even though this SamplerThread is still alive,
// because the next time the main loop of Run() iterates it won't get past
// the mActivityGeneration check, and so it won't make any more ::Sleep()
// calls.
if (mIntervalMicroseconds < 10 * 1000) {
::timeEndPeriod(mIntervalMicroseconds / 1000);
}
}
template<typename Func>
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
// For now, keep the old behaviour of minimum Sleep(1), even for
// smaller-than-usual sleeps after an overshoot, unless the user has
// explicitly opted into a sub-millisecond profiler interval.
if (mIntervalMicroseconds >= 1000) {
::Sleep(std::max(1u, aMicroseconds / 1000));
} else {
TimeStamp start = TimeStamp::Now();
TimeStamp end = start + TimeDuration::FromMicroseconds(aMicroseconds);
// First, sleep for as many whole milliseconds as possible.
if (aMicroseconds >= 1000) {
::Sleep(aMicroseconds / 1000);
}
// Then, spin until enough time has passed.
while (TimeStamp::Now() < end) {
_mm_pause();
}
}
}
void
SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample)
Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample,
const Func& aDoSample)
{
HANDLE profiled_thread = aSample.mPlatformData->ProfiledThread();
if (profiled_thread == nullptr)
if (profiled_thread == nullptr) {
return;
}
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
@ -228,7 +150,7 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
aSample.mContext = &context;
Tick(aLock, ActivePS::Buffer(aLock), aSample);
aDoSample();
//----------------------------------------------------------------//
// Resume the target thread.
@ -240,6 +162,105 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
}
// END Sampler target specifics
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread target specifics
static unsigned int __stdcall
ThreadEntry(void* aArg)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return 0;
}
SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: Sampler(aLock)
, mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// By default we'll not adjust the timer resolution which tends to be
// around 16ms. However, if the requested interval is sufficiently low
// we'll try to adjust the resolution to match.
if (mIntervalMicroseconds < 10*1000) {
::timeBeginPeriod(mIntervalMicroseconds / 1000);
}
// Create a new thread. It is important to use _beginthreadex() instead of
// the Win32 function CreateThread(), because the CreateThread() does not
// initialize thread-specific structures in the C runtime library.
mThread = reinterpret_cast<HANDLE>(
_beginthreadex(nullptr,
/* stack_size */ 0,
ThreadEntry,
this,
/* initflag */ 0,
nullptr));
if (mThread == 0) {
MOZ_CRASH("_beginthreadex failed");
}
}
SamplerThread::~SamplerThread()
{
WaitForSingleObject(mThread, INFINITE);
// Close our own handle for the thread.
if (mThread != kNoThread) {
CloseHandle(mThread);
}
}
void
SamplerThread::SleepMicro(uint32_t aMicroseconds)
{
// For now, keep the old behaviour of minimum Sleep(1), even for
// smaller-than-usual sleeps after an overshoot, unless the user has
// explicitly opted into a sub-millisecond profiler interval.
if (mIntervalMicroseconds >= 1000) {
::Sleep(std::max(1u, aMicroseconds / 1000));
} else {
TimeStamp start = TimeStamp::Now();
TimeStamp end = start + TimeDuration::FromMicroseconds(aMicroseconds);
// First, sleep for as many whole milliseconds as possible.
if (aMicroseconds >= 1000) {
::Sleep(aMicroseconds / 1000);
}
// Then, spin until enough time has passed.
while (TimeStamp::Now() < end) {
_mm_pause();
}
}
}
void
SamplerThread::Stop(PSLockRef aLock)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Disable any timer resolution changes we've made. Do it now while
// gPSMutex is locked, i.e. before any other SamplerThread can be created
// and call ::timeBeginPeriod().
//
// It's safe to do this now even though this SamplerThread is still alive,
// because the next time the main loop of Run() iterates it won't get past
// the mActivityGeneration check, and so it won't make any more ::Sleep()
// calls.
if (mIntervalMicroseconds < 10 * 1000) {
::timeEndPeriod(mIntervalMicroseconds / 1000);
}
Sampler::Disable(aLock);
}
// END SamplerThread target specifics
////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -980,31 +980,22 @@ StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure)
}
static void
DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
DoNativeBacktrace(PSLockRef aLock, NativeStack& aNativeStack,
const TickSample& aSample)
{
void* pc_array[1000];
void* sp_array[1000];
NativeStack nativeStack = {
pc_array,
sp_array,
mozilla::ArrayLength(pc_array),
0
};
// Start with the current function. We use 0 as the frame number here because
// the FramePointerStackWalk() and MozStackWalk() calls below will use 1..N.
// This is a bit weird but it doesn't matter because StackWalkCallback()
// doesn't use the frame number argument.
StackWalkCallback(/* frameNum */ 0, aSample.mPC, aSample.mSP, &nativeStack);
StackWalkCallback(/* frameNum */ 0, aSample.mPC, aSample.mSP, &aNativeStack);
uint32_t maxFrames = uint32_t(nativeStack.size - nativeStack.count);
uint32_t maxFrames = uint32_t(aNativeStack.size - aNativeStack.count);
#if defined(GP_OS_darwin) || (defined(GP_PLAT_x86_windows))
void* stackEnd = aSample.mStackTop;
if (aSample.mFP >= aSample.mSP && aSample.mFP <= stackEnd) {
FramePointerStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames,
&nativeStack, reinterpret_cast<void**>(aSample.mFP),
&aNativeStack, reinterpret_cast<void**>(aSample.mFP),
stackEnd);
}
#else
@ -1012,28 +1003,17 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
// MozStackWalk().
uintptr_t thread = GetThreadHandle(aSample.mPlatformData);
MOZ_ASSERT(thread);
MozStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &nativeStack,
MozStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &aNativeStack,
thread, /* platformData */ nullptr);
#endif
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
}
#endif
#ifdef USE_EHABI_STACKWALK
static void
DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
DoNativeBacktrace(PSLockRef aLock, NativeStack& aNativeStack,
const TickSample& aSample)
{
void* pc_array[1000];
void* sp_array[1000];
NativeStack nativeStack = {
pc_array,
sp_array,
mozilla::ArrayLength(pc_array),
0
};
const mcontext_t* mcontext =
&reinterpret_cast<ucontext_t*>(aSample.mContext)->uc_mcontext;
mcontext_t savedContext;
@ -1054,11 +1034,11 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
// the saved state.
uint32_t* vSP = reinterpret_cast<uint32_t*>(entry.stackAddress());
nativeStack.count += EHABIStackWalk(*mcontext,
/* stackBase = */ vSP,
sp_array + nativeStack.count,
pc_array + nativeStack.count,
nativeStack.size - nativeStack.count);
aNativeStack.count += EHABIStackWalk(*mcontext,
/* stackBase = */ vSP,
aNativeStack.sp_array + aNativeStack.count,
aNativeStack.pc_array + aNativeStack.count,
aNativeStack.size - aNativeStack.count);
memset(&savedContext, 0, sizeof(savedContext));
@ -1080,13 +1060,11 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
// Now unwind whatever's left (starting from either the last EnterJIT frame
// or, if no EnterJIT was found, the original registers).
nativeStack.count += EHABIStackWalk(*mcontext,
aSample.mStackTop,
sp_array + nativeStack.count,
pc_array + nativeStack.count,
nativeStack.size - nativeStack.count);
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
aNativeStack.count += EHABIStackWalk(*mcontext,
aSample.mStackTop,
aNativeStack.sp_array + aNativeStack.count,
aNativeStack.pc_array + aNativeStack.count,
aNativeStack.size - aNativeStack.count);
}
#endif
@ -1111,7 +1089,7 @@ ASAN_memcpy(void* aDst, const void* aSrc, size_t aLen)
#endif
static void
DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
DoNativeBacktrace(PSLockRef aLock, NativeStack& aNativeStack,
const TickSample& aSample)
{
const mcontext_t* mc =
@ -1219,72 +1197,67 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
// The maximum number of frames that LUL will produce. Setting it
// too high gives a risk of it wasting a lot of time looping on
// corrupted stacks.
// corrupted stacks. Limit the size of the passed-in native stack
// to not exceed this number.
const int MAX_NATIVE_FRAMES = 256;
if (aNativeStack.size > MAX_NATIVE_FRAMES) {
aNativeStack.size = MAX_NATIVE_FRAMES;
}
size_t scannedFramesAllowed = 0;
uintptr_t framePCs[MAX_NATIVE_FRAMES];
uintptr_t frameSPs[MAX_NATIVE_FRAMES];
size_t framesAvail = mozilla::ArrayLength(framePCs);
size_t framesUsed = 0;
size_t scannedFramesAcquired = 0, framePointerFramesAcquired = 0;
lul::LUL* lul = CorePS::Lul(aLock);
lul->Unwind(&framePCs[0], &frameSPs[0],
&framesUsed, &framePointerFramesAcquired, &scannedFramesAcquired,
framesAvail, scannedFramesAllowed,
lul->Unwind(reinterpret_cast<uintptr_t*>(aNativeStack.pc_array),
reinterpret_cast<uintptr_t*>(aNativeStack.sp_array),
&aNativeStack.count,
&framePointerFramesAcquired, &scannedFramesAcquired,
aNativeStack.size, scannedFramesAllowed,
&startRegs, &stackImg);
NativeStack nativeStack = {
reinterpret_cast<void**>(framePCs),
reinterpret_cast<void**>(frameSPs),
mozilla::ArrayLength(framePCs),
framesUsed
};
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
// Update stats in the LUL stats object. Unfortunately this requires
// three global memory operations.
lul->mStats.mContext += 1;
lul->mStats.mCFI += framesUsed - 1 - framePointerFramesAcquired -
scannedFramesAcquired;
lul->mStats.mCFI += aNativeStack.count - 1 - framePointerFramesAcquired -
scannedFramesAcquired;
lul->mStats.mFP += framePointerFramesAcquired;
lul->mStats.mScanned += scannedFramesAcquired;
}
#endif
static void
DoSampleStackTrace(PSLockRef aLock, ProfileBuffer* aBuffer,
const TickSample& aSample)
void
Tick(PSLockRef aLock, const TickSample& aSample, ProfileBuffer* aBuffer)
{
NativeStack nativeStack = { nullptr, nullptr, 0, 0 };
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
MOZ_RELEASE_ASSERT(ActivePS::Exists(aLock));
if (ActivePS::FeatureLeaf(aLock)) {
aBuffer->addTag(ProfileBufferEntry::NativeLeafAddr((void*)aSample.mPC));
}
}
// This function is called for each sampling period with the current program
// counter. It is called within a signal and so must be re-entrant.
static void
Tick(PSLockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample)
{
aBuffer->addTagThreadId(aSample.mThreadId, aSample.mLastSample);
mozilla::TimeDuration delta =
aSample.mTimeStamp - CorePS::ProcessStartTime(aLock);
aBuffer->addTag(ProfileBufferEntry::Time(delta.ToMilliseconds()));
void* pc_array[1000];
void* sp_array[1000];
NativeStack nativeStack = {
pc_array,
sp_array,
mozilla::ArrayLength(pc_array),
0
};
#if defined(HAVE_NATIVE_UNWIND)
if (ActivePS::FeatureStackWalk(aLock)) {
DoNativeBacktrace(aLock, aBuffer, aSample);
DoNativeBacktrace(aLock, nativeStack, aSample);
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
} else
#endif
{
DoSampleStackTrace(aLock, aBuffer, aSample);
MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
if (ActivePS::FeatureLeaf(aLock)) {
aBuffer->addTag(ProfileBufferEntry::NativeLeafAddr((void*)aSample.mPC));
}
}
// Don't process the PseudoStack's markers if we're synchronously sampling
@ -1683,17 +1656,77 @@ PrintUsageThenExit(int aExitCode)
}
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread
// BEGIN Sampler
#if defined(GP_OS_linux) || defined(GP_OS_android)
struct SigHandlerCoordinator;
#endif
// Sampler performs setup and teardown of the state required to sample with the
// profiler. Sampler may exist when ActivePS is not present.
//
// SuspendAndSampleAndResumeThread must only be called from a single thread,
// and must not sample the thread it is being called from. A separate Sampler
// instance must be used for each thread which wants to capture samples.
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//
// With the exception of SamplerThread, all Sampler objects must be Disable-d
// before releasing the lock which was used to create them. This avoids races
// on linux with the SIGPROF signal handler.
class Sampler
{
public:
// Sets up the profiler such that it can begin sampling.
explicit Sampler(PSLockRef aLock);
// Disable the sampler, restoring it to its previous state. This must be
// called once, and only once, before the Sampler is destroyed.
void Disable(PSLockRef aLock);
// This method suspends and resumes the samplee thread. It calls the passed-in
// function like object aDoSample while the samplee thread is suspended, after
// filling in register values in aSample.
//
// Func must be a function-like object of type `void()`.
template<typename Func>
void SuspendAndSampleAndResumeThread(PSLockRef aLock,
TickSample& aSample,
const Func& aDoSample);
private:
#if defined(GP_OS_linux) || defined(GP_OS_android)
// Used to restore the SIGPROF handler when ours is removed.
struct sigaction mOldSigprofHandler;
// This process' ID. Needed as an argument for tgkill in
// SuspendAndSampleAndResumeThread.
int mMyPid;
// The sampler thread's ID. Used to assert that it is not sampling itself,
// which would lead to deadlock.
int mSamplerTid;
public:
// This is the one-and-only variable used to communicate between the sampler
// thread and the samplee thread's signal handler. It's static because the
// samplee thread's signal handler is static.
static struct SigHandlerCoordinator* sSigHandlerCoordinator;
#endif
};
// END Sampler
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// BEGIN SamplerThread
// The sampler thread controls sampling and runs whenever the profiler is
// active. It periodically runs through all registered threads, finds those
// that should be sampled, then pauses and samples them.
class SamplerThread
class SamplerThread : public Sampler
{
public:
// Creates a sampler thread, but doesn't start it.
@ -1701,10 +1734,6 @@ public:
double aIntervalMilliseconds);
~SamplerThread();
// This runs on the sampler thread. It suspends and resumes the samplee
// threads.
void SuspendAndSampleAndResumeThread(PSLockRef aLock, TickSample& aSample);
// This runs on (is!) the sampler thread.
void Run();
@ -1729,26 +1758,6 @@ private:
pthread_t mThread;
#endif
#if defined(GP_OS_linux) || defined(GP_OS_android)
// Used to restore the SIGPROF handler when ours is removed.
struct sigaction mOldSigprofHandler;
// This process' ID. Needed as an argument for tgkill in
// SuspendAndSampleAndResumeThread.
int mMyPid;
public:
// The sampler thread's ID. Used to assert that it is not sampling itself,
// which would lead to deadlock.
int mSamplerTid;
// This is the one-and-only variable used to communicate between the sampler
// thread and the samplee thread's signal handler. It's static because the
// samplee thread's signal handler is static.
static struct SigHandlerCoordinator* sSigHandlerCoordinator;
#endif
private:
SamplerThread(const SamplerThread&) = delete;
void operator=(const SamplerThread&) = delete;
};
@ -1832,7 +1841,9 @@ SamplerThread::Run()
TickSample sample(info, rssMemory, ussMemory);
SuspendAndSampleAndResumeThread(lock, sample);
SuspendAndSampleAndResumeThread(lock, sample, [&] {
Tick(lock, sample, ActivePS::Buffer(lock));
});
}
#if defined(USE_LUL_STACKWALK)
@ -2778,7 +2789,7 @@ profiler_get_backtrace()
#endif
#endif
Tick(lock, buffer, sample);
Tick(lock, sample, buffer);
return UniqueProfilerBacktrace(
new ProfilerBacktrace("SyncProfile", tid, buffer));
@ -2993,15 +3004,58 @@ profiler_clear_js_context()
info->mContext = nullptr;
}
void*
profiler_get_stack_top()
int
profiler_current_thread_id()
{
return Thread::GetCurrentId();
}
// NOTE: The callback function passed in will be called while the target thread
// is paused. Doing stuff in this function like allocating which may try to
// claim locks is a surefire way to deadlock.
void
profiler_suspend_and_sample_thread(int aThreadId,
const std::function<void(void**, size_t)>& aCallback,
bool aSampleNative /* = true */)
{
// Allocate the space for the native stack
void* pc_array[1000];
void* sp_array[1000];
NativeStack nativeStack = {
pc_array,
sp_array,
mozilla::ArrayLength(pc_array),
0
};
// Lock the profiler mutex
PSAutoLock lock(gPSMutex);
ThreadInfo* threadInfo = FindLiveThreadInfo(lock);
if (threadInfo) {
return threadInfo->StackTop();
const CorePS::ThreadVector& liveThreads = CorePS::LiveThreads(lock);
for (uint32_t i = 0; i < liveThreads.size(); i++) {
ThreadInfo* info = liveThreads.at(i);
if (info->ThreadId() == aThreadId) {
// Suspend, sample, and then resume the target thread.
Sampler sampler(lock);
TickSample sample(info, 0, 0);
sampler.SuspendAndSampleAndResumeThread(lock, sample, [&] {
// The target thread is now suspended, collect a native backtrace, and
// call the callback.
#if defined(HAVE_NATIVE_UNWIND)
if (aSampleNative) {
DoNativeBacktrace(lock, nativeStack, sample);
}
#endif
aCallback(nativeStack.pc_array, nativeStack.count);
});
// NOTE: Make sure to disable the sampler before it is destroyed, in case
// the profiler is running at the same time.
sampler.Disable(lock);
break;
}
}
return nullptr;
}
// END externally visible functions

Просмотреть файл

@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdarg.h>
#include <functional>
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
@ -376,11 +377,19 @@ PROFILER_FUNC(double profiler_time(), 0)
PROFILER_FUNC_VOID(profiler_log(const char *str))
// Gets the stack top of the current thread.
PROFILER_FUNC(int profiler_current_thread_id(), 0)
// This method suspends the thread identified by aThreadId, optionally samples
// it for its native stack, and then calls the callback. The callback is passed
// the native stack's program counters and length as two arguments if
// aSampleNative is true.
//
// The thread must have been previously registered with the profiler, otherwise
// this method will return nullptr.
PROFILER_FUNC(void* profiler_get_stack_top(), nullptr)
// WARNING: The target thread is suspended during the callback. Do not try to
// allocate or acquire any locks, or you could deadlock. The target thread will
// have resumed by the time that this function returns.
PROFILER_FUNC_VOID(profiler_suspend_and_sample_thread(int aThreadId,
const std::function<void(void**, size_t)>& aCallback,
bool aSampleNative = true))
// End of the functions defined whether the profiler is enabled or not.

Просмотреть файл

@ -598,7 +598,6 @@ BackgroundHangMonitor::Startup()
if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta")) {
if (XRE_IsParentProcess()) { // cached ClientID hasn't been read yet
ThreadStackHelper::Startup();
BackgroundHangThread::Startup();
BackgroundHangManager::sInstance = new BackgroundHangManager();
@ -612,7 +611,6 @@ BackgroundHangMonitor::Startup()
}
}
ThreadStackHelper::Startup();
BackgroundHangThread::Startup();
BackgroundHangManager::sInstance = new BackgroundHangManager();
#endif
@ -633,7 +631,6 @@ BackgroundHangMonitor::Shutdown()
we don't want to hold the lock when it's being destroyed. */
BackgroundHangManager::sInstance->Shutdown();
BackgroundHangManager::sInstance = nullptr;
ThreadStackHelper::Shutdown();
BackgroundHangManager::sDisabled = true;
#endif
}

Просмотреть файл

@ -9,9 +9,6 @@
#include "nsJSPrincipals.h"
#include "nsScriptSecurityManager.h"
#include "jsfriendapi.h"
#ifdef MOZ_THREADSTACKHELPER_NATIVE
#include "shared-libraries.h"
#endif
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
#include "PseudoStack.h"
#endif
@ -65,91 +62,20 @@
#endif
#endif
#ifdef MOZ_THREADSTACKHELPER_NATIVE
#if defined(MOZ_THREADSTACKHELPER_X86) || \
defined(MOZ_THREADSTACKHELPER_X64)
// On these architectures, the stack grows downwards (toward lower addresses).
#define MOZ_THREADSTACKHELPER_STACK_GROWS_DOWN
#else
#error "Unsupported architecture"
#endif
#endif // MOZ_THREADSTACKHELPER_NATIVE
namespace mozilla {
void
ThreadStackHelper::Startup()
{
#if defined(XP_LINUX)
MOZ_ASSERT(NS_IsMainThread());
if (!sInitialized) {
// TODO: centralize signal number allocation
sFillStackSignum = SIGRTMIN + 4;
if (sFillStackSignum > SIGRTMAX) {
// Leave uninitialized
MOZ_ASSERT(false);
return;
}
struct sigaction sigact = {};
sigact.sa_sigaction = FillStackHandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO | SA_RESTART;
MOZ_ALWAYS_TRUE(!::sigaction(sFillStackSignum, &sigact, nullptr));
}
sInitialized++;
#endif
}
void
ThreadStackHelper::Shutdown()
{
#if defined(XP_LINUX)
MOZ_ASSERT(NS_IsMainThread());
if (sInitialized == 1) {
struct sigaction sigact = {};
sigact.sa_handler = SIG_DFL;
MOZ_ALWAYS_TRUE(!::sigaction(sFillStackSignum, &sigact, nullptr));
}
sInitialized--;
#endif
}
ThreadStackHelper::ThreadStackHelper()
: mStackToFill(nullptr)
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
: mStackToFill(nullptr)
, mPseudoStack(profiler_get_pseudo_stack())
, mMaxStackSize(Stack::sMaxInlineStorage)
, mMaxBufferSize(512)
#endif
{
#if defined(XP_LINUX)
MOZ_ALWAYS_TRUE(!::sem_init(&mSem, 0, 0));
mThreadID = ::syscall(SYS_gettid);
#elif defined(XP_WIN)
mInitialized = !!::DuplicateHandle(
::GetCurrentProcess(), ::GetCurrentThread(),
::GetCurrentProcess(), &mThreadID,
THREAD_SUSPEND_RESUME
#ifdef MOZ_THREADSTACKHELPER_NATIVE
| THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION
, mNativeStackToFill(nullptr)
#endif
, FALSE, 0);
mStackTop = profiler_get_stack_top();
MOZ_ASSERT(mInitialized);
#elif defined(XP_MACOSX)
mThreadID = mach_thread_self();
#endif
}
ThreadStackHelper::~ThreadStackHelper()
{
#if defined(XP_LINUX)
MOZ_ALWAYS_TRUE(!::sem_destroy(&mSem));
#elif defined(XP_WIN)
if (mInitialized) {
MOZ_ALWAYS_TRUE(!!::CloseHandle(mThreadID));
}
#endif
mThreadId = profiler_current_thread_id();
}
namespace {
@ -170,138 +96,10 @@ ThreadStackHelper::GetPseudoStack(Stack& aStack)
GetStacksInternal(&aStack, nullptr);
}
void
ThreadStackHelper::GetStacksInternal(Stack* aStack, NativeStack* aNativeStack)
{
// Always run PrepareStackBuffer first to clear aStack
if (aStack && !PrepareStackBuffer(*aStack)) {
// Skip and return empty aStack
return;
}
ScopedSetPtr<Stack> stackPtr(mStackToFill, aStack);
#if defined(XP_LINUX)
if (!sInitialized) {
MOZ_ASSERT(false);
return;
}
if (aStack) {
siginfo_t uinfo = {};
uinfo.si_signo = sFillStackSignum;
uinfo.si_code = SI_QUEUE;
uinfo.si_pid = getpid();
uinfo.si_uid = getuid();
uinfo.si_value.sival_ptr = this;
if (::syscall(SYS_rt_tgsigqueueinfo, uinfo.si_pid,
mThreadID, sFillStackSignum, &uinfo)) {
// rt_tgsigqueueinfo was added in Linux 2.6.31.
// Could have failed because the syscall did not exist.
return;
}
MOZ_ALWAYS_TRUE(!::sem_wait(&mSem));
}
#elif defined(XP_WIN)
if (!mInitialized) {
MOZ_ASSERT(false);
return;
}
// NOTE: We can only perform frame pointer stack walking on non win64
// platforms, because Win64 always omits frame pointers. We don't want to use
// MozStackWalk here, so we just skip collecting stacks entirely.
#ifndef MOZ_THREADSTACKHELPER_X64
if (aNativeStack) {
aNativeStack->reserve(Telemetry::HangStack::sMaxNativeFrames);
}
#endif
if (::SuspendThread(mThreadID) == DWORD(-1)) {
MOZ_ASSERT(false);
return;
}
// SuspendThread is asynchronous, so the thread may still be running. Use
// GetThreadContext to ensure it's really suspended.
// See https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743.
CONTEXT context;
memset(&context, 0, sizeof(context));
context.ContextFlags = CONTEXT_CONTROL;
if (::GetThreadContext(mThreadID, &context)) {
if (aStack) {
FillStackBuffer();
}
#ifndef MOZ_THREADSTACKHELPER_X64
if (aNativeStack) {
auto callback = [](uint32_t, void* aPC, void*, void* aClosure) {
NativeStack* stack = static_cast<NativeStack*>(aClosure);
stack->push_back(reinterpret_cast<uintptr_t>(aPC));
};
// Now we need to get our frame pointer, our stack pointer, and our stack
// top. Rather than registering and storing the stack tops ourselves, we use
// the gecko profiler to look it up.
void** framePointer = reinterpret_cast<void**>(context.Ebp);
void** stackPointer = reinterpret_cast<void**>(context.Esp);
MOZ_ASSERT(mStackTop, "The thread should be registered by the profiler");
// Double check that the values we pulled for the thread make sense before
// walking the stack.
if (mStackTop && framePointer >= stackPointer && framePointer < mStackTop) {
// NOTE: In bug 1346415 this was changed to use FramePointerStackWalk.
// This was done because lowering the background hang timer threshold
// would cause it to fire on infra early during the boot process, causing
// a deadlock in MozStackWalk when the target thread was holding the
// windows-internal lock on the function table, as it would be suspended
// before we tried to grab the lock to walk its stack.
//
// FramePointerStackWalk is implemented entirely in userspace and thus
// doesn't have the same issues with deadlocking. Unfortunately as 64-bit
// windows is not guaranteed to have frame pointers, the stack walking
// code is only enabled on 32-bit windows builds (bug 1357829).
FramePointerStackWalk(callback, /* skipFrames */ 0,
/* maxFrames */ Telemetry::HangStack::sMaxNativeFrames,
reinterpret_cast<void*>(aNativeStack), framePointer,
mStackTop);
}
}
#endif
}
MOZ_ALWAYS_TRUE(::ResumeThread(mThreadID) != DWORD(-1));
#elif defined(XP_MACOSX)
# if defined(MOZ_VALGRIND) && defined(RUNNING_ON_VALGRIND)
if (RUNNING_ON_VALGRIND) {
/* thread_suspend and thread_resume sometimes hang runs on Valgrind,
for unknown reasons. So, just avoid them. See bug 1100911. */
return;
}
# endif
if (aStack) {
if (::thread_suspend(mThreadID) != KERN_SUCCESS) {
MOZ_ASSERT(false);
return;
}
FillStackBuffer();
MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS);
}
#endif
}
void
ThreadStackHelper::GetNativeStack(NativeStack& aNativeStack)
{
#ifdef MOZ_THREADSTACKHELPER_NATIVE
GetStacksInternal(nullptr, &aNativeStack);
#endif // MOZ_THREADSTACKHELPER_NATIVE
}
void
@ -310,22 +108,47 @@ ThreadStackHelper::GetPseudoAndNativeStack(Stack& aStack, NativeStack& aNativeSt
GetStacksInternal(&aStack, &aNativeStack);
}
#ifdef XP_LINUX
int ThreadStackHelper::sInitialized;
int ThreadStackHelper::sFillStackSignum;
void
ThreadStackHelper::FillStackHandler(int aSignal, siginfo_t* aInfo,
void* aContext)
ThreadStackHelper::GetStacksInternal(Stack* aStack, NativeStack* aNativeStack)
{
ThreadStackHelper* const helper =
reinterpret_cast<ThreadStackHelper*>(aInfo->si_value.sival_ptr);
helper->FillStackBuffer();
::sem_post(&helper->mSem);
}
#if defined(MOZ_THREADSTACKHELPER_PSEUDO) || defined(MOZ_THREADSTACKHELPER_NATIVE)
// Always run PrepareStackBuffer first to clear aStack
if (aStack && !PrepareStackBuffer(*aStack)) {
// Skip and return empty aStack
return;
}
#endif // XP_LINUX
// Prepare the native stack
if (aNativeStack) {
aNativeStack->clear();
aNativeStack->reserve(Telemetry::HangStack::sMaxNativeFrames);
}
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
ScopedSetPtr<Stack> stackPtr(mStackToFill, aStack);
#endif
#ifdef MOZ_THREADSTACKHELPER_NATIVE
ScopedSetPtr<NativeStack> nativeStackPtr(mNativeStackToFill, aNativeStack);
#endif
auto callback = [&, this] (void** aPCs, size_t aCount) {
FillStackBuffer();
#ifdef MOZ_THREADSTACKHELPER_NATIVE
if (mNativeStackToFill) {
while (aCount-- &&
mNativeStackToFill->size() < mNativeStackToFill->capacity()) {
mNativeStackToFill->push_back(reinterpret_cast<uintptr_t>(aPCs[aCount]));
}
}
#endif
};
profiler_suspend_and_sample_thread(mThreadId,
callback,
/* aSampleNative = */ !!aNativeStack);
#endif
}
bool
ThreadStackHelper::PrepareStackBuffer(Stack& aStack)
@ -484,9 +307,9 @@ ThreadStackHelper::AppendJSEntry(const volatile js::ProfileEntry* aEntry,
void
ThreadStackHelper::FillStackBuffer()
{
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
MOZ_ASSERT(mStackToFill->empty());
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
size_t reservedSize = mStackToFill->capacity();
size_t reservedBufferSize = mStackToFill->AvailableBufferSize();
intptr_t availableBufferSize = intptr_t(reservedBufferSize);

Просмотреть файл

@ -22,25 +22,20 @@
#include <mach/mach.h>
#endif
// Support pseudostack on these platforms.
// Support pseudostack and native stack on these platforms.
#if defined(XP_LINUX) || defined(XP_WIN) || defined(XP_MACOSX)
# ifdef MOZ_GECKO_PROFILER
# define MOZ_THREADSTACKHELPER_PSEUDO
# define MOZ_THREADSTACKHELPER_NATIVE
# endif
#endif
#if defined(MOZ_THREADSTACKHELPER_PSEUDO) && defined(XP_WIN)
# define MOZ_THREADSTACKHELPER_NATIVE
# if defined(__i386__) || defined(_M_IX86)
# define MOZ_THREADSTACKHELPER_X86
# elif defined(__x86_64__) || defined(_M_X64)
# define MOZ_THREADSTACKHELPER_X64
# elif defined(__arm__) || defined(_M_ARM)
# define MOZ_THREADSTACKHELPER_ARM
# else
// Unsupported architecture
# undef MOZ_THREADSTACKHELPER_NATIVE
# endif
// NOTE: Currently, due to a problem with LUL stackwalking initialization taking
// a long time (bug 1365309), we don't perform pseudostack or native stack
// walking on Linux.
#if defined(XP_LINUX)
# undef MOZ_THREADSTACKHELPER_NATIVE
# undef MOZ_THREADSTACKHELPER_PSEUDO
#endif
namespace mozilla {
@ -67,12 +62,15 @@ public:
typedef Telemetry::NativeHangStack NativeStack;
private:
Stack* mStackToFill;
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
Stack* mStackToFill;
const PseudoStack* const mPseudoStack;
size_t mMaxStackSize;
size_t mMaxBufferSize;
#endif
#ifdef MOZ_THREADSTACKHELPER_NATIVE
NativeStack* mNativeStackToFill;
#endif
bool PrepareStackBuffer(Stack& aStack);
void FillStackBuffer();
@ -83,22 +81,11 @@ private:
#endif
public:
/**
* Initialize ThreadStackHelper. Must be called from main thread.
*/
static void Startup();
/**
* Uninitialize ThreadStackHelper. Must be called from main thread.
*/
static void Shutdown();
/**
* Create a ThreadStackHelper instance targeting the current thread.
*/
ThreadStackHelper();
~ThreadStackHelper();
/**
* Retrieve the current pseudostack of the thread associated
* with this ThreadStackHelper.
@ -130,27 +117,9 @@ private:
// If only aStack needs to be collected, nullptr may be passed for
// aNativeStack, and vice versa.
void GetStacksInternal(Stack* aStack, NativeStack* aNativeStack);
#if defined(XP_LINUX)
private:
static int sInitialized;
static int sFillStackSignum;
static void FillStackHandler(int aSignal, siginfo_t* aInfo, void* aContext);
sem_t mSem;
pid_t mThreadID;
#elif defined(XP_WIN)
private:
bool mInitialized;
HANDLE mThreadID;
void* mStackTop;
#elif defined(XP_MACOSX)
private:
thread_act_t mThreadID;
#endif
// The profiler's unique thread identifier for the target thread.
int mThreadId;
};
} // namespace mozilla