merge autoland to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2017-01-20 15:21:47 +01:00
Родитель 0367e7729d c9370d609b
Коммит 3ec1815acd
53 изменённых файлов: 1474 добавлений и 1397 удалений

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

@ -502,7 +502,8 @@ const gExtensionsNotifications = {
updateAlerts() {
let sideloaded = ExtensionsUI.sideloaded;
if (sideloaded.size == 0) {
let updates = ExtensionsUI.updates;
if (sideloaded.size + updates.size == 0) {
gMenuButtonBadgeManager.removeBadge(gMenuButtonBadgeManager.BADGEID_ADDONS);
} else {
gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_ADDONS,
@ -519,6 +520,23 @@ const gExtensionsNotifications = {
const DEFAULT_EXTENSION_ICON =
"chrome://mozapps/skin/extensions/extensionGeneric.svg";
let items = 0;
for (let update of updates) {
if (++items > 4) {
break;
}
let button = document.createElement("toolbarbutton");
button.setAttribute("label", `"${update.addon.name}" requires new permissions`);
let icon = update.addon.iconURL || DEFAULT_EXTENSION_ICON;
button.setAttribute("image", icon);
button.addEventListener("click", evt => {
ExtensionsUI.showUpdate(gBrowser, update);
});
container.appendChild(button);
}
for (let addon of sideloaded) {
if (++items > 4) {
break;

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

@ -7412,10 +7412,12 @@ var gIdentityHandler = {
// If the permission item we were looking for doesn't exist,
// the user has temporarily allowed sharing and we need to add
// an item in the permissions array to reflect this.
let permission =
SitePermissions.getPermissionDetails(id, SitePermissions.SCOPE_REQUEST);
permission.inUse = true;
permissions.push(permission);
permissions.push({
id,
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_REQUEST,
inUse: true,
});
}
}
}
@ -7476,7 +7478,7 @@ var gIdentityHandler = {
state = SitePermissions.ALLOW;
scope = SitePermissions.SCOPE_REQUEST;
}
stateLabel.textContent = SitePermissions.getStateLabel(state, scope);
stateLabel.textContent = SitePermissions.getCurrentStateLabel(state, scope);
let button = document.createElement("button");
button.setAttribute("class", "identity-popup-permission-remove-button");

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

@ -135,7 +135,7 @@ function createRow(aPartId) {
for (let state of SitePermissions.getAvailableStates(aPartId)) {
let radio = document.createElement("radio");
radio.setAttribute("id", aPartId + "#" + state);
radio.setAttribute("label", SitePermissions.getStateLabel(state));
radio.setAttribute("label", SitePermissions.getMultichoiceStateLabel(state));
radio.setAttribute("command", commandId);
radiogroup.appendChild(radio);
}

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

@ -120,6 +120,9 @@ support-files =
file_install_extensions.html
browser_webext_permissions.xpi
browser_webext_nopermissions.xpi
browser_webext_update1.xpi
browser_webext_update2.xpi
browser_webext_update.json
!/image/test/mochitest/blue.png
!/toolkit/components/passwordmgr/test/browser/form_basic.html
!/toolkit/components/passwordmgr/test/browser/insecure_test.html
@ -306,6 +309,7 @@ skip-if = os == "mac" # decoder doctor isn't implemented on osx
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
[browser_extension_permissions.js]
[browser_extension_sideloading.js]
[browser_extension_update.js]
[browser_favicon_change.js]
[browser_favicon_change_not_in_document.js]
[browser_findbarClose.js]

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

@ -0,0 +1,192 @@
const {AddonManagerPrivate} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
const URL_BASE = "https://example.com/browser/browser/base/content/test/general";
const ID = "update@tests.mozilla.org";
function promiseViewLoaded(tab, viewid) {
let win = tab.linkedBrowser.contentWindow;
if (win.gViewController && !win.gViewController.isLoading &&
win.gViewController.currentViewId == viewid) {
return Promise.resolve();
}
return new Promise(resolve => {
function listener() {
if (win.gViewController.currentViewId != viewid) {
return;
}
win.document.removeEventListener("ViewChanged", listener);
resolve();
}
win.document.addEventListener("ViewChanged", listener);
});
}
function promisePopupNotificationShown(name) {
return new Promise(resolve => {
function popupshown() {
let notification = PopupNotifications.getNotification(name);
if (!notification) { return; }
ok(notification, `${name} notification shown`);
ok(PopupNotifications.isPanelOpen, "notification panel open");
PopupNotifications.panel.removeEventListener("popupshown", popupshown);
resolve(PopupNotifications.panel.firstChild);
}
PopupNotifications.panel.addEventListener("popupshown", popupshown);
});
}
function getBadgeStatus() {
let menuButton = document.getElementById("PanelUI-menu-button");
return menuButton.getAttribute("badge-status");
}
function promiseUpdateDownloaded(addon) {
return new Promise(resolve => {
let listener = {
onDownloadEnded(install) {
if (install.addon.id == addon.id) {
AddonManager.removeInstallListener(listener);
resolve();
}
},
};
AddonManager.addInstallListener(listener);
});
}
function promiseUpgrade(addon) {
return new Promise(resolve => {
let listener = {
onInstallEnded(install, newAddon) {
if (newAddon.id == addon.id) {
AddonManager.removeInstallListener(listener);
resolve(newAddon);
}
},
};
AddonManager.addInstallListener(listener);
});
}
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [
// Turn on background updates
["extensions.update.enabled", true],
// Point updates to the local mochitest server
["extensions.update.background.url", `${URL_BASE}/browser_webext_update.json`],
// We don't have pre-pinned certificates for the local mochitest server
["extensions.install.requireBuiltInCerts", false],
["extensions.update.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
// Install version 1.0 of the test extension
let url1 = `${URL_BASE}/browser_webext_update1.xpi`;
let install = yield AddonManager.getInstallForURL(url1, null, "application/x-xpinstall");
ok(install, "Created install");
let addon = yield new Promise(resolve => {
install.addListener({
onInstallEnded(_install, _addon) {
resolve(_addon);
},
});
install.install();
});
ok(addon, "Addon was installed");
is(getBadgeStatus(), "", "Should not start out with an addon alert badge");
// Trigger an update check and wait for the update for this addon
// to be downloaded.
let updatePromise = promiseUpdateDownloaded(addon);
AddonManagerPrivate.backgroundUpdateCheck();
yield updatePromise;
is(getBadgeStatus(), "addon-alert", "Should have addon alert badge");
// Find the menu entry for the update
yield PanelUI.show();
let addons = document.getElementById("PanelUI-footer-addons");
is(addons.children.length, 1, "Have a menu entry for the update");
// Click the menu item
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
addons.children[0].click();
// about:addons should load and go to the list of extensions
let tab = yield tabPromise;
is(tab.linkedBrowser.currentURI.spec, "about:addons");
const VIEW = "addons://list/extension";
yield promiseViewLoaded(tab, VIEW);
let win = tab.linkedBrowser.contentWindow;
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
// Wait for the permission prompt and cancel it
let panel = yield popupPromise;
panel.secondaryButton.click();
addon = yield AddonManager.getAddonByID(ID);
is(addon.version, "1.0", "Should still be running the old version");
yield BrowserTestUtils.removeTab(tab);
// Alert badge and hamburger menu items should be gone
is(getBadgeStatus(), "", "Addon alert badge should be gone");
yield PanelUI.show();
addons = document.getElementById("PanelUI-footer-addons");
is(addons.children.length, 0, "Update menu entries should be gone");
yield PanelUI.hide();
// Re-check for an update
updatePromise = promiseUpdateDownloaded(addon);
yield AddonManagerPrivate.backgroundUpdateCheck();
yield updatePromise;
is(getBadgeStatus(), "addon-alert", "Should have addon alert badge");
// Find the menu entry for the update
yield PanelUI.show();
addons = document.getElementById("PanelUI-footer-addons");
is(addons.children.length, 1, "Have a menu entry for the update");
// Click the menu item
tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
popupPromise = promisePopupNotificationShown("addon-webext-permissions");
addons.children[0].click();
// Wait for about:addons to load
tab = yield tabPromise;
is(tab.linkedBrowser.currentURI.spec, "about:addons");
yield promiseViewLoaded(tab, VIEW);
win = tab.linkedBrowser.contentWindow;
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
// Wait for the permission prompt and accept it this time
updatePromise = promiseUpgrade(addon);
panel = yield popupPromise;
panel.button.click();
addon = yield updatePromise;
is(addon.version, "2.0", "Should have upgraded to the new version");
yield BrowserTestUtils.removeTab(tab);
is(getBadgeStatus(), "", "Addon alert badge should be gone");
});

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

@ -0,0 +1,18 @@
{
"addons": {
"update@tests.mozilla.org": {
"updates": [
{
"version": "2.0",
"update_link": "https://example.com/browser/browser/base/content/test/general/browser_webext_update2.xpi",
"applications": {
"gecko": {
"strict_min_version": "1",
"advisory_max_version": "55.0"
}
}
}
]
}
}
}

Двоичные данные
browser/base/content/test/general/browser_webext_update1.xpi Normal file

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

Двоичные данные
browser/base/content/test/general/browser_webext_update2.xpi Normal file

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

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

@ -2,12 +2,28 @@
# 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/.
allow = Allow
allowForSession = Allow for Session
allowTemporarily = Allow Temporarily
block = Block
blockTemporarily = Block Temporarily
alwaysAsk = Always Ask
# LOCALIZATION NOTE (state.current.allowed,
# state.current.allowedForSession,
# state.current.allowedTemporarily,
# state.current.blockedTemporarily,
# state.current.blocked):
# This label is used to display active permission states in the site
# identity popup (which does not have a lot of screen space).
state.current.allowed = Allowed
state.current.allowedForSession = Allowed for Session
state.current.allowedTemporarily = Allowed Temporarily
state.current.blockedTemporarily = Blocked Temporarily
state.current.blocked = Blocked
# LOCALIZATION NOTE (state.multichoice.alwaysAsk,
# state.multichoice.allow,
# state.multichoice.allowForSession,
# state.multichoice.block):
# Used to label permission state checkboxes in the page info dialog.
state.multichoice.alwaysAsk = Always Ask
state.multichoice.allow = Allow
state.multichoice.allowForSession = Allow for Session
state.multichoice.block = Block
permission.cookie.label = Set Cookies
permission.desktop-notification2.label = Receive Notifications

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

@ -26,9 +26,11 @@ const HTML_NS = "http://www.w3.org/1999/xhtml";
this.ExtensionsUI = {
sideloaded: new Set(),
updates: new Set(),
init() {
Services.obs.addObserver(this, "webextension-permission-prompt", false);
Services.obs.addObserver(this, "webextension-update-permissions", false);
this._checkForSideloaded();
},
@ -60,11 +62,7 @@ this.ExtensionsUI = {
});
},
showSideloaded(browser, addon) {
addon.markAsSeen();
this.sideloaded.delete(addon);
this.emit("change");
showAddonsManager(browser, info) {
let loadPromise = new Promise(resolve => {
let listener = (subject, topic) => {
if (subject.location.href == "about:addons") {
@ -76,16 +74,41 @@ this.ExtensionsUI = {
});
let tab = browser.addTab("about:addons");
browser.selectedTab = tab;
loadPromise.then(win => {
return loadPromise.then(win => {
win.loadView("addons://list/extension");
let info = {
addon,
icon: addon.iconURL,
type: "sideload",
};
this.showPermissionsPrompt(browser.selectedBrowser, info).then(answer => {
addon.userDisabled = !answer;
});
return this.showPermissionsPrompt(browser.selectedBrowser, info);
});
},
showSideloaded(browser, addon) {
addon.markAsSeen();
this.sideloaded.delete(addon);
this.emit("change");
let info = {
addon,
permissions: addon.userPermissions,
icon: addon.iconURL,
type: "sideload",
};
this.showAddonsManager(browser, info).then(answer => {
addon.userDisabled = !answer;
});
},
showUpdate(browser, info) {
info.type = "update";
this.showAddonsManager(browser, info).then(answer => {
if (answer) {
info.resolve();
} else {
info.reject();
}
// At the moment, this prompt will re-appear next time we do an update
// check. See bug 1332360 for proposal to avoid this.
this.updates.delete(info);
this.emit("change");
});
},
@ -101,15 +124,26 @@ this.ExtensionsUI = {
progressNotification.remove();
}
this.showPermissionsPrompt(target, info).then(answer => {
let reply = answer => {
Services.obs.notifyObservers(subject, "webextension-permission-response",
JSON.stringify(answer));
});
};
let perms = info.addon.userPermissions;
if (!perms) {
reply(true);
} else {
info.permissions = perms;
this.showPermissionsPrompt(target, info).then(reply);
}
} else if (topic == "webextension-update-permissions") {
this.updates.add(subject.wrappedJSObject);
this.emit("change");
}
},
showPermissionsPrompt(target, info) {
let perms = info.addon.userPermissions;
let perms = info.permissions;
if (!perms) {
return Promise.resolve();
}
@ -147,6 +181,11 @@ this.ExtensionsUI = {
acceptKey = "E";
cancelText = "Disable";
cancelKey = "D";
} else if (info.type == "update") {
header = "";
text = `${name} has been updated. You must approve new permissions before the updated version will install.`;
acceptText = "Update";
acceptKey = "U";
}
let formatPermission = perm => {

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

@ -183,34 +183,6 @@ this.SitePermissions = {
return result;
},
/**
* Returns detailed information on the specified permission.
*
* @param {String} id
* The permissionID of the permission.
* @param {SitePermissions scope} scope
* The current scope of the permission.
* @param {SitePermissions state} state (optional)
* The current state of the permission.
* Will default to the default state if omitted.
*
* @return {Object} an object with the keys:
* - id: the permissionID of the permission
* - label: the localized label
* - state: the passed in state argument
* - scope: the passed in scope argument
* - availableStates: an array of all available states for that permission,
* represented as objects with the keys:
* - id: the state constant
* - label: the translated label of that state
*/
getPermissionDetails(id, scope, state = this.getDefault(id)) {
let availableStates = this.getAvailableStates(id).map(val => {
return { id: val, label: this.getStateLabel(val) };
});
return {id, label: this.getPermissionLabel(id), state, scope, availableStates};
},
/**
* Returns all custom permissions for a given browser.
*
@ -249,11 +221,17 @@ this.SitePermissions = {
* @param {Browser} browser
* The browser to fetch permission for.
*
* @return {Array} a list of objects. See getPermissionDetails for the content of each object.
* @return {Array<Object>} a list of objects with the keys:
* - id: the permissionID of the permission
* - state: a constant representing the current permission state
* (e.g. SitePermissions.ALLOW)
* - scope: a constant representing how long the permission will
* be kept.
* - label: the localized label
*/
getAllPermissionDetailsForBrowser(browser) {
return this.getAllForBrowser(browser).map(({id, scope, state}) =>
this.getPermissionDetails(id, scope, state));
({id, scope, state, label: this.getPermissionLabel(id)}));
},
/**
@ -489,29 +467,52 @@ this.SitePermissions = {
*
* @param {SitePermissions state} state
* The state to get the label for.
* @param {SitePermissions scope} scope (optional)
* The scope to get the label for.
*
* @return {String} the localized label.
* @return {String|null} the localized label or null if an
* unknown state was passed.
*/
getStateLabel(state, scope = null) {
getMultichoiceStateLabel(state) {
switch (state) {
case this.UNKNOWN:
return gStringBundle.GetStringFromName("alwaysAsk");
return gStringBundle.GetStringFromName("state.multichoice.alwaysAsk");
case this.ALLOW:
if (scope && scope != this.SCOPE_PERSISTENT)
return gStringBundle.GetStringFromName("allowTemporarily");
return gStringBundle.GetStringFromName("allow");
return gStringBundle.GetStringFromName("state.multichoice.allow");
case this.ALLOW_COOKIES_FOR_SESSION:
return gStringBundle.GetStringFromName("allowForSession");
return gStringBundle.GetStringFromName("state.multichoice.allowForSession");
case this.BLOCK:
if (scope && scope != this.SCOPE_PERSISTENT)
return gStringBundle.GetStringFromName("blockTemporarily");
return gStringBundle.GetStringFromName("block");
return gStringBundle.GetStringFromName("state.multichoice.block");
default:
return null;
}
}
},
/**
* Returns the localized label for a permission's current state.
*
* @param {SitePermissions state} state
* The state to get the label for.
* @param {SitePermissions scope} scope (optional)
* The scope to get the label for.
*
* @return {String|null} the localized label or null if an
* unknown state was passed.
*/
getCurrentStateLabel(state, scope = null) {
switch (state) {
case this.ALLOW:
if (scope && scope != this.SCOPE_PERSISTENT)
return gStringBundle.GetStringFromName("state.current.allowedTemporarily");
return gStringBundle.GetStringFromName("state.current.allowed");
case this.ALLOW_COOKIES_FOR_SESSION:
return gStringBundle.GetStringFromName("state.current.allowedForSession");
case this.BLOCK:
if (scope && scope != this.SCOPE_PERSISTENT)
return gStringBundle.GetStringFromName("state.current.blockedTemporarily");
return gStringBundle.GetStringFromName("state.current.blocked");
default:
return null;
}
},
};
var gPermissionObject = {

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

@ -38,33 +38,21 @@ add_task(function* testGetAllPermissionDetailsForBrowser() {
label: "Use the Camera",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_PERSISTENT,
availableStates: [
{ id: SitePermissions.UNKNOWN, label: "Always Ask" },
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
// check that removed permissions (State.UNKNOWN) are skipped
// Check that removed permissions (State.UNKNOWN) are skipped.
SitePermissions.remove(uri, "camera");
permissions = SitePermissions.getAllPermissionDetailsForBrowser(tab.linkedBrowser);
camera = permissions.find(({id}) => id === "camera");
Assert.equal(camera, undefined);
// check that different available state values are represented
let cookie = permissions.find(({id}) => id === "cookie");
Assert.deepEqual(cookie, {
id: "cookie",
label: "Set Cookies",
state: SitePermissions.ALLOW_COOKIES_FOR_SESSION,
scope: SitePermissions.SCOPE_PERSISTENT,
availableStates: [
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.ALLOW_COOKIES_FOR_SESSION, label: "Allow for Session" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
let popup = permissions.find(({id}) => id === "popup");
@ -73,10 +61,6 @@ add_task(function* testGetAllPermissionDetailsForBrowser() {
label: "Open Pop-up Windows",
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_PERSISTENT,
availableStates: [
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
let geo = permissions.find(({id}) => id === "geo");
@ -85,11 +69,6 @@ add_task(function* testGetAllPermissionDetailsForBrowser() {
label: "Access Your Location",
state: SitePermissions.ALLOW,
scope: SitePermissions.SCOPE_SESSION,
availableStates: [
{ id: SitePermissions.UNKNOWN, label: "Always Ask" },
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
SitePermissions.remove(uri, "cookie");

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

@ -51,3 +51,19 @@ add_task(function* testGetAllByURI() {
Assert.deepEqual(SitePermissions.getAllByURI(uri), []);
SitePermissions.remove(uri, "addon");
});
add_task(function* testGetAvailableStates() {
Assert.deepEqual(SitePermissions.getAvailableStates("camera"),
[ SitePermissions.UNKNOWN,
SitePermissions.ALLOW,
SitePermissions.BLOCK ]);
Assert.deepEqual(SitePermissions.getAvailableStates("cookie"),
[ SitePermissions.ALLOW,
SitePermissions.ALLOW_COOKIES_FOR_SESSION,
SitePermissions.BLOCK ]);
Assert.deepEqual(SitePermissions.getAvailableStates("popup"),
[ SitePermissions.ALLOW,
SitePermissions.BLOCK ]);
});

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

@ -1277,56 +1277,11 @@ EventStateManager::IsRemoteTarget(nsIContent* target) {
return false;
}
static bool
CrossProcessSafeEvent(const WidgetEvent& aEvent)
{
switch (aEvent.mClass) {
case eKeyboardEventClass:
case eWheelEventClass:
return true;
case eMouseEventClass:
switch (aEvent.mMessage) {
case eMouseDown:
case eMouseUp:
case eMouseMove:
case eContextMenu:
case eMouseEnterIntoWidget:
case eMouseExitFromWidget:
case eMouseTouchDrag:
return true;
default:
return false;
}
case eTouchEventClass:
switch (aEvent.mMessage) {
case eTouchStart:
case eTouchMove:
case eTouchEnd:
case eTouchCancel:
return true;
default:
return false;
}
case eDragEventClass:
switch (aEvent.mMessage) {
case eDragOver:
case eDragExit:
case eDrop:
return true;
default:
return false;
}
default:
return false;
}
}
bool
EventStateManager::HandleCrossProcessEvent(WidgetEvent* aEvent,
nsEventStatus *aStatus) {
if (*aStatus == nsEventStatus_eConsumeNoDefault ||
aEvent->mFlags.mNoCrossProcessBoundaryForwarding ||
!CrossProcessSafeEvent(*aEvent)) {
!aEvent->CanBeSentToRemoteProcess()) {
return false;
}

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

@ -1566,9 +1566,11 @@ TabChild::RecvMouseEvent(const nsString& aType,
const int32_t& aModifiers,
const bool& aIgnoreRootScrollFrame)
{
APZCCallbackHelper::DispatchMouseEvent(GetPresShell(), aType, CSSPoint(aX, aY),
aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN, 0 /* Use the default value here. */);
APZCCallbackHelper::DispatchMouseEvent(GetPresShell(), aType,
CSSPoint(aX, aY), aButton, aClickCount,
aModifiers, aIgnoreRootScrollFrame,
nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN,
0 /* Use the default value here. */);
return IPC_OK();
}
@ -1603,13 +1605,15 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
// process EventStateManager code, have an input block id which they get from
// the InputAPZContext in the parent process stack. However, they did not
// actually go through the APZ code and so their mHandledByAPZ flag is false.
// Since thos events didn't go through APZ, we don't need to send notifications
// for them.
// Since thos events didn't go through APZ, we don't need to send
// notifications for them.
bool pendingLayerization = false;
if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
nsCOMPtr<nsIDocument> document(GetDocument());
pendingLayerization = APZCCallbackHelper::SendSetTargetAPZCNotification(
mPuppetWidget, document, aEvent, aGuid, aInputBlockId);
pendingLayerization =
APZCCallbackHelper::SendSetTargetAPZCNotification(mPuppetWidget, document,
aEvent, aGuid,
aInputBlockId);
}
nsEventStatus unused;
@ -1644,7 +1648,7 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
WidgetWheelEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
mPuppetWidget->GetDefaultScale());
mPuppetWidget->GetDefaultScale());
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
if (localEvent.mCanTriggerSwipe) {
@ -1669,16 +1673,18 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
mPuppetWidget->GetDefaultScale());
mPuppetWidget->GetDefaultScale());
if (localEvent.mMessage == eTouchStart && AsyncPanZoomEnabled()) {
nsCOMPtr<nsIDocument> document = GetDocument();
if (gfxPrefs::TouchActionEnabled()) {
APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(mPuppetWidget,
document, localEvent, aInputBlockId, mSetAllowedTouchBehaviorCallback);
APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(
mPuppetWidget, document, localEvent, aInputBlockId,
mSetAllowedTouchBehaviorCallback);
}
APZCCallbackHelper::SendSetTargetAPZCNotification(mPuppetWidget, document,
localEvent, aGuid, aInputBlockId);
localEvent, aGuid,
aInputBlockId);
}
// Dispatch event to content (potentially a long-running operation)
@ -1692,7 +1698,7 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
}
mAPZEventState->ProcessTouchEvent(localEvent, aGuid, aInputBlockId,
aApzResponse, status);
aApzResponse, status);
return IPC_OK();
}
@ -1782,7 +1788,8 @@ mozilla::ipc::IPCResult
TabChild::RecvNativeSynthesisResponse(const uint64_t& aObserverId,
const nsCString& aResponse)
{
mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId, aResponse.get());
mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId,
aResponse.get());
return IPC_OK();
}
@ -1825,16 +1832,16 @@ TabChild::UpdateRepeatedKeyEventEndTime(const WidgetKeyboardEvent& aEvent)
}
mozilla::ipc::IPCResult
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent,
const MaybeNativeKeyBinding& aBindings)
{
if (SkipRepeatedKeyEvent(event)) {
if (SkipRepeatedKeyEvent(aEvent)) {
return IPC_OK();
}
AutoCacheNativeKeyCommands autoCache(mPuppetWidget);
if (event.mMessage == eKeyPress) {
if (aEvent.mMessage == eKeyPress) {
// If content code called preventDefault() on a keydown event, then we don't
// want to process any following keypress events.
if (mIgnoreKeyPressEvent) {
@ -1850,7 +1857,7 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
}
}
WidgetKeyboardEvent localEvent(event);
WidgetKeyboardEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
@ -1858,7 +1865,7 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
// some incoming events in case event handling took long time.
UpdateRepeatedKeyEventEndTime(localEvent);
if (event.mMessage == eKeyDown) {
if (aEvent.mMessage == eKeyDown) {
mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
}
@ -1894,22 +1901,22 @@ TabChild::RecvKeyEvent(const nsString& aType,
}
mozilla::ipc::IPCResult
TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
TabChild::RecvCompositionEvent(const WidgetCompositionEvent& aEvent)
{
WidgetCompositionEvent localEvent(event);
WidgetCompositionEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
Unused << SendOnEventNeedingAckHandled(event.mMessage);
Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
return IPC_OK();
}
mozilla::ipc::IPCResult
TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
TabChild::RecvSelectionEvent(const WidgetSelectionEvent& aEvent)
{
WidgetSelectionEvent localEvent(event);
WidgetSelectionEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
Unused << SendOnEventNeedingAckHandled(event.mMessage);
Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
return IPC_OK();
}
@ -1935,7 +1942,8 @@ TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer,
return IPC_OK();
}
nsCOMPtr<nsICommandParams> params = do_CreateInstance("@mozilla.org/embedcomp/command-params;1", &rv);
nsCOMPtr<nsICommandParams> params =
do_CreateInstance("@mozilla.org/embedcomp/command-params;1", &rv);
NS_ENSURE_SUCCESS(rv, IPC_OK());
rv = params->SetISupportsValue("transferable", trans);

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

@ -1058,7 +1058,8 @@ TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
if (!mIsDestroyed) {
Unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
aButton, aClickCount,
aModifiers, aIgnoreRootScrollFrame);
aModifiers,
aIgnoreRootScrollFrame);
}
}
@ -1069,31 +1070,34 @@ TabParent::SendKeyEvent(const nsAString& aType,
int32_t aModifiers,
bool aPreventDefault)
{
if (!mIsDestroyed) {
Unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
aModifiers, aPreventDefault);
if (mIsDestroyed) {
return;
}
Unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
aModifiers, aPreventDefault);
}
bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
bool
TabParent::SendRealMouseEvent(WidgetMouseEvent& aEvent)
{
if (mIsDestroyed) {
return false;
}
event.mRefPoint += GetChildProcessOffset();
aEvent.mRefPoint += GetChildProcessOffset();
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
// When we mouseenter the tab, the tab's cursor should
// become the current cursor. When we mouseexit, we stop.
if (eMouseEnterIntoWidget == event.mMessage) {
if (eMouseEnterIntoWidget == aEvent.mMessage) {
mTabSetsCursor = true;
if (mCustomCursor) {
widget->SetCursor(mCustomCursor, mCustomCursorHotspotX, mCustomCursorHotspotY);
widget->SetCursor(mCustomCursor,
mCustomCursorHotspotX, mCustomCursorHotspotY);
} else if (mCursor != nsCursor(-1)) {
widget->SetCursor(mCursor);
}
} else if (eMouseExitFromWidget == event.mMessage) {
} else if (eMouseExitFromWidget == aEvent.mMessage) {
mTabSetsCursor = false;
}
}
@ -1102,15 +1106,15 @@ bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
uint64_t blockId;
ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
if (eMouseMove == event.mMessage) {
if (event.mReason == WidgetMouseEvent::eSynthesized) {
return SendSynthMouseMoveEvent(event, guid, blockId);
if (eMouseMove == aEvent.mMessage) {
if (aEvent.mReason == WidgetMouseEvent::eSynthesized) {
return SendSynthMouseMoveEvent(aEvent, guid, blockId);
} else {
return SendRealMouseMoveEvent(event, guid, blockId);
return SendRealMouseMoveEvent(aEvent, guid, blockId);
}
}
return SendRealMouseButtonEvent(event, guid, blockId);
return SendRealMouseButtonEvent(aEvent, guid, blockId);
}
LayoutDeviceToCSSScale
@ -1126,22 +1130,24 @@ TabParent::GetLayoutDeviceToCSSScale()
}
bool
TabParent::SendRealDragEvent(WidgetDragEvent& event, uint32_t aDragAction,
TabParent::SendRealDragEvent(WidgetDragEvent& aEvent, uint32_t aDragAction,
uint32_t aDropEffect)
{
if (mIsDestroyed) {
return false;
}
event.mRefPoint += GetChildProcessOffset();
return PBrowserParent::SendRealDragEvent(event, aDragAction, aDropEffect);
aEvent.mRefPoint += GetChildProcessOffset();
return PBrowserParent::SendRealDragEvent(aEvent, aDragAction, aDropEffect);
}
LayoutDevicePoint TabParent::AdjustTapToChildWidget(const LayoutDevicePoint& aPoint)
LayoutDevicePoint
TabParent::AdjustTapToChildWidget(const LayoutDevicePoint& aPoint)
{
return aPoint + LayoutDevicePoint(GetChildProcessOffset());
}
bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
bool
TabParent::SendMouseWheelEvent(WidgetWheelEvent& aEvent)
{
if (mIsDestroyed) {
return false;
@ -1150,8 +1156,8 @@ bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
ScrollableLayerGuid guid;
uint64_t blockId;
ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
event.mRefPoint += GetChildProcessOffset();
return PBrowserParent::SendMouseWheelEvent(event, guid, blockId);
aEvent.mRefPoint += GetChildProcessOffset();
return PBrowserParent::SendMouseWheelEvent(aEvent, guid, blockId);
}
mozilla::ipc::IPCResult
@ -1205,7 +1211,8 @@ TabParent::RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent)
static void
DoCommandCallback(mozilla::Command aCommand, void* aData)
{
static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->AppendElement(aCommand);
static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->
AppendElement(aCommand);
}
mozilla::ipc::IPCResult
@ -1229,12 +1236,15 @@ TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
return IPC_OK();
}
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
localEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
localEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
localEvent, DoCommandCallback, &richText);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForSingleLineEditor,
localEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForMultiLineEditor,
localEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor,
localEvent, DoCommandCallback, &richText);
if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
*aBindings = NativeKeyBinding(singleLine, multiLine, richText);
@ -1265,7 +1275,8 @@ public:
return NS_OK;
}
if (!mTabParent->SendNativeSynthesisResponse(mObserverId, nsCString(aTopic))) {
if (!mTabParent->SendNativeSynthesisResponse(mObserverId,
nsCString(aTopic))) {
NS_WARNING("Unable to send native event synthesization response!");
}
// Null out tabparent to indicate we already sent the response
@ -1320,8 +1331,9 @@ TabParent::RecvSynthesizeNativeKeyEvent(const int32_t& aNativeKeyboardLayout,
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
widget->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
aModifierFlags, aCharacters, aUnmodifiedCharacters,
responder.GetObserver());
aModifierFlags, aCharacters,
aUnmodifiedCharacters,
responder.GetObserver());
}
return IPC_OK();
}
@ -1336,7 +1348,7 @@ TabParent::RecvSynthesizeNativeMouseEvent(const LayoutDeviceIntPoint& aPoint,
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
widget->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, aModifierFlags,
responder.GetObserver());
responder.GetObserver());
}
return IPC_OK();
}
@ -1354,38 +1366,42 @@ TabParent::RecvSynthesizeNativeMouseMove(const LayoutDeviceIntPoint& aPoint,
}
mozilla::ipc::IPCResult
TabParent::RecvSynthesizeNativeMouseScrollEvent(const LayoutDeviceIntPoint& aPoint,
const uint32_t& aNativeMessage,
const double& aDeltaX,
const double& aDeltaY,
const double& aDeltaZ,
const uint32_t& aModifierFlags,
const uint32_t& aAdditionalFlags,
const uint64_t& aObserverId)
TabParent::RecvSynthesizeNativeMouseScrollEvent(
const LayoutDeviceIntPoint& aPoint,
const uint32_t& aNativeMessage,
const double& aDeltaX,
const double& aDeltaY,
const double& aDeltaZ,
const uint32_t& aModifierFlags,
const uint32_t& aAdditionalFlags,
const uint64_t& aObserverId)
{
AutoSynthesizedEventResponder responder(this, aObserverId, "mousescrollevent");
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
widget->SynthesizeNativeMouseScrollEvent(aPoint, aNativeMessage,
aDeltaX, aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags,
responder.GetObserver());
aDeltaX, aDeltaY, aDeltaZ,
aModifierFlags, aAdditionalFlags,
responder.GetObserver());
}
return IPC_OK();
}
mozilla::ipc::IPCResult
TabParent::RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId,
const TouchPointerState& aPointerState,
const LayoutDeviceIntPoint& aPoint,
const double& aPointerPressure,
const uint32_t& aPointerOrientation,
const uint64_t& aObserverId)
TabParent::RecvSynthesizeNativeTouchPoint(
const uint32_t& aPointerId,
const TouchPointerState& aPointerState,
const LayoutDeviceIntPoint& aPoint,
const double& aPointerPressure,
const uint32_t& aPointerOrientation,
const uint64_t& aObserverId)
{
AutoSynthesizedEventResponder responder(this, aObserverId, "touchpoint");
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
widget->SynthesizeNativeTouchPoint(aPointerId, aPointerState, aPoint,
aPointerPressure, aPointerOrientation, responder.GetObserver());
aPointerPressure, aPointerOrientation,
responder.GetObserver());
}
return IPC_OK();
}
@ -1414,38 +1430,43 @@ TabParent::RecvClearNativeTouchSequence(const uint64_t& aObserverId)
return IPC_OK();
}
bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event)
bool
TabParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent)
{
if (mIsDestroyed) {
return false;
}
event.mRefPoint += GetChildProcessOffset();
aEvent.mRefPoint += GetChildProcessOffset();
MaybeNativeKeyBinding bindings;
bindings = void_t();
if (event.mMessage == eKeyPress) {
if (aEvent.mMessage == eKeyPress) {
nsCOMPtr<nsIWidget> widget = GetWidget();
AutoTArray<mozilla::CommandInt, 4> singleLine;
AutoTArray<mozilla::CommandInt, 4> multiLine;
AutoTArray<mozilla::CommandInt, 4> richText;
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
event, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
event, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
event, DoCommandCallback, &richText);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForSingleLineEditor,
aEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForMultiLineEditor,
aEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor,
aEvent, DoCommandCallback, &richText);
if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
bindings = NativeKeyBinding(singleLine, multiLine, richText);
}
}
return PBrowserParent::SendRealKeyEvent(event, bindings);
return PBrowserParent::SendRealKeyEvent(aEvent, bindings);
}
bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
bool
TabParent::SendRealTouchEvent(WidgetTouchEvent& aEvent)
{
if (mIsDestroyed) {
return false;
@ -1455,10 +1476,10 @@ bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
// confuses remote content and the panning and zooming logic into thinking
// that the added touches are part of the touchend/cancel, when actually
// they're not.
if (event.mMessage == eTouchEnd || event.mMessage == eTouchCancel) {
for (int i = event.mTouches.Length() - 1; i >= 0; i--) {
if (!event.mTouches[i]->mChanged) {
event.mTouches.RemoveElementAt(i);
if (aEvent.mMessage == eTouchEnd || aEvent.mMessage == eTouchCancel) {
for (int i = aEvent.mTouches.Length() - 1; i >= 0; i--) {
if (!aEvent.mTouches[i]->mChanged) {
aEvent.mTouches.RemoveElementAt(i);
}
}
}
@ -1473,13 +1494,13 @@ bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
}
LayoutDeviceIntPoint offset = GetChildProcessOffset();
for (uint32_t i = 0; i < event.mTouches.Length(); i++) {
event.mTouches[i]->mRefPoint += offset;
for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) {
aEvent.mTouches[i]->mRefPoint += offset;
}
return (event.mMessage == eTouchMove) ?
PBrowserParent::SendRealTouchMoveEvent(event, guid, blockId, apzResponse) :
PBrowserParent::SendRealTouchEvent(event, guid, blockId, apzResponse);
return (aEvent.mMessage == eTouchMove) ?
PBrowserParent::SendRealTouchMoveEvent(aEvent, guid, blockId, apzResponse) :
PBrowserParent::SendRealTouchEvent(aEvent, guid, blockId, apzResponse);
}
bool
@ -1497,8 +1518,8 @@ TabParent::SendHandleTap(TapType aType,
GetRenderFrame()->TakeFocusForClickFromTap();
}
LayoutDeviceIntPoint offset = GetChildProcessOffset();
return PBrowserParent::SendHandleTap(aType, aPoint + offset, aModifiers, aGuid,
aInputBlockId);
return PBrowserParent::SendHandleTap(aType, aPoint + offset, aModifiers,
aGuid, aInputBlockId);
}
mozilla::ipc::IPCResult
@ -1705,13 +1726,14 @@ TabParent::RecvNotifyIMETextChange(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
if (!widget) {
return IPC_OK();
}
#ifdef DEBUG
nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
NS_ASSERTION(updatePreference.WantTextChange(),
"Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
"Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
#endif
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
@ -1728,7 +1750,6 @@ TabParent::RecvNotifyIMECompositionUpdate(
if (!widget) {
return IPC_OK();
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return IPC_OK();
@ -1739,9 +1760,9 @@ TabParent::RecvNotifyIMESelection(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
if (!widget) {
return IPC_OK();
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return IPC_OK();
@ -1783,7 +1804,6 @@ TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
if (!widget) {
return IPC_OK();
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return IPC_OK();
@ -1940,11 +1960,11 @@ TabParent::GetChildProcessOffset()
}
mozilla::ipc::IPCResult
TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event)
TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent)
{
NS_ENSURE_TRUE(mFrameElement, IPC_OK());
WidgetKeyboardEvent localEvent(event);
WidgetKeyboardEvent localEvent(aEvent);
// Mark the event as not to be dispatched to remote process again.
localEvent.StopCrossProcessForwarding();
@ -2012,20 +2032,20 @@ TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
}
bool
TabParent::SendCompositionEvent(WidgetCompositionEvent& event)
TabParent::SendCompositionEvent(WidgetCompositionEvent& aEvent)
{
if (mIsDestroyed) {
return false;
}
if (!mContentCache.OnCompositionEvent(event)) {
if (!mContentCache.OnCompositionEvent(aEvent)) {
return true;
}
return PBrowserParent::SendCompositionEvent(event);
return PBrowserParent::SendCompositionEvent(aEvent);
}
bool
TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
TabParent::SendSelectionEvent(WidgetSelectionEvent& aEvent)
{
if (mIsDestroyed) {
return false;
@ -2034,11 +2054,11 @@ TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
if (!widget) {
return true;
}
mContentCache.OnSelectionEvent(event);
if (NS_WARN_IF(!PBrowserParent::SendSelectionEvent(event))) {
mContentCache.OnSelectionEvent(aEvent);
if (NS_WARN_IF(!PBrowserParent::SendSelectionEvent(aEvent))) {
return false;
}
event.mSucceeded = true;
aEvent.mSucceeded = true;
return true;
}

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

@ -454,17 +454,17 @@ public:
int32_t aCharCode, int32_t aModifiers,
bool aPreventDefault);
bool SendRealMouseEvent(mozilla::WidgetMouseEvent& event);
bool SendRealMouseEvent(mozilla::WidgetMouseEvent& aEvent);
bool SendRealDragEvent(mozilla::WidgetDragEvent& aEvent,
uint32_t aDragAction,
uint32_t aDropEffect);
bool SendMouseWheelEvent(mozilla::WidgetWheelEvent& event);
bool SendMouseWheelEvent(mozilla::WidgetWheelEvent& aEvent);
bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event);
bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& aEvent);
bool SendRealTouchEvent(WidgetTouchEvent& event);
bool SendRealTouchEvent(WidgetTouchEvent& aEvent);
bool SendHandleTap(TapType aType,
const LayoutDevicePoint& aPoint,
@ -512,9 +512,9 @@ public:
bool HandleQueryContentEvent(mozilla::WidgetQueryContentEvent& aEvent);
bool SendCompositionEvent(mozilla::WidgetCompositionEvent& event);
bool SendCompositionEvent(mozilla::WidgetCompositionEvent& aEvent);
bool SendSelectionEvent(mozilla::WidgetSelectionEvent& event);
bool SendSelectionEvent(mozilla::WidgetSelectionEvent& aEvent);
bool SendPasteTransferable(const IPCDataTransfer& aDataTransfer,
const bool& aIsPrivateData,

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

@ -3959,8 +3959,13 @@ var gCSSProperties = {
domProp: "width",
inherited: false,
type: CSS_TYPE_LONGHAND,
/* computed value tests for width test more with display:block */
prerequisites: { "display": "block" },
prerequisites: {
// computed value tests for width test more with display:block
"display": "block",
// add some margin to avoid the initial "auto" value getting
// resolved to the same length as the parent element.
"margin-left": "5px",
},
initial_values: [ " auto" ],
/* XXX these have prerequisites */
other_values: [ "15px", "3em", "15%",
@ -5106,7 +5111,12 @@ var gCSSProperties = {
get_computed: logical_axis_prop_get_computed,
/* XXX testing auto has prerequisites */
initial_values: [ "auto" ],
prerequisites: { "display": "block" },
prerequisites: {
"display": "block",
// add some margin to avoid the initial "auto" value getting
// resolved to the same length as the parent element.
"margin-left": "5px",
},
other_values: [ "15px", "3em", "15%",
// these three keywords compute to the initial value only when the
// writing mode is vertical, and we're testing with a horizontal

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

@ -22,6 +22,7 @@
/** Test for computation of CSS 'inherit' on all properties and 'unset' on
inherited properties **/
var gDisplayTree = document.getElementById("display");
// elements without a frame
var gNParent = document.getElementById("nparent");
var gNChild = document.getElementById("nchild");
@ -127,9 +128,15 @@ function test_property(property)
is(inherit_initial_computed_n, initial_computed_n,
keyword + " should cause inheritance of initial value for '" +
property + "'");
is(inherit_initial_computed_f, initial_computed_f,
keyword + " should cause inheritance of initial value for '" +
property + "'");
// For width and inline-size, getComputedStyle returns used value
// when the element is displayed. Their initial value "auto" makes
// the element fill available space of the parent, so it doesn't
// make sense to compare it with the value we get before.
if (property != "width" && property != "inline-size") {
is(inherit_initial_computed_f, initial_computed_f,
keyword + " should cause inheritance of initial value for '" +
property + "'");
}
gParentRuleTop.style.removeProperty(property);
gChildRule1.style.removeProperty(property);
gChildRule2.style.removeProperty(property);
@ -142,10 +149,22 @@ function test_property(property)
gChildRuleTop.style.removeProperty(prereq);
}
}
// FIXME -moz-binding value makes gElementF and its parent loses
// their frame. Force it to get recreated after each property.
// See bug 1331903.
gDisplayTree.style.display = "none";
get_computed_value(getComputedStyle(gFChild, ""), "width");
gDisplayTree.style.display = "";
get_computed_value(getComputedStyle(gFChild, ""), "width");
});
}
for (var prop in gCSSProperties) {
// Skip -moz-binding because it effectively drops the frame.
if (prop == "-moz-binding") {
continue;
}
var info = gCSSProperties[prop];
gChildRule3.style.setProperty(prop, info.other_values[0], "");
}

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

@ -46,6 +46,7 @@ function xfail_initial(property) {
return property in gBrokenInitial;
}
var gDisplayTree = document.getElementById("display");
var gElementN = document.getElementById("elementn");
var gElementF = document.getElementById("elementf");
var gStyleSheet = document.getElementById("stylesheet").sheet;
@ -136,13 +137,12 @@ function test_property(property)
gElementF.parentNode.style.removeProperty(property);
}
// FIXME: Something (maybe with the -moz-binding values in
// test_value_computation.html, but may as well do it here to match)
// causes gElementF's frame to get lost. Force it to get recreated
// after each property.
gElementF.parentNode.style.display = "none";
// FIXME -moz-binding value makes gElementF and its parent loses
// their frame. Force it to get recreated after each property.
// See bug 1331903.
gDisplayTree.style.display = "none";
get_computed_value(getComputedStyle(gElementF, ""), "width");
gElementF.parentNode.style.display = "";
gDisplayTree.style.display = "";
get_computed_value(getComputedStyle(gElementF, ""), "width");
});
}

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

@ -104,6 +104,7 @@ function swap_when_frame(property, value) {
gSwapInitialWhenHaveFrame[property].indexOf(value) != -1;
}
var gDisplayTree = document.getElementById("display");
var gElementN = document.getElementById("elementn");
var gElementF = document.getElementById("elementf");
var gStyleSheet = document.getElementById("stylesheet").sheet;
@ -206,12 +207,12 @@ function test_value(property, val, is_initial)
gElementF.parentNode.style.removeProperty(property);
}
// FIXME: Something (maybe with the -moz-binding values) causes
// gElementF's frame to get lost. Force it to get recreated after
// each property.
gElementF.parentNode.style.display = "none";
// FIXME -moz-binding value makes gElementF and its parent loses
// their frame. Force it to get recreated after each property.
// See bug 1331903.
gDisplayTree.style.display = "none";
get_computed_value(getComputedStyle(gElementF, ""), "width");
gElementF.parentNode.style.display = "";
gDisplayTree.style.display = "";
get_computed_value(getComputedStyle(gElementF, ""), "width");
}

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

@ -35,6 +35,8 @@ using namespace stagefright;
namespace mp4_demuxer
{
static LazyLogModule sLog("MP4Metadata");
class DataSourceAdapter : public DataSource
{
public:
@ -197,8 +199,6 @@ TrackTypeToString(mozilla::TrackInfo::TrackType aType)
uint32_t
MP4Metadata::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
{
static LazyLogModule sLog("MP4Metadata");
uint32_t numTracks = mStagefright->GetNumberTracks(aType);
#ifdef MOZ_RUST_MP4PARSE
@ -616,7 +616,6 @@ bool
RustStreamAdaptor::Read(uint8_t* buffer, uintptr_t size, size_t* bytes_read)
{
if (!mOffset.isValid()) {
static LazyLogModule sLog("MP4Metadata");
MOZ_LOG(sLog, LogLevel::Error, ("Overflow in source stream offset"));
return false;
}
@ -638,7 +637,6 @@ read_source(uint8_t* buffer, uintptr_t size, void* userdata)
size_t bytes_read = 0;
bool rv = source->Read(buffer, size, &bytes_read);
if (!rv) {
static LazyLogModule sLog("MP4Metadata");
MOZ_LOG(sLog, LogLevel::Warning, ("Error reading source data"));
return -1;
}
@ -653,7 +651,10 @@ MP4MetadataRust::MP4MetadataRust(Stream* aSource)
mRustParser.reset(mp4parse_new(&io));
MOZ_ASSERT(mRustParser);
static LazyLogModule sLog("MP4Metadata");
if (MOZ_LOG_TEST(sLog, LogLevel::Debug)) {
mp4parse_log(true);
}
mp4parse_error rv = mp4parse_read(mRustParser.get());
MOZ_LOG(sLog, LogLevel::Debug, ("rust parser returned %d\n", rv));
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
@ -701,8 +702,6 @@ TrackTypeEqual(TrackInfo::TrackType aLHS, mp4parse_track_type aRHS)
uint32_t
MP4MetadataRust::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
{
static LazyLogModule sLog("MP4Metadata");
uint32_t tracks;
auto rv = mp4parse_get_track_count(mRustParser.get(), &tracks);
if (rv != MP4PARSE_OK) {
@ -762,8 +761,6 @@ mozilla::UniquePtr<mozilla::TrackInfo>
MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
size_t aTrackNumber) const
{
static LazyLogModule sLog("MP4Metadata");
Maybe<uint32_t> trackIndex = TrackTypeToGlobalTrackIndex(aType, aTrackNumber);
if (trackIndex.isNothing()) {
return nullptr;

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

@ -39,6 +39,12 @@ if CONFIG['MOZ_REPLACE_MALLOC']:
'replace_malloc.c',
]
if CONFIG['OS_TARGET'] == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or
CONFIG['MOZ_MEMORY'] and not CONFIG['MOZ_JEMALLOC4']):
SOURCES += [
'zone.c',
]
Library('memory')
if CONFIG['MOZ_GLUE_IN_PROGRAM']:

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

@ -300,247 +300,3 @@ MOZ_MEMORY_API __realloc_hook_type __realloc_hook = realloc_impl;
MOZ_MEMORY_API __memalign_hook_type __memalign_hook = memalign_impl;
#endif
/*
* The following is a OSX zone allocator implementation.
* /!\ WARNING. It assumes the underlying malloc implementation's
* malloc_usable_size returns 0 when the given pointer is not owned by
* the allocator. Sadly, OSX does call zone_size with pointers not
* owned by the allocator.
*/
#ifdef XP_DARWIN
#include <stdlib.h>
#include <malloc/malloc.h>
#include "mozilla/Assertions.h"
static size_t
zone_size(malloc_zone_t *zone, void *ptr)
{
return malloc_usable_size_impl(ptr);
}
static void *
zone_malloc(malloc_zone_t *zone, size_t size)
{
return malloc_impl(size);
}
static void *
zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
{
return calloc_impl(num, size);
}
static void *
zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
{
if (malloc_usable_size_impl(ptr))
return realloc_impl(ptr, size);
return realloc(ptr, size);
}
static void
zone_free(malloc_zone_t *zone, void *ptr)
{
if (malloc_usable_size_impl(ptr)) {
free_impl(ptr);
return;
}
free(ptr);
}
static void
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
{
size_t current_size = malloc_usable_size_impl(ptr);
if (current_size) {
MOZ_ASSERT(current_size == size);
free_impl(ptr);
return;
}
free(ptr);
}
static void *
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
{
void *ptr;
if (posix_memalign_impl(&ptr, alignment, size) == 0)
return ptr;
return NULL;
}
static void *
zone_valloc(malloc_zone_t *zone, size_t size)
{
return valloc_impl(size);
}
static void *
zone_destroy(malloc_zone_t *zone)
{
/* This function should never be called. */
MOZ_CRASH();
}
static size_t
zone_good_size(malloc_zone_t *zone, size_t size)
{
return malloc_good_size_impl(size);
}
#ifdef MOZ_JEMALLOC
#include "jemalloc/internal/jemalloc_internal.h"
static void
zone_force_lock(malloc_zone_t *zone)
{
/* /!\ This calls into jemalloc. It works because we're linked in the
* same library. Stolen from jemalloc's zone.c. */
if (isthreaded)
jemalloc_prefork();
}
static void
zone_force_unlock(malloc_zone_t *zone)
{
/* /!\ This calls into jemalloc. It works because we're linked in the
* same library. Stolen from jemalloc's zone.c. */
if (isthreaded)
jemalloc_postfork_parent();
}
#else
#define JEMALLOC_ZONE_VERSION 6
/* Empty implementations are needed, because fork() calls zone->force_(un)lock
* unconditionally. */
static void
zone_force_lock(malloc_zone_t *zone)
{
}
static void
zone_force_unlock(malloc_zone_t *zone)
{
}
#endif
static malloc_zone_t zone;
static struct malloc_introspection_t zone_introspect;
static malloc_zone_t *get_default_zone()
{
malloc_zone_t **zones = NULL;
unsigned int num_zones = 0;
/*
* On OSX 10.12, malloc_default_zone returns a special zone that is not
* present in the list of registered zones. That zone uses a "lite zone"
* if one is present (apparently enabled when malloc stack logging is
* enabled), or the first registered zone otherwise. In practice this
* means unless malloc stack logging is enabled, the first registered
* zone is the default.
* So get the list of zones to get the first one, instead of relying on
* malloc_default_zone.
*/
if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones,
&num_zones)) {
/* Reset the value in case the failure happened after it was set. */
num_zones = 0;
}
if (num_zones) {
return zones[0];
}
return malloc_default_zone();
}
__attribute__((constructor)) void
register_zone(void)
{
malloc_zone_t *default_zone = get_default_zone();
zone.size = (void *)zone_size;
zone.malloc = (void *)zone_malloc;
zone.calloc = (void *)zone_calloc;
zone.valloc = (void *)zone_valloc;
zone.free = (void *)zone_free;
zone.realloc = (void *)zone_realloc;
zone.destroy = (void *)zone_destroy;
zone.zone_name = "replace_malloc_zone";
zone.batch_malloc = NULL;
zone.batch_free = NULL;
zone.introspect = &zone_introspect;
zone.version = JEMALLOC_ZONE_VERSION;
zone.memalign = zone_memalign;
zone.free_definite_size = zone_free_definite_size;
#if (JEMALLOC_ZONE_VERSION >= 8)
zone.pressure_relief = NULL;
#endif
zone_introspect.enumerator = NULL;
zone_introspect.good_size = (void *)zone_good_size;
zone_introspect.check = NULL;
zone_introspect.print = NULL;
zone_introspect.log = NULL;
zone_introspect.force_lock = (void *)zone_force_lock;
zone_introspect.force_unlock = (void *)zone_force_unlock;
zone_introspect.statistics = NULL;
zone_introspect.zone_locked = NULL;
#if (JEMALLOC_ZONE_VERSION >= 7)
zone_introspect.enable_discharge_checking = NULL;
zone_introspect.disable_discharge_checking = NULL;
zone_introspect.discharge = NULL;
#ifdef __BLOCKS__
zone_introspect.enumerate_discharged_pointers = NULL;
#else
zone_introspect.enumerate_unavailable_without_blocks = NULL;
#endif
#endif
/*
* The default purgeable zone is created lazily by OSX's libc. It uses
* the default zone when it is created for "small" allocations
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
* obviously fails when the default zone is the jemalloc zone, so
* malloc_default_purgeable_zone is called beforehand so that the
* default purgeable zone is created when the default zone is still
* a scalable_zone.
*/
malloc_zone_t *purgeable_zone = malloc_default_purgeable_zone();
/* Register the custom zone. At this point it won't be the default. */
malloc_zone_register(&zone);
do {
/*
* Unregister and reregister the default zone. On OSX >= 10.6,
* unregistering takes the last registered zone and places it at the
* location of the specified zone. Unregistering the default zone thus
* makes the last registered one the default. On OSX < 10.6,
* unregistering shifts all registered zones. The first registered zone
* then becomes the default.
*/
malloc_zone_unregister(default_zone);
malloc_zone_register(default_zone);
/*
* On OSX 10.6, having the default purgeable zone appear before the default
* zone makes some things crash because it thinks it owns the default
* zone allocated pointers. We thus unregister/re-register it in order to
* ensure it's always after the default zone. On OSX < 10.6, as
* unregistering shifts registered zones, this simply removes the purgeable
* zone from the list and adds it back at the end, after the default zone.
* On OSX >= 10.6, unregistering replaces the purgeable zone with the last
* registered zone above, i.e the default zone. Registering it again then
* puts it at the end, obviously after the default zone.
*/
malloc_zone_unregister(purgeable_zone);
malloc_zone_register(purgeable_zone);
default_zone = get_default_zone();
} while (default_zone != &zone);
}
#endif

425
memory/build/zone.c Normal file
Просмотреть файл

@ -0,0 +1,425 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozmemory_wrap.h"
#include <stdlib.h>
#include <mach/mach_types.h>
#include "mozilla/Assertions.h"
/*
* Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
* specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
*/
#define MALLOC_DECL(name, return_type, ...) \
MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
#include "malloc_decls.h"
#define MALLOC_DECL(name, return_type, ...) \
MOZ_JEMALLOC_API return_type name ## _impl(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
#include "malloc_decls.h"
/*
* Definitions of the following structs in malloc/malloc.h might be too old
* for the built binary to run on newer versions of OSX. So use the newest
* possible version of those structs.
*/
typedef struct _malloc_zone_t {
void *reserved1;
void *reserved2;
size_t (*size)(struct _malloc_zone_t *, const void *);
void *(*malloc)(struct _malloc_zone_t *, size_t);
void *(*calloc)(struct _malloc_zone_t *, size_t, size_t);
void *(*valloc)(struct _malloc_zone_t *, size_t);
void (*free)(struct _malloc_zone_t *, void *);
void *(*realloc)(struct _malloc_zone_t *, void *, size_t);
void (*destroy)(struct _malloc_zone_t *);
const char *zone_name;
unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned);
void (*batch_free)(struct _malloc_zone_t *, void **, unsigned);
struct malloc_introspection_t *introspect;
unsigned version;
void *(*memalign)(struct _malloc_zone_t *, size_t, size_t);
void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t);
size_t (*pressure_relief)(struct _malloc_zone_t *, size_t);
} malloc_zone_t;
typedef struct {
vm_address_t address;
vm_size_t size;
} vm_range_t;
typedef struct malloc_statistics_t {
unsigned blocks_in_use;
size_t size_in_use;
size_t max_size_in_use;
size_t size_allocated;
} malloc_statistics_t;
typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **);
typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned);
typedef struct malloc_introspection_t {
kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t);
size_t (*good_size)(malloc_zone_t *, size_t);
boolean_t (*check)(malloc_zone_t *);
void (*print)(malloc_zone_t *, boolean_t);
void (*log)(malloc_zone_t *, void *);
void (*force_lock)(malloc_zone_t *);
void (*force_unlock)(malloc_zone_t *);
void (*statistics)(malloc_zone_t *, malloc_statistics_t *);
boolean_t (*zone_locked)(malloc_zone_t *);
boolean_t (*enable_discharge_checking)(malloc_zone_t *);
boolean_t (*disable_discharge_checking)(malloc_zone_t *);
void (*discharge)(malloc_zone_t *, void *);
#ifdef __BLOCKS__
void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *));
#else
void *enumerate_unavailable_without_blocks;
#endif
void (*reinit_lock)(malloc_zone_t *);
} malloc_introspection_t;
extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *);
extern malloc_zone_t *malloc_default_zone(void);
extern void malloc_zone_register(malloc_zone_t *zone);
extern void malloc_zone_unregister(malloc_zone_t *zone);
extern malloc_zone_t *malloc_default_purgeable_zone(void);
/*
* The following is a OSX zone allocator implementation.
* /!\ WARNING. It assumes the underlying malloc implementation's
* malloc_usable_size returns 0 when the given pointer is not owned by
* the allocator. Sadly, OSX does call zone_size with pointers not
* owned by the allocator.
*/
static size_t
zone_size(malloc_zone_t *zone, const void *ptr)
{
return malloc_usable_size_impl(ptr);
}
static void *
zone_malloc(malloc_zone_t *zone, size_t size)
{
return malloc_impl(size);
}
static void *
zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
{
return calloc_impl(num, size);
}
static void *
zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
{
if (malloc_usable_size_impl(ptr))
return realloc_impl(ptr, size);
return realloc(ptr, size);
}
static void
zone_free(malloc_zone_t *zone, void *ptr)
{
if (malloc_usable_size_impl(ptr)) {
free_impl(ptr);
return;
}
free(ptr);
}
static void
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
{
size_t current_size = malloc_usable_size_impl(ptr);
if (current_size) {
MOZ_ASSERT(current_size == size);
free_impl(ptr);
return;
}
free(ptr);
}
static void *
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
{
void *ptr;
if (posix_memalign_impl(&ptr, alignment, size) == 0)
return ptr;
return NULL;
}
static void *
zone_valloc(malloc_zone_t *zone, size_t size)
{
return valloc_impl(size);
}
static void
zone_destroy(malloc_zone_t *zone)
{
/* This function should never be called. */
MOZ_CRASH();
}
static unsigned
zone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
unsigned num_requested)
{
unsigned i;
for (i = 0; i < num_requested; i++) {
results[i] = malloc_impl(size);
if (!results[i])
break;
}
return i;
}
static void
zone_batch_free(malloc_zone_t *zone, void **to_be_freed,
unsigned num_to_be_freed)
{
unsigned i;
for (i = 0; i < num_to_be_freed; i++) {
zone_free(zone, to_be_freed[i]);
to_be_freed[i] = NULL;
}
}
static size_t
zone_pressure_relief(malloc_zone_t *zone, size_t goal)
{
return 0;
}
static size_t
zone_good_size(malloc_zone_t *zone, size_t size)
{
return malloc_good_size_impl(size);
}
static kern_return_t
zone_enumerator(task_t task, void *data, unsigned type_mask,
vm_address_t zone_address, memory_reader_t reader,
vm_range_recorder_t recorder)
{
return KERN_SUCCESS;
}
static boolean_t
zone_check(malloc_zone_t *zone)
{
return true;
}
static void
zone_print(malloc_zone_t *zone, boolean_t verbose)
{
}
static void
zone_log(malloc_zone_t *zone, void *address)
{
}
#ifdef MOZ_JEMALLOC
#include "jemalloc/internal/jemalloc_internal.h"
static void
zone_force_lock(malloc_zone_t *zone)
{
/* /!\ This calls into jemalloc. It works because we're linked in the
* same library. Stolen from jemalloc's zone.c. */
if (isthreaded)
jemalloc_prefork();
}
static void
zone_force_unlock(malloc_zone_t *zone)
{
/* /!\ This calls into jemalloc. It works because we're linked in the
* same library. Stolen from jemalloc's zone.c. See the comment there. */
if (isthreaded)
jemalloc_postfork_child();
}
#else
extern void _malloc_prefork(void);
extern void _malloc_postfork_child(void);
static void
zone_force_lock(malloc_zone_t *zone)
{
/* /!\ This calls into mozjemalloc. It works because we're linked in the
* same library. */
_malloc_prefork();
}
static void
zone_force_unlock(malloc_zone_t *zone)
{
/* /!\ This calls into mozjemalloc. It works because we're linked in the
* same library. */
_malloc_postfork_child();
}
#endif
static void
zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
{
/* We make no effort to actually fill the values */
stats->blocks_in_use = 0;
stats->size_in_use = 0;
stats->max_size_in_use = 0;
stats->size_allocated = 0;
}
static boolean_t
zone_locked(malloc_zone_t *zone)
{
/* Pretend no lock is being held */
return false;
}
static void
zone_reinit_lock(malloc_zone_t *zone)
{
/* As of OSX 10.12, this function is only used when force_unlock would
* be used if the zone version were < 9. So just use force_unlock. */
zone_force_unlock(zone);
}
static malloc_zone_t zone;
static struct malloc_introspection_t zone_introspect;
static malloc_zone_t *get_default_zone()
{
malloc_zone_t **zones = NULL;
unsigned int num_zones = 0;
/*
* On OSX 10.12, malloc_default_zone returns a special zone that is not
* present in the list of registered zones. That zone uses a "lite zone"
* if one is present (apparently enabled when malloc stack logging is
* enabled), or the first registered zone otherwise. In practice this
* means unless malloc stack logging is enabled, the first registered
* zone is the default.
* So get the list of zones to get the first one, instead of relying on
* malloc_default_zone.
*/
if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones,
&num_zones)) {
/* Reset the value in case the failure happened after it was set. */
num_zones = 0;
}
if (num_zones) {
return zones[0];
}
return malloc_default_zone();
}
#ifdef MOZ_REPLACE_MALLOC
__attribute__((constructor))
#endif
void
register_zone(void)
{
malloc_zone_t *default_zone = get_default_zone();
zone.size = zone_size;
zone.malloc = zone_malloc;
zone.calloc = zone_calloc;
zone.valloc = zone_valloc;
zone.free = zone_free;
zone.realloc = zone_realloc;
zone.destroy = zone_destroy;
#ifdef MOZ_REPLACE_MALLOC
zone.zone_name = "replace_malloc_zone";
#else
zone.zone_name = "jemalloc_zone";
#endif
zone.batch_malloc = zone_batch_malloc;
zone.batch_free = zone_batch_free;
zone.introspect = &zone_introspect;
zone.version = 9;
zone.memalign = zone_memalign;
zone.free_definite_size = zone_free_definite_size;
zone.pressure_relief = zone_pressure_relief;
zone_introspect.enumerator = zone_enumerator;
zone_introspect.good_size = zone_good_size;
zone_introspect.check = zone_check;
zone_introspect.print = zone_print;
zone_introspect.log = zone_log;
zone_introspect.force_lock = zone_force_lock;
zone_introspect.force_unlock = zone_force_unlock;
zone_introspect.statistics = zone_statistics;
zone_introspect.zone_locked = zone_locked;
zone_introspect.enable_discharge_checking = NULL;
zone_introspect.disable_discharge_checking = NULL;
zone_introspect.discharge = NULL;
#ifdef __BLOCKS__
zone_introspect.enumerate_discharged_pointers = NULL;
#else
zone_introspect.enumerate_unavailable_without_blocks = NULL;
#endif
zone_introspect.reinit_lock = zone_reinit_lock;
/*
* The default purgeable zone is created lazily by OSX's libc. It uses
* the default zone when it is created for "small" allocations
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
* obviously fails when the default zone is the jemalloc zone, so
* malloc_default_purgeable_zone is called beforehand so that the
* default purgeable zone is created when the default zone is still
* a scalable_zone.
*/
malloc_zone_t *purgeable_zone = malloc_default_purgeable_zone();
/* Register the custom zone. At this point it won't be the default. */
malloc_zone_register(&zone);
do {
/*
* Unregister and reregister the default zone. On OSX >= 10.6,
* unregistering takes the last registered zone and places it at the
* location of the specified zone. Unregistering the default zone thus
* makes the last registered one the default. On OSX < 10.6,
* unregistering shifts all registered zones. The first registered zone
* then becomes the default.
*/
malloc_zone_unregister(default_zone);
malloc_zone_register(default_zone);
/*
* On OSX 10.6, having the default purgeable zone appear before the default
* zone makes some things crash because it thinks it owns the default
* zone allocated pointers. We thus unregister/re-register it in order to
* ensure it's always after the default zone. On OSX < 10.6, as
* unregistering shifts registered zones, this simply removes the purgeable
* zone from the list and adds it back at the end, after the default zone.
* On OSX >= 10.6, unregistering replaces the purgeable zone with the last
* registered zone above, i.e the default zone. Registering it again then
* puts it at the end, obviously after the default zone.
*/
malloc_zone_unregister(purgeable_zone);
malloc_zone_register(purgeable_zone);
default_zone = get_default_zone();
} while (default_zone != &zone);
}

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

@ -1 +1 @@
4.4.0-0-gf1f76357313e7dcad7262f17a48ff0a2e005fcdc
4.4.0-3-gc6943acb3c56d1b3d1e82dd43b3fcfeae7771990

150
memory/jemalloc/src/configure поставляемый
Просмотреть файл

@ -9007,156 +9007,6 @@ if test "x${enable_zone_allocator}" = "x1" ; then
fi
$as_echo "#define JEMALLOC_ZONE " >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking malloc zone version" >&5
$as_echo_n "checking malloc zone version... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_zone_t) == sizeof(void *) * 14 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=3
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_zone_t) == sizeof(void *) * 15 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=5
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_zone_t) == sizeof(void *) * 16 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_introspection_t) == sizeof(void *) * 9 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_introspection_t) == sizeof(void *) * 13 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=7
else
JEMALLOC_ZONE_VERSION=
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_zone_t) == sizeof(void *) * 17 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=8
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <malloc/malloc.h>
int
main ()
{
static int foo[sizeof(malloc_zone_t) > sizeof(void *) * 17 ? 1 : -1]
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
JEMALLOC_ZONE_VERSION=9
else
JEMALLOC_ZONE_VERSION=
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; }
as_fn_error $? "Unsupported malloc zone version" "$LINENO" 5
fi
if test "${JEMALLOC_ZONE_VERSION}" = 9; then
JEMALLOC_ZONE_VERSION=8
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: > 8" >&5
$as_echo "> 8" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $JEMALLOC_ZONE_VERSION" >&5
$as_echo "$JEMALLOC_ZONE_VERSION" >&6; }
fi
cat >>confdefs.h <<_ACEOF
#define JEMALLOC_ZONE_VERSION $JEMALLOC_ZONE_VERSION
_ACEOF
fi

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

@ -1774,37 +1774,6 @@ if test "x${enable_zone_allocator}" = "x1" ; then
AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])
fi
AC_DEFINE([JEMALLOC_ZONE], [ ])
dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6
dnl releases. malloc_zone_t and malloc_introspection_t have new fields in
dnl 10.6, which is the only source-level indication of the change.
AC_MSG_CHECKING([malloc zone version])
AC_DEFUN([JE_ZONE_PROGRAM],
[AC_LANG_PROGRAM(
[#include <malloc/malloc.h>],
[static int foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]
)])
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]
)])],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]
)])])])])
if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
AC_MSG_RESULT([unsupported])
AC_MSG_ERROR([Unsupported malloc zone version])
fi
if test "${JEMALLOC_ZONE_VERSION}" = 9; then
JEMALLOC_ZONE_VERSION=8
AC_MSG_RESULT([> 8])
else
AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])
fi
AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])
fi
dnl ============================================================================

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

@ -158,7 +158,6 @@ static const bool config_cache_oblivious =
#include <mach/mach_error.h>
#include <mach/mach_init.h>
#include <mach/vm_map.h>
#include <malloc/malloc.h>
#endif
#include "jemalloc/internal/ph.h"

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

@ -239,7 +239,6 @@
* Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.
*/
#undef JEMALLOC_ZONE
#undef JEMALLOC_ZONE_VERSION
/*
* Methods for determining whether the OS overcommits.

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

@ -76,7 +76,7 @@ mb_write(void)
: "memory" /* Clobbers. */
);
}
#elif defined(__sparc64__)
#elif defined(__sparc__) && defined(__arch64__)
JEMALLOC_INLINE void
mb_write(void)
{

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

@ -3,6 +3,75 @@
# error "This source file is for zones on Darwin (OS X)."
#endif
/* Definitions of the following structs in malloc/malloc.h might be too old
* for the built binary to run on newer versions of OSX. So use the newest
* possible version of those structs.
*/
typedef struct _malloc_zone_t {
void *reserved1;
void *reserved2;
size_t (*size)(struct _malloc_zone_t *, const void *);
void *(*malloc)(struct _malloc_zone_t *, size_t);
void *(*calloc)(struct _malloc_zone_t *, size_t, size_t);
void *(*valloc)(struct _malloc_zone_t *, size_t);
void (*free)(struct _malloc_zone_t *, void *);
void *(*realloc)(struct _malloc_zone_t *, void *, size_t);
void (*destroy)(struct _malloc_zone_t *);
const char *zone_name;
unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned);
void (*batch_free)(struct _malloc_zone_t *, void **, unsigned);
struct malloc_introspection_t *introspect;
unsigned version;
void *(*memalign)(struct _malloc_zone_t *, size_t, size_t);
void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t);
size_t (*pressure_relief)(struct _malloc_zone_t *, size_t);
} malloc_zone_t;
typedef struct {
vm_address_t address;
vm_size_t size;
} vm_range_t;
typedef struct malloc_statistics_t {
unsigned blocks_in_use;
size_t size_in_use;
size_t max_size_in_use;
size_t size_allocated;
} malloc_statistics_t;
typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **);
typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned);
typedef struct malloc_introspection_t {
kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t);
size_t (*good_size)(malloc_zone_t *, size_t);
boolean_t (*check)(malloc_zone_t *);
void (*print)(malloc_zone_t *, boolean_t);
void (*log)(malloc_zone_t *, void *);
void (*force_lock)(malloc_zone_t *);
void (*force_unlock)(malloc_zone_t *);
void (*statistics)(malloc_zone_t *, malloc_statistics_t *);
boolean_t (*zone_locked)(malloc_zone_t *);
boolean_t (*enable_discharge_checking)(malloc_zone_t *);
boolean_t (*disable_discharge_checking)(malloc_zone_t *);
void (*discharge)(malloc_zone_t *, void *);
#ifdef __BLOCKS__
void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *));
#else
void *enumerate_unavailable_without_blocks;
#endif
void (*reinit_lock)(malloc_zone_t *);
} malloc_introspection_t;
extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *);
extern malloc_zone_t *malloc_default_zone(void);
extern void malloc_zone_register(malloc_zone_t *zone);
extern void malloc_zone_unregister(malloc_zone_t *zone);
/*
* The malloc_default_purgeable_zone() function is only available on >= 10.6.
* We need to check whether it is present at runtime, thus the weak_import.
@ -20,24 +89,35 @@ static struct malloc_introspection_t jemalloc_zone_introspect;
/******************************************************************************/
/* Function prototypes for non-inline static functions. */
static size_t zone_size(malloc_zone_t *zone, void *ptr);
static size_t zone_size(malloc_zone_t *zone, const void *ptr);
static void *zone_malloc(malloc_zone_t *zone, size_t size);
static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size);
static void *zone_valloc(malloc_zone_t *zone, size_t size);
static void zone_free(malloc_zone_t *zone, void *ptr);
static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
#if (JEMALLOC_ZONE_VERSION >= 5)
static void *zone_memalign(malloc_zone_t *zone, size_t alignment,
#endif
#if (JEMALLOC_ZONE_VERSION >= 6)
size_t size);
static void zone_free_definite_size(malloc_zone_t *zone, void *ptr,
size_t size);
#endif
static void *zone_destroy(malloc_zone_t *zone);
static void zone_destroy(malloc_zone_t *zone);
static unsigned zone_batch_malloc(struct _malloc_zone_t *zone, size_t size,
void **results, unsigned num_requested);
static void zone_batch_free(struct _malloc_zone_t *zone,
void **to_be_freed, unsigned num_to_be_freed);
static size_t zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal);
static size_t zone_good_size(malloc_zone_t *zone, size_t size);
static kern_return_t zone_enumerator(task_t task, void *data, unsigned type_mask,
vm_address_t zone_address, memory_reader_t reader,
vm_range_recorder_t recorder);
static boolean_t zone_check(malloc_zone_t *zone);
static void zone_print(malloc_zone_t *zone, boolean_t verbose);
static void zone_log(malloc_zone_t *zone, void *address);
static void zone_force_lock(malloc_zone_t *zone);
static void zone_force_unlock(malloc_zone_t *zone);
static void zone_statistics(malloc_zone_t *zone,
malloc_statistics_t *stats);
static boolean_t zone_locked(malloc_zone_t *zone);
static void zone_reinit_lock(malloc_zone_t *zone);
/******************************************************************************/
/*
@ -45,7 +125,7 @@ static void zone_force_unlock(malloc_zone_t *zone);
*/
static size_t
zone_size(malloc_zone_t *zone, void *ptr)
zone_size(malloc_zone_t *zone, const void *ptr)
{
/*
@ -106,7 +186,6 @@ zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
return (realloc(ptr, size));
}
#if (JEMALLOC_ZONE_VERSION >= 5)
static void *
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
{
@ -116,9 +195,7 @@ zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
return (ret);
}
#endif
#if (JEMALLOC_ZONE_VERSION >= 6)
static void
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
{
@ -133,15 +210,46 @@ zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
free(ptr);
}
#endif
static void *
static void
zone_destroy(malloc_zone_t *zone)
{
/* This function should never be called. */
not_reached();
return (NULL);
}
static unsigned
zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, void **results,
unsigned num_requested)
{
unsigned i;
for (i = 0; i < num_requested; i++) {
results[i] = je_malloc(size);
if (!results[i])
break;
}
return i;
}
static void
zone_batch_free(struct _malloc_zone_t *zone, void **to_be_freed,
unsigned num_to_be_freed)
{
unsigned i;
for (i = 0; i < num_to_be_freed; i++) {
zone_free(zone, to_be_freed[i]);
to_be_freed[i] = NULL;
}
}
static size_t
zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal)
{
return 0;
}
static size_t
@ -153,6 +261,30 @@ zone_good_size(malloc_zone_t *zone, size_t size)
return (s2u(size));
}
static kern_return_t
zone_enumerator(task_t task, void *data, unsigned type_mask,
vm_address_t zone_address, memory_reader_t reader,
vm_range_recorder_t recorder)
{
return KERN_SUCCESS;
}
static boolean_t
zone_check(malloc_zone_t *zone)
{
return true;
}
static void
zone_print(malloc_zone_t *zone, boolean_t verbose)
{
}
static void
zone_log(malloc_zone_t *zone, void *address)
{
}
static void
zone_force_lock(malloc_zone_t *zone)
{
@ -176,53 +308,69 @@ zone_force_unlock(malloc_zone_t *zone)
jemalloc_postfork_child();
}
static void
zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
{
/* We make no effort to actually fill the values */
stats->blocks_in_use = 0;
stats->size_in_use = 0;
stats->max_size_in_use = 0;
stats->size_allocated = 0;
}
static boolean_t
zone_locked(malloc_zone_t *zone)
{
/* Pretend no lock is being held */
return false;
}
static void
zone_reinit_lock(malloc_zone_t *zone)
{
/* As of OSX 10.12, this function is only used when force_unlock would
* be used if the zone version were < 9. So just use force_unlock. */
zone_force_unlock(zone);
}
static void
zone_init(void)
{
jemalloc_zone.size = (void *)zone_size;
jemalloc_zone.malloc = (void *)zone_malloc;
jemalloc_zone.calloc = (void *)zone_calloc;
jemalloc_zone.valloc = (void *)zone_valloc;
jemalloc_zone.free = (void *)zone_free;
jemalloc_zone.realloc = (void *)zone_realloc;
jemalloc_zone.destroy = (void *)zone_destroy;
jemalloc_zone.size = zone_size;
jemalloc_zone.malloc = zone_malloc;
jemalloc_zone.calloc = zone_calloc;
jemalloc_zone.valloc = zone_valloc;
jemalloc_zone.free = zone_free;
jemalloc_zone.realloc = zone_realloc;
jemalloc_zone.destroy = zone_destroy;
jemalloc_zone.zone_name = "jemalloc_zone";
jemalloc_zone.batch_malloc = NULL;
jemalloc_zone.batch_free = NULL;
jemalloc_zone.batch_malloc = zone_batch_malloc;
jemalloc_zone.batch_free = zone_batch_free;
jemalloc_zone.introspect = &jemalloc_zone_introspect;
jemalloc_zone.version = JEMALLOC_ZONE_VERSION;
#if (JEMALLOC_ZONE_VERSION >= 5)
jemalloc_zone.version = 9;
jemalloc_zone.memalign = zone_memalign;
#endif
#if (JEMALLOC_ZONE_VERSION >= 6)
jemalloc_zone.free_definite_size = zone_free_definite_size;
#endif
#if (JEMALLOC_ZONE_VERSION >= 8)
jemalloc_zone.pressure_relief = NULL;
#endif
jemalloc_zone.pressure_relief = zone_pressure_relief;
jemalloc_zone_introspect.enumerator = NULL;
jemalloc_zone_introspect.good_size = (void *)zone_good_size;
jemalloc_zone_introspect.check = NULL;
jemalloc_zone_introspect.print = NULL;
jemalloc_zone_introspect.log = NULL;
jemalloc_zone_introspect.force_lock = (void *)zone_force_lock;
jemalloc_zone_introspect.force_unlock = (void *)zone_force_unlock;
jemalloc_zone_introspect.statistics = NULL;
#if (JEMALLOC_ZONE_VERSION >= 6)
jemalloc_zone_introspect.zone_locked = NULL;
#endif
#if (JEMALLOC_ZONE_VERSION >= 7)
jemalloc_zone_introspect.enumerator = zone_enumerator;
jemalloc_zone_introspect.good_size = zone_good_size;
jemalloc_zone_introspect.check = zone_check;
jemalloc_zone_introspect.print = zone_print;
jemalloc_zone_introspect.log = zone_log;
jemalloc_zone_introspect.force_lock = zone_force_lock;
jemalloc_zone_introspect.force_unlock = zone_force_unlock;
jemalloc_zone_introspect.statistics = zone_statistics;
jemalloc_zone_introspect.zone_locked = zone_locked;
jemalloc_zone_introspect.enable_discharge_checking = NULL;
jemalloc_zone_introspect.disable_discharge_checking = NULL;
jemalloc_zone_introspect.discharge = NULL;
# ifdef __BLOCKS__
#ifdef __BLOCKS__
jemalloc_zone_introspect.enumerate_discharged_pointers = NULL;
# else
#else
jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL;
# endif
#endif
jemalloc_zone_introspect.reinit_lock = zone_reinit_lock;
}
static malloc_zone_t *

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

@ -1,2 +1,2 @@
UPSTREAM_REPO=https://github.com/jemalloc/jemalloc
UPSTREAM_COMMIT=4.4.0
UPSTREAM_COMMIT=c6943acb3c56d1b3d1e82dd43b3fcfeae7771990

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

@ -1451,67 +1451,18 @@ static
#endif
bool malloc_init_hard(void);
static void _malloc_prefork(void);
static void _malloc_postfork(void);
#ifdef MOZ_MEMORY_DARWIN
/*
* MALLOC_ZONE_T_NOTE
*
* On Darwin, we hook into the memory allocator using a malloc_zone_t struct.
* We must be very careful around this struct because of different behaviour on
* different versions of OSX.
*
* Each of OSX 10.5, 10.6 and 10.7 use different versions of the struct
* (with version numbers 3, 6 and 8 respectively). The binary we use on each of
* these platforms will not necessarily be built using the correct SDK [1].
* This means we need to statically know the correct struct size to use on all
* OSX releases, and have a fallback for unknown future versions. The struct
* sizes defined in osx_zone_types.h.
*
* For OSX 10.8 and later, we may expect the malloc_zone_t struct to change
* again, and need to dynamically account for this. By simply leaving
* malloc_zone_t alone, we don't quite deal with the problem, because there
* remain calls to jemalloc through the mozalloc interface. We check this
* dynamically on each allocation, using the CHECK_DARWIN macro and
* osx_use_jemalloc.
*
*
* [1] Mozilla is built as a universal binary on Mac, supporting i386 and
* x86_64. The i386 target is built using the 10.5 SDK, even if it runs on
* 10.6. The x86_64 target is built using the 10.6 SDK, even if it runs on
* 10.7 or later, or 10.5.
*
* FIXME:
* When later versions of OSX come out (10.8 and up), we need to check their
* malloc_zone_t versions. If they're greater than 8, we need a new version
* of malloc_zone_t adapted into osx_zone_types.h.
*/
#ifndef MOZ_REPLACE_MALLOC
#include "osx_zone_types.h"
#define LEOPARD_MALLOC_ZONE_T_VERSION 3
#define SNOW_LEOPARD_MALLOC_ZONE_T_VERSION 6
#define LION_MALLOC_ZONE_T_VERSION 8
static bool osx_use_jemalloc = false;
static lion_malloc_zone l_szone;
static malloc_zone_t * szone = (malloc_zone_t*)(&l_szone);
static lion_malloc_introspection l_ozone_introspect;
static malloc_introspection_t * const ozone_introspect =
(malloc_introspection_t*)(&l_ozone_introspect);
static malloc_zone_t *get_default_zone();
static void szone2ozone(malloc_zone_t *zone, size_t size);
static size_t zone_version_size(int version);
#else
static const bool osx_use_jemalloc = true;
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void _malloc_prefork(void);
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void _malloc_postfork_parent(void);
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void _malloc_postfork_child(void);
/*
* End function prototypes.
@ -5580,6 +5531,10 @@ malloc_init(void)
}
#endif
#if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
extern void register_zone(void);
#endif
#if !defined(MOZ_MEMORY_WINDOWS)
static
#endif
@ -5593,9 +5548,6 @@ malloc_init_hard(void)
#ifndef MOZ_MEMORY_WINDOWS
int linklen;
#endif
#ifdef MOZ_MEMORY_DARWIN
malloc_zone_t* default_zone;
#endif
#ifndef MOZ_MEMORY_WINDOWS
malloc_mutex_lock(&init_lock);
@ -6091,7 +6043,7 @@ MALLOC_OUT:
#if !defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)
/* Prevent potential deadlock on malloc locks after fork. */
pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
pthread_atfork(_malloc_prefork, _malloc_postfork_parent, _malloc_postfork_child);
#endif
#if defined(NEEDS_PTHREAD_MMAP_UNALIGNED_TSD)
@ -6101,45 +6053,7 @@ MALLOC_OUT:
#endif
#if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
/*
* Overwrite the default memory allocator to use jemalloc everywhere.
*/
default_zone = get_default_zone();
/*
* We only use jemalloc with MacOS 10.6 and 10.7. jemalloc is disabled
* on 32-bit builds (10.5 and 32-bit 10.6) due to bug 702250, an
* apparent MacOS bug. In fact, this code isn't even compiled on
* 32-bit builds.
*
* We'll have to update our code to work with newer versions, because
* the malloc zone layout is likely to change.
*/
osx_use_jemalloc = (default_zone->version == SNOW_LEOPARD_MALLOC_ZONE_T_VERSION ||
default_zone->version == LION_MALLOC_ZONE_T_VERSION);
/* Allow us dynamically turn off jemalloc for testing. */
if (getenv("NO_MAC_JEMALLOC")) {
osx_use_jemalloc = false;
#ifdef __i386__
malloc_printf("Warning: NO_MAC_JEMALLOC has no effect on "
"i386 machines (such as this one).\n");
#endif
}
if (osx_use_jemalloc) {
/*
* Convert the default szone to an "overlay zone" that is capable
* of deallocating szone-allocated objects, but allocating new
* objects from jemalloc.
*/
size_t size = zone_version_size(default_zone->version);
szone2ozone(default_zone, size);
}
else {
szone = default_zone;
}
register_zone();
#endif
#ifndef MOZ_MEMORY_WINDOWS
@ -6166,32 +6080,11 @@ malloc_shutdown()
* Begin malloc(3)-compatible functions.
*/
/*
* Even though we compile with MOZ_MEMORY, we may have to dynamically decide
* not to use jemalloc, as discussed above. However, we call jemalloc
* functions directly from mozalloc. Since it's pretty dangerous to mix the
* allocators, we need to call the OSX allocators from the functions below,
* when osx_use_jemalloc is not (dynamically) set.
*
* Note that we assume jemalloc is enabled on i386. This is safe because the
* only i386 versions of MacOS are 10.5 and 10.6, which we support. We have to
* do this because madvise isn't in the malloc zone struct for 10.5.
*
* This means that NO_MAC_JEMALLOC doesn't work on i386.
*/
#if defined(MOZ_MEMORY_DARWIN) && !defined(__i386__) && !defined(MOZ_REPLACE_MALLOC)
#define DARWIN_ONLY(A) if (!osx_use_jemalloc) { A; }
#else
#define DARWIN_ONLY(A)
#endif
MOZ_MEMORY_API void *
malloc_impl(size_t size)
{
void *ret;
DARWIN_ONLY(return (szone->malloc)(szone, size));
if (malloc_init()) {
ret = NULL;
goto RETURN;
@ -6274,8 +6167,6 @@ MEMALIGN(size_t alignment, size_t size)
{
void *ret;
DARWIN_ONLY(return (szone->memalign)(szone, alignment, size));
assert(((alignment - 1) & alignment) == 0);
if (malloc_init()) {
@ -6374,8 +6265,6 @@ calloc_impl(size_t num, size_t size)
void *ret;
size_t num_size;
DARWIN_ONLY(return (szone->calloc)(szone, num, size));
if (malloc_init()) {
num_size = 0;
ret = NULL;
@ -6430,8 +6319,6 @@ realloc_impl(void *ptr, size_t size)
{
void *ret;
DARWIN_ONLY(return (szone->realloc)(szone, ptr, size));
if (size == 0) {
#ifdef MALLOC_SYSV
if (opt_sysv == false)
@ -6494,8 +6381,6 @@ free_impl(void *ptr)
{
size_t offset;
DARWIN_ONLY((szone->free)(szone, ptr); return);
UTRACE(ptr, 0, 0);
/*
@ -6519,12 +6404,7 @@ free_impl(void *ptr)
*/
/* This was added by Mozilla for use by SQLite. */
#if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
static
#else
MOZ_MEMORY_API
#endif
size_t
MOZ_MEMORY_API size_t
malloc_good_size_impl(size_t size)
{
/*
@ -6566,8 +6446,6 @@ malloc_good_size_impl(size_t size)
MOZ_MEMORY_API size_t
malloc_usable_size_impl(MALLOC_USABLE_SIZE_CONST_PTR void *ptr)
{
DARWIN_ONLY(return (szone->size)(szone, ptr));
#ifdef MALLOC_VALIDATE
return (isalloc_validate(ptr));
#else
@ -6885,7 +6763,10 @@ jemalloc_free_dirty_pages_impl(void)
* is threaded here.
*/
static void
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void
_malloc_prefork(void)
{
unsigned i;
@ -6903,8 +6784,11 @@ _malloc_prefork(void)
malloc_mutex_lock(&huge_mtx);
}
static void
_malloc_postfork(void)
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void
_malloc_postfork_parent(void)
{
unsigned i;
@ -6921,6 +6805,27 @@ _malloc_postfork(void)
malloc_spin_unlock(&arenas_lock);
}
#ifndef MOZ_MEMORY_DARWIN
static
#endif
void
_malloc_postfork_child(void)
{
unsigned i;
/* Reinitialize all mutexes, now that fork() has completed. */
malloc_mutex_init(&huge_mtx);
malloc_mutex_init(&base_mtx);
for (i = 0; i < narenas; i++) {
if (arenas[i] != NULL)
malloc_spin_init(&arenas[i]->lock);
}
malloc_spin_init(&arenas_lock);
}
/*
* End library-private functions.
*/
@ -6932,254 +6837,6 @@ _malloc_postfork(void)
#if defined(MOZ_MEMORY_DARWIN)
#if !defined(MOZ_REPLACE_MALLOC)
static void *
zone_malloc(malloc_zone_t *zone, size_t size)
{
return (malloc_impl(size));
}
static void *
zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
{
return (calloc_impl(num, size));
}
static void *
zone_valloc(malloc_zone_t *zone, size_t size)
{
void *ret = NULL; /* Assignment avoids useless compiler warning. */
posix_memalign_impl(&ret, pagesize, size);
return (ret);
}
static void *
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
{
return (memalign_impl(alignment, size));
}
static void *
zone_destroy(malloc_zone_t *zone)
{
/* This function should never be called. */
assert(false);
return (NULL);
}
static size_t
zone_good_size(malloc_zone_t *zone, size_t size)
{
return malloc_good_size_impl(size);
}
static size_t
ozone_size(malloc_zone_t *zone, void *ptr)
{
size_t ret = isalloc_validate(ptr);
if (ret == 0)
ret = szone->size(zone, ptr);
return ret;
}
static void
ozone_free(malloc_zone_t *zone, void *ptr)
{
if (isalloc_validate(ptr) != 0)
free_impl(ptr);
else {
size_t size = szone->size(zone, ptr);
if (size != 0)
(szone->free)(zone, ptr);
/* Otherwise we leak. */
}
}
static void *
ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
{
size_t oldsize;
if (ptr == NULL)
return (malloc_impl(size));
oldsize = isalloc_validate(ptr);
if (oldsize != 0)
return (realloc_impl(ptr, size));
else {
oldsize = szone->size(zone, ptr);
if (oldsize == 0)
return (malloc_impl(size));
else {
void *ret = malloc_impl(size);
if (ret != NULL) {
memcpy(ret, ptr, (oldsize < size) ? oldsize :
size);
(szone->free)(zone, ptr);
}
return (ret);
}
}
}
static unsigned
ozone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
unsigned num_requested)
{
/* Don't bother implementing this interface, since it isn't required. */
return 0;
}
static void
ozone_batch_free(malloc_zone_t *zone, void **to_be_freed, unsigned num)
{
unsigned i;
for (i = 0; i < num; i++)
ozone_free(zone, to_be_freed[i]);
}
static void
ozone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
{
if (isalloc_validate(ptr) != 0) {
assert(isalloc_validate(ptr) == size);
free_impl(ptr);
} else {
assert(size == szone->size(zone, ptr));
l_szone.m16(zone, ptr, size);
}
}
static void
ozone_force_lock(malloc_zone_t *zone)
{
_malloc_prefork();
szone->introspect->force_lock(zone);
}
static void
ozone_force_unlock(malloc_zone_t *zone)
{
szone->introspect->force_unlock(zone);
_malloc_postfork();
}
static size_t
zone_version_size(int version)
{
switch (version)
{
case SNOW_LEOPARD_MALLOC_ZONE_T_VERSION:
return sizeof(snow_leopard_malloc_zone);
case LEOPARD_MALLOC_ZONE_T_VERSION:
return sizeof(leopard_malloc_zone);
default:
case LION_MALLOC_ZONE_T_VERSION:
return sizeof(lion_malloc_zone);
}
}
static malloc_zone_t *get_default_zone()
{
malloc_zone_t **zones = NULL;
unsigned int num_zones = 0;
/*
* On OSX 10.12, malloc_default_zone returns a special zone that is not
* present in the list of registered zones. That zone uses a "lite zone"
* if one is present (apparently enabled when malloc stack logging is
* enabled), or the first registered zone otherwise. In practice this
* means unless malloc stack logging is enabled, the first registered
* zone is the default.
* So get the list of zones to get the first one, instead of relying on
* malloc_default_zone.
*/
if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones,
&num_zones)) {
/* Reset the value in case the failure happened after it was set. */
num_zones = 0;
}
if (num_zones) {
return zones[0];
}
return malloc_default_zone();
}
/*
* Overlay the default scalable zone (szone) such that existing allocations are
* drained, and further allocations come from jemalloc. This is necessary
* because Core Foundation directly accesses and uses the szone before the
* jemalloc library is even loaded.
*/
static void
szone2ozone(malloc_zone_t *default_zone, size_t size)
{
lion_malloc_zone *l_zone;
assert(malloc_initialized);
/*
* Stash a copy of the original szone so that we can call its
* functions as needed. Note that internally, the szone stores its
* bookkeeping data structures immediately following the malloc_zone_t
* header, so when calling szone functions, we need to pass a pointer to
* the original zone structure.
*/
memcpy(szone, default_zone, size);
/* OSX 10.7 allocates the default zone in protected memory. */
if (default_zone->version >= LION_MALLOC_ZONE_T_VERSION) {
void* start_of_page = (void*)((size_t)(default_zone) & ~pagesize_mask);
mprotect (start_of_page, size, PROT_READ | PROT_WRITE);
}
default_zone->size = (void *)ozone_size;
default_zone->malloc = (void *)zone_malloc;
default_zone->calloc = (void *)zone_calloc;
default_zone->valloc = (void *)zone_valloc;
default_zone->free = (void *)ozone_free;
default_zone->realloc = (void *)ozone_realloc;
default_zone->destroy = (void *)zone_destroy;
default_zone->batch_malloc = NULL;
default_zone->batch_free = ozone_batch_free;
default_zone->introspect = ozone_introspect;
/* Don't modify default_zone->zone_name; Mac libc may rely on the name
* being unchanged. See Mozilla bug 694896. */
ozone_introspect->enumerator = NULL;
ozone_introspect->good_size = (void *)zone_good_size;
ozone_introspect->check = NULL;
ozone_introspect->print = NULL;
ozone_introspect->log = NULL;
ozone_introspect->force_lock = (void *)ozone_force_lock;
ozone_introspect->force_unlock = (void *)ozone_force_unlock;
ozone_introspect->statistics = NULL;
/* Platform-dependent structs */
l_zone = (lion_malloc_zone*)(default_zone);
if (default_zone->version >= SNOW_LEOPARD_MALLOC_ZONE_T_VERSION) {
l_zone->m15 = (void (*)())zone_memalign;
l_zone->m16 = (void (*)())ozone_free_definite_size;
l_ozone_introspect.m9 = NULL;
}
if (default_zone->version >= LION_MALLOC_ZONE_T_VERSION) {
l_zone->m17 = NULL;
l_ozone_introspect.m10 = NULL;
l_ozone_introspect.m11 = NULL;
l_ozone_introspect.m12 = NULL;
l_ozone_introspect.m13 = NULL;
}
}
#endif
__attribute__((constructor))
void
jemalloc_darwin_init(void)

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

@ -1,147 +0,0 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
/* vim:set softtabstop=8 shiftwidth=8: */
/*-
* Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice(s), this list of conditions and the following disclaimer as
* the first lines of this file unmodified other than the possible
* addition of one or more copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
* notice(s), this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The purpose of these structs is described in jemalloc.c, in the comment
* marked MALLOC_ZONE_T_NOTE.
*
* We need access to some structs that come with a specific version of OSX
* but can't copy them here because of licensing restrictions (see bug
* 603655). The structs below are equivalent in that they'll always be
* compiled to the same representation on all platforms.
*
* `void*` and `void (*)()` may not be the same size on weird platforms, but
* the size of a function pointer shouldn't vary according to its parameters
* or return type.
*
* Apple's version of these structures, complete with member names and
* comments, is available online at
*
* http://www.opensource.apple.com/source/Libc/Libc-763.12/include/malloc/malloc.h
*
*/
/*
* OSX 10.5 - Leopard
*/
typedef struct _leopard_malloc_zone {
void *m1;
void *m2;
void (*m3)();
void (*m4)();
void (*m5)();
void (*m6)();
void (*m7)();
void (*m8)();
void (*m9)();
void *m10;
void (*m11)();
void (*m12)();
void *m13;
unsigned m14;
} leopard_malloc_zone;
/*
* OSX 10.6 - Snow Leopard
*/
typedef struct _snow_leopard_malloc_zone {
void *m1;
void *m2;
void (*m3)();
void (*m4)();
void (*m5)();
void (*m6)();
void (*m7)();
void (*m8)();
void (*m9)();
void *m10;
void (*m11)();
void (*m12)();
void *m13;
unsigned m14;
void (*m15)(); // this member added in 10.6
void (*m16)(); // this member added in 10.6
} snow_leopard_malloc_zone;
typedef struct _snow_leopard_malloc_introspection {
void (*m1)();
void (*m2)();
void (*m3)();
void (*m4)();
void (*m5)();
void (*m6)();
void (*m7)();
void (*m8)();
void (*m9)(); // this member added in 10.6
} snow_leopard_malloc_introspection;
/*
* OSX 10.7 - Lion
*/
typedef struct _lion_malloc_zone {
void *m1;
void *m2;
void (*m3)();
void (*m4)();
void (*m5)();
void (*m6)();
void (*m7)();
void (*m8)();
void (*m9)();
void *m10;
void (*m11)();
void (*m12)();
void *m13;
unsigned m14;
void (*m15)();
void (*m16)();
void (*m17)(); // this member added in 10.7
} lion_malloc_zone;
typedef struct _lion_malloc_introspection {
void (*m1)();
void (*m2)();
void (*m3)();
void (*m4)();
void (*m5)();
void (*m6)();
void (*m7)();
void (*m8)();
void (*m9)();
void (*m10)(); // this member added in 10.7
void (*m11)(); // this member added in 10.7
void (*m12)(); // this member added in 10.7
#ifdef __BLOCKS__
void (*m13)(); // this member added in 10.7
#else
void *m13; // this member added in 10.7
#endif
} lion_malloc_introspection;

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

@ -741,6 +741,7 @@ public class BrowserApp extends GeckoApp
"CharEncoding:State",
"Settings:Show",
"Updater:Launch",
"Sanitize:OpenTabs",
null);
EventDispatcher.getInstance().registerBackgroundThreadListener(this,
@ -1454,6 +1455,7 @@ public class BrowserApp extends GeckoApp
"CharEncoding:State",
"Settings:Show",
"Updater:Launch",
"Sanitize:OpenTabs",
null);
EventDispatcher.getInstance().unregisterBackgroundThreadListener(this,
@ -1914,6 +1916,11 @@ public class BrowserApp extends GeckoApp
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
break;
case "Sanitize:OpenTabs":
Tabs.getInstance().closeAll();
callback.sendSuccess(null);
break;
case "Sanitize:ClearHistory":
BrowserDB.from(getProfile()).clearHistory(
getContentResolver(), message.getBoolean("clearSearchHistory", false));

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

@ -585,17 +585,20 @@ public abstract class GeckoApp
Log.e(LOGTAG, "Error adding sanitize object", ex);
}
// If the user has opted out of session restore, and does want to clear history
// If the user wants to clear open tabs, or else has opted out of session restore and does want to clear history,
// we also want to prevent the current session info from being saved.
if (clearObj.has("private.data.history")) {
final String sessionRestore = getSessionRestorePreference(getSharedPreferences());
try {
res.put("dontSaveSession", "quit".equals(sessionRestore));
} catch (JSONException ex) {
Log.e(LOGTAG, "Error adding session restore data", ex);
}
}
try {
if (clearObj.has("private.data.openTabs")) {
res.put("dontSaveSession", true);
} else if (clearObj.has("private.data.history")) {
final String sessionRestore = getSessionRestorePreference(getSharedPreferences());
res.put("dontSaveSession", "quit".equals(sessionRestore));
}
} catch (JSONException ex) {
Log.e(LOGTAG, "Error adding session restore data", ex);
}
GeckoAppShell.notifyObservers("Browser:Quit", res.toString());
// We don't call doShutdown() here because this creates a race condition which can
// cause the clearing of private data to fail. Instead, we shut down the UI only after

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

@ -85,6 +85,12 @@ public class Tabs implements BundleEventListener {
private PersistTabsRunnable mPersistTabsRunnable;
private int mPrivateClearColor;
public void closeAll() {
for (final Tab tab : mOrder) {
Tabs.getInstance().closeTab(tab, false);
}
}
private static class PersistTabsRunnable implements Runnable {
private final BrowserDB db;
private final Context context;

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

@ -225,8 +225,13 @@ public class HomePager extends ViewPager implements HomeScreen {
// list of panels in place.
mTabStrip.setVisibility(View.INVISIBLE);
// Load list of panels from configuration
lm.initLoader(LOADER_ID_CONFIG, null, mConfigLoaderCallbacks);
// If HomeConfigLoader already exist, force load to select the current item
if (lm.getLoader(LOADER_ID_CONFIG) != null) {
lm.getLoader(LOADER_ID_CONFIG).forceLoad();
} else {
// Load list of panels from configuration
lm.initLoader(LOADER_ID_CONFIG, null, mConfigLoaderCallbacks);
}
if (shouldAnimate) {
animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() {

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

@ -7,8 +7,6 @@ package org.mozilla.gecko.home.activitystream.menu;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.NavigationView;
import android.view.MenuItem;
import android.view.View;
@ -82,6 +80,7 @@ public abstract class ActivityStreamContextMenu
final MenuItem bookmarkItem = getItemByID(R.id.bookmark);
if (Boolean.TRUE.equals(item.isBookmarked())) {
bookmarkItem.setTitle(R.string.bookmark_remove);
bookmarkItem.setIcon(R.drawable.as_bookmark_filled);
}
final MenuItem pinItem = getItemByID(R.id.pin);
@ -111,6 +110,7 @@ public abstract class ActivityStreamContextMenu
protected void onPostExecute(Boolean hasBookmark) {
if (hasBookmark) {
bookmarkItem.setTitle(R.string.bookmark_remove);
bookmarkItem.setIcon(R.drawable.as_bookmark_filled);
}
item.updateBookmarked(hasBookmark);

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

@ -54,12 +54,13 @@ public class FadedMultiColorTextView extends FadedTextView {
updateGradientShader(needsEllipsis, right);
final float center = getHeight() / 2;
// Shrink height of gradient to prevent it overlaying parent view border.
// The shrunk size just nee to cover the text itself.
final float top = center - getTextSize() / 2;
final float bottom = center + getTextSize() / 2;
final float density = getResources().getDisplayMetrics().density;
final float h = Math.abs(fadePaint.getFontMetrics().top) + 1;
final float l = fadePaint.getFontMetrics().bottom + 1;
final float top = getBaseline() - h * density;
final float bottom = getBaseline() + l * density;
canvas.drawRect(left, top, right, bottom, fadePaint);
}

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

@ -387,6 +387,7 @@ size. -->
<!ENTITY pref_history_search_suggestions "Show search history">
<!ENTITY pref_import_options "Import options">
<!ENTITY pref_import_android_summary "Import bookmarks and history from the native browser">
<!ENTITY pref_private_data_openTabs "Open tabs">
<!ENTITY pref_private_data_history2 "Browsing history">
<!ENTITY pref_private_data_searchHistory "Search history">
<!ENTITY pref_private_data_formdata2 "Form history">

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

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12.01,1C11.508,1.068 11.087,1.415 10.925,1.895L8.178,7.562L2.301,8.552C0.956,8.771 0.622,9.738 1.557,10.7L5.717,15.186L4.748,21.497C4.601,22.445 4.99,22.997 5.673,22.997C5.985,22.985 6.291,22.899 6.564,22.748L12.021,19.817L17.542,22.748C17.816,22.9 18.121,22.985 18.434,22.997C19.117,22.997 19.504,22.442 19.36,21.497L18.394,15.186L22.505,10.705C23.441,9.739 23.105,8.771 21.761,8.552L15.972,7.562L13.1,1.9C12.939,1.416 12.516,1.067 12.01,1L12.01,1Z"/>
</vector>

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

@ -78,6 +78,7 @@
<item>android_import.data.history</item>
</string-array>
<string-array name="pref_private_data_entries">
<item>@string/pref_private_data_openTabs</item>
<item>@string/pref_private_data_history2</item>
<item>@string/pref_private_data_searchHistory</item>
<item>@string/pref_private_data_downloadFiles2</item>
@ -99,9 +100,11 @@
<item>true</item>
<item>true</item>
<item>true</item>
<item>true</item>
<item>false</item>
</string-array>
<string-array name="pref_private_data_values">
<item>private.data.openTabs</item>
<item>private.data.history</item>
<item>private.data.searchHistory</item>
<item>private.data.downloadFiles</item>
@ -114,6 +117,7 @@
<item>private.data.passwords</item>
</string-array>
<string-array name="pref_private_data_keys">
<item>private.data.openTabs</item>
<item>private.data.history</item>
<item>private.data.searchHistory</item>
<item>private.data.downloadFiles</item>
@ -136,6 +140,7 @@
<item>false</item>
<item>false</item>
<item>false</item>
<item>false</item>
</string-array>
<string-array name="pref_restore_entries">
<item>@string/pref_restore_always</item>

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

@ -279,6 +279,7 @@
<string name="pref_sync_summary">&pref_sync_summary2;</string>
<string name="pref_search_suggestions">&pref_search_suggestions;</string>
<string name="pref_history_search_suggestions">&pref_history_search_suggestions;</string>
<string name="pref_private_data_openTabs">&pref_private_data_openTabs;</string>
<string name="pref_private_data_history2">&pref_private_data_history2;</string>
<string name="pref_private_data_searchHistory">&pref_private_data_searchHistory;</string>
<string name="pref_private_data_formdata2">&pref_private_data_formdata2;</string>

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

@ -1470,6 +1470,12 @@ var BrowserApp = {
promises.push(Sanitizer.clearItem("cookies"));
promises.push(Sanitizer.clearItem("sessions"));
break;
case "openTabs":
if (aShutdown === true) {
Services.obs.notifyObservers(null, "browser:purge-session-tabs", "");
break;
}
// fall-through if aShutdown is false
default:
promises.push(Sanitizer.clearItem(key));
}

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

@ -180,6 +180,7 @@ SessionStore.prototype = {
observerService.addObserver(this, "domwindowopened", true);
observerService.addObserver(this, "domwindowclosed", true);
observerService.addObserver(this, "browser:purge-session-history", true);
observerService.addObserver(this, "browser:purge-session-tabs", true);
observerService.addObserver(this, "quit-application-requested", true);
observerService.addObserver(this, "quit-application-proceeding", true);
observerService.addObserver(this, "quit-application", true);
@ -236,8 +237,9 @@ SessionStore.prototype = {
this._loadState = STATE_QUITTING_FLUSHED;
break;
case "browser:purge-session-tabs":
case "browser:purge-session-history": // catch sanitization
log("browser:purge-session-history");
log(aTopic);
this._clearDisk();
// Clear all data about closed tabs
@ -1780,6 +1782,12 @@ SessionStore.prototype = {
},
_sendClosedTabsToJava: function ss_sendClosedTabsToJava(aWindow) {
// If the app is shutting down, we don't need to do anything.
if (this._loadState <= STATE_QUITTING) {
return;
}
if (!aWindow.__SSID) {
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
}

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

@ -9,3 +9,10 @@
-keep public class * extends android.support.v4.view.ActionProvider {
public <init>(android.content.Context);
}
-keepclassmembers class android.support.graphics.drawable.VectorDrawableCompat$* {
void set*(***);
*** get*();
}
-keepattributes LocalVariableTable

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

@ -168,6 +168,26 @@ Sanitizer.prototype = {
}
},
openTabs: {
clear: function ()
{
return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:OpenTabs" })
.catch(e => Cu.reportError("Java-side tab clearing failed: " + e))
.then(function() {
try {
// clear "Recently Closed" tabs in Android App
Services.obs.notifyObservers(null, "browser:purge-session-tabs", "");
}
catch (e) { }
});
},
get canClear()
{
return true;
}
},
searchHistory: {
clear: function ()
{

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

@ -1376,6 +1376,35 @@ var AddonManagerInternal = {
return uri.replace(/\+/g, "%2B");
},
_updatePromptHandler(info) {
let oldPerms = info.existingAddon.userPermissions || {hosts: [], permissions: []};
let newPerms = info.addon.userPermissions;
// See bug 1331769: should we do something more complicated to
// compare host permissions?
// e.g., if we go from <all_urls> to a specific host or from
// a *.domain.com to specific-host.domain.com that's actually a
// drop in permissions but the simple test below will cause a prompt.
let difference = {
hosts: newPerms.hosts.filter(perm => !oldPerms.hosts.includes(perm)),
permissions: newPerms.permissions.filter(perm => !oldPerms.permissions.includes(perm)),
};
// If there are no new permissions, just go ahead with the update
if (difference.hosts.length == 0 && difference.permissions.length == 0) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
let subject = {wrappedJSObject: {
addon: info.addon,
permissions: difference,
resolve, reject
}};
Services.obs.notifyObservers(subject, "webextension-update-permissions", null);
});
},
/**
* Performs a background update check by starting an update for all add-ons
* that can be updated.
@ -1430,6 +1459,9 @@ var AddonManagerInternal = {
// XXX we really should resolve when this install is done,
// not when update-available check completes, no?
logger.debug(`Starting upgrade install of ${aAddon.id}`);
if (WEBEXT_PERMISSION_PROMPTS) {
aInstall.promptHandler = (...args) => AddonManagerInternal._updatePromptHandler(...args);
}
aInstall.install();
}
},

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

@ -508,6 +508,10 @@ public:
*/
bool HasPluginActivationEventMessage() const;
/**
* Returns true if the event can be sent to remote process.
*/
bool CanBeSentToRemoteProcess() const;
/**
* Returns true if the event is native event deliverer event for plugin and
* it should be retarted to focused document.

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

@ -306,40 +306,40 @@ PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect)
}
void
PuppetWidget::InitEvent(WidgetGUIEvent& event, LayoutDeviceIntPoint* aPoint)
PuppetWidget::InitEvent(WidgetGUIEvent& aEvent, LayoutDeviceIntPoint* aPoint)
{
if (nullptr == aPoint) {
event.mRefPoint = LayoutDeviceIntPoint(0, 0);
aEvent.mRefPoint = LayoutDeviceIntPoint(0, 0);
} else {
// use the point override if provided
event.mRefPoint = *aPoint;
aEvent.mRefPoint = *aPoint;
}
event.mTime = PR_Now() / 1000;
aEvent.mTime = PR_Now() / 1000;
}
nsresult
PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
PuppetWidget::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
{
#ifdef DEBUG
debug_DumpEvent(stdout, event->mWidget, event, "PuppetWidget", 0);
debug_DumpEvent(stdout, aEvent->mWidget, aEvent, "PuppetWidget", 0);
#endif
MOZ_ASSERT(!mChild || mChild->mWindowType == eWindowType_popup,
"Unexpected event dispatch!");
AutoCacheNativeKeyCommands autoCache(this);
if ((event->mFlags.mIsSynthesizedForTests ||
event->mFlags.mIsSuppressedOrDelayed) && !mNativeKeyCommandsValid) {
WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
if ((aEvent->mFlags.mIsSynthesizedForTests ||
aEvent->mFlags.mIsSuppressedOrDelayed) && !mNativeKeyCommandsValid) {
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
if (keyEvent) {
mTabChild->RequestNativeKeyBindings(&autoCache, keyEvent);
}
}
if (event->mClass == eCompositionEventClass) {
if (aEvent->mClass == eCompositionEventClass) {
// Store the latest native IME context of parent process's widget or
// TextEventDispatcher if it's in this process.
WidgetCompositionEvent* compositionEvent = event->AsCompositionEvent();
WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
#ifdef DEBUG
if (mNativeIMEContext.IsValid() &&
mNativeIMEContext != compositionEvent->mNativeIMEContext) {
@ -357,7 +357,8 @@ PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
aStatus = nsEventStatus_eIgnore;
if (GetCurrentWidgetListener()) {
aStatus = GetCurrentWidgetListener()->HandleEvent(event, mUseAttachedEvents);
aStatus =
GetCurrentWidgetListener()->HandleEvent(aEvent, mUseAttachedEvents);
}
return NS_OK;
@ -409,8 +410,9 @@ PuppetWidget::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
return NS_ERROR_FAILURE;
}
mTabChild->SendSynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
aModifierFlags, nsString(aCharacters), nsString(aUnmodifiedCharacters),
notifier.SaveObserver());
aModifierFlags, nsString(aCharacters),
nsString(aUnmodifiedCharacters),
notifier.SaveObserver());
return NS_OK;
}
@ -425,7 +427,8 @@ PuppetWidget::SynthesizeNativeMouseEvent(mozilla::LayoutDeviceIntPoint aPoint,
return NS_ERROR_FAILURE;
}
mTabChild->SendSynthesizeNativeMouseEvent(aPoint, aNativeMessage,
aModifierFlags, notifier.SaveObserver());
aModifierFlags,
notifier.SaveObserver());
return NS_OK;
}
@ -442,22 +445,25 @@ PuppetWidget::SynthesizeNativeMouseMove(mozilla::LayoutDeviceIntPoint aPoint,
}
nsresult
PuppetWidget::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
uint32_t aModifierFlags,
uint32_t aAdditionalFlags,
nsIObserver* aObserver)
PuppetWidget::SynthesizeNativeMouseScrollEvent(
mozilla::LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
uint32_t aModifierFlags,
uint32_t aAdditionalFlags,
nsIObserver* aObserver)
{
AutoObserverNotifier notifier(aObserver, "mousescrollevent");
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
mTabChild->SendSynthesizeNativeMouseScrollEvent(aPoint, aNativeMessage,
aDeltaX, aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags,
notifier.SaveObserver());
aDeltaX, aDeltaY, aDeltaZ,
aModifierFlags,
aAdditionalFlags,
notifier.SaveObserver());
return NS_OK;
}
@ -474,8 +480,9 @@ PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId,
return NS_ERROR_FAILURE;
}
mTabChild->SendSynthesizeNativeTouchPoint(aPointerId, aPointerState,
aPoint, aPointerPressure, aPointerOrientation,
notifier.SaveObserver());
aPoint, aPointerPressure,
aPointerOrientation,
notifier.SaveObserver());
return NS_OK;
}
@ -489,7 +496,7 @@ PuppetWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
return NS_ERROR_FAILURE;
}
mTabChild->SendSynthesizeNativeTouchTap(aPoint, aLongTap,
notifier.SaveObserver());
notifier.SaveObserver());
return NS_OK;
}
@ -505,8 +512,9 @@ PuppetWidget::ClearNativeTouchSequence(nsIObserver* aObserver)
}
void
PuppetWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
PuppetWidget::SetConfirmedTargetAPZC(
uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
if (mTabChild) {
mTabChild->SetTargetAPZC(aInputBlockId, aTargets);
@ -530,15 +538,12 @@ PuppetWidget::AsyncPanZoomEnabled() const
}
bool
PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData)
PuppetWidget::ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData)
{
// B2G doesn't have native key bindings.
#ifdef MOZ_WIDGET_GONK
return false;
#else // #ifdef MOZ_WIDGET_GONK
AutoCacheNativeKeyCommands autoCache(this);
if (!aEvent.mWidget && !mNativeKeyCommandsValid) {
MOZ_ASSERT(!aEvent.mFlags.mIsSynthesizedForTests);
@ -575,7 +580,6 @@ PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
aCallback(static_cast<mozilla::Command>((*commands)[i]), aCallbackData);
}
return true;
#endif
}
LayerManager*
@ -606,7 +610,6 @@ PuppetWidget::RecreateLayerManager(PLayerTransactionChild* aShadowManager)
nsresult
PuppetWidget::RequestIMEToCommitComposition(bool aCancel)
{
#ifdef MOZ_CROSS_PROCESS_IME
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
@ -646,9 +649,6 @@ PuppetWidget::RequestIMEToCommitComposition(bool aCancel)
DispatchEvent(&compositionCommitEvent, status);
// NOTE: PuppetWidget might be destroyed already.
#endif // #ifdef MOZ_CROSS_PROCESS_IME
return NS_OK;
}
@ -717,11 +717,6 @@ PuppetWidget::SetInputContext(const InputContext& aContext,
// can be changed by user but native IME may not notify us of changing the
// open state on some platforms.
mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
#ifndef MOZ_CROSS_PROCESS_IME
return;
#endif
if (!mTabChild) {
return;
}
@ -738,10 +733,6 @@ PuppetWidget::SetInputContext(const InputContext& aContext,
InputContext
PuppetWidget::GetInputContext()
{
#ifndef MOZ_CROSS_PROCESS_IME
return InputContext();
#endif
// XXX Currently, we don't support retrieving IME open state from child
// process.
@ -777,12 +768,9 @@ PuppetWidget::GetNativeIMEContext()
nsresult
PuppetWidget::NotifyIMEOfFocusChange(const IMENotification& aIMENotification)
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (!mTabChild)
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
bool gotFocus = aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS;
if (gotFocus) {
@ -816,11 +804,9 @@ nsresult
PuppetWidget::NotifyIMEOfCompositionUpdate(
const IMENotification& aIMENotification)
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}
if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
@ -833,7 +819,6 @@ PuppetWidget::NotifyIMEOfCompositionUpdate(
nsIMEUpdatePreference
PuppetWidget::GetIMEUpdatePreference()
{
#ifdef MOZ_CROSS_PROCESS_IME
// e10s requires IME content cache in in the TabParent for handling query
// content event only with the parent process. Therefore, this process
// needs to receive a lot of information from the focused editor to sent
@ -848,10 +833,6 @@ PuppetWidget::GetIMEUpdatePreference()
return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
#else
// B2G doesn't handle IME as widget-level.
return nsIMEUpdatePreference();
#endif
}
nsresult
@ -859,13 +840,9 @@ PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
{
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
"Passed wrong notification");
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (!mTabChild)
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
// While a plugin has focus, text change notification shouldn't be available.
if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
@ -896,13 +873,9 @@ PuppetWidget::NotifyIMEOfSelectionChange(
{
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
"Passed wrong notification");
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (!mTabChild)
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
// While a plugin has focus, selection change notification shouldn't be
// available.
@ -951,9 +924,6 @@ PuppetWidget::NotifyIMEOfMouseButtonEvent(
nsresult
PuppetWidget::NotifyIMEOfPositionChange(const IMENotification& aIMENotification)
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}

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

@ -313,6 +313,41 @@ WidgetEvent::HasPluginActivationEventMessage() const
* Specific event checking methods.
******************************************************************************/
bool
WidgetEvent::CanBeSentToRemoteProcess() const
{
// If this event is explicitly marked as shouldn't be sent to remote process,
// just return false.
if (mFlags.mNoCrossProcessBoundaryForwarding) {
return false;
}
if (mClass == eKeyboardEventClass ||
mClass == eWheelEventClass) {
return true;
}
switch (mMessage) {
case eMouseDown:
case eMouseUp:
case eMouseMove:
case eContextMenu:
case eMouseEnterIntoWidget:
case eMouseExitFromWidget:
case eMouseTouchDrag:
case eTouchStart:
case eTouchMove:
case eTouchEnd:
case eTouchCancel:
case eDragOver:
case eDragExit:
case eDrop:
return true;
default:
return false;
}
}
bool
WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
{