Merge m-c to b2g-inbound a=merge

This commit is contained in:
Wes Kocher 2014-10-24 15:07:43 -07:00
Родитель b818f677ef a3f4d1e96c
Коммит 707341e841
166 изменённых файлов: 3483 добавлений и 1287 удалений

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

@ -6,6 +6,9 @@
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<style>
#listitemnone {
list-style-type: none;
}
h6.gencontent:before {
content: "aga"
}
@ -67,13 +70,17 @@
//////////////////////////////////////////////////////////////////////////
IDs = [ "list" ];
testCharacterCount(IDs, 1);
testText(IDs, 0, 1, kEmbedChar);
testCharacterCount(IDs, 2);
testText(IDs, 0, 2, kEmbedChar + kEmbedChar);
IDs = [ "listitem" ];
testCharacterCount(IDs, 6);
testText(IDs, 0, 6, "1. foo");
IDs = [ "listitemnone" ];
testCharacterCount(IDs, 3);
testText(IDs, 0, 3, "bar");
testText(["testbr"], 0, 3, "foo");
testTextAtOffset(2, nsIAccessibleText.BOUNDARY_CHAR, "o", 2, 3, "testbr",
@ -117,7 +124,10 @@
<div id="hypertext">hello <a>friend</a> see <img></div>
<div id="hypertext2">hello <a>friend</a> see <input></div>
<ol id="list"><li id="listitem">foo</li></ol>
<ol id="list">
<li id="listitem">foo</li>
<li id="listitemnone">bar</li>
</ol>
<div id="hypertext3">line
<!-- haha -->

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

@ -62,7 +62,8 @@ TestRunner.prototype = {
},
_uncaughtErrorObserver: function({message, date, fileName, stack, lineNumber}) {
this.fail("There was an uncaught Promise rejection: " + stack);
this.fail("There was an uncaught Promise rejection: " + message + " @ " +
fileName + ":" + lineNumber + "\n" + stack);
},
pass: function pass(message) {

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

@ -1613,7 +1613,7 @@ pref("loop.soft_start_hostname", "soft-start.loop.services.mozilla.com");
pref("loop.server", "https://loop.services.mozilla.com");
pref("loop.seenToS", "unseen");
pref("loop.learnMoreUrl", "https://www.firefox.com/hello/");
pref("loop.legal.ToS_url", "https://call.mozilla.com/legal/terms/");
pref("loop.legal.ToS_url", "https://hello.firefox.com/legal/terms/");
pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/");
pref("loop.do_not_disturb", false);
pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");

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

@ -52,19 +52,37 @@ var security = {
cAName : issuerName,
encryptionAlgorithm : undefined,
encryptionStrength : undefined,
version: undefined,
isBroken : isBroken,
isEV : isEV,
cert : cert,
fullLocation : gWindow.location
};
var version;
try {
retval.encryptionAlgorithm = status.cipherName;
retval.encryptionStrength = status.secretKeyLength;
version = status.protocolVersion;
}
catch (e) {
}
switch (version) {
case nsISSLStatus.SSL_VERSION_3:
retval.version = "SSL 3";
break;
case nsISSLStatus.TLS_VERSION_1:
retval.version = "TLS 1.0";
break;
case nsISSLStatus.TLS_VERSION_1_1:
retval.version = "TLS 1.1";
break;
case nsISSLStatus.TLS_VERSION_1_2:
retval.version = "TLS 1.2"
break;
}
return retval;
} else {
return {
@ -72,10 +90,11 @@ var security = {
cAName : "",
encryptionAlgorithm : "",
encryptionStrength : 0,
version: "",
isBroken : isBroken,
isEV : isEV,
cert : null,
fullLocation : gWindow.location
fullLocation : gWindow.location
};
}
},
@ -239,15 +258,19 @@ function securityOnLoad() {
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}
else if (info.encryptionStrength >= 90) {
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBits",
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
security._cert = info.cert;
}
else if (info.encryptionStrength > 0) {
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBits",
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
}

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

@ -16,20 +16,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "LOOP_SESSION_TYPE",
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
"resource:///modules/loop/MozLoopPushHandler.jsm");
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
XPCOMUtils.defineLazyGetter(this, "log", () => {
let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI;
let consoleOptions = {
maxLogLevel: Services.prefs.getCharPref(PREF_LOG_LEVEL).toLowerCase(),
prefix: "Loop",
};
return new ConsoleAPI(consoleOptions);
});
this.EXPORTED_SYMBOLS = ["LoopRooms", "roomsPushNotification"];
let gRoomsListFetched = false;
let gRooms = new Map();
let gCallbacks = new Map();
/**
* Callback used to indicate changes to rooms data on the LoopServer.
@ -59,7 +50,7 @@ let LoopRoomsInternal = {
// identifier.
for (let room of rooms) {
let id = MozLoopService.generateLocalID();
room.localRoomID = id;
room.localRoomId = id;
// Next, request the detailed information for each room.
// If the request fails the room data will not be added to the map.
try {
@ -67,22 +58,24 @@ let LoopRoomsInternal = {
for (let attr in details) {
room[attr] = details[attr]
}
delete room.currSize; //This attribute will be eliminated in the next revision.
gRooms.set(id, room);
}
catch (error) {log.warn("failed GETing room details for roomToken = " + room.roomToken + ": ", error)}
catch (error) {MozLoopService.log.warn(
"failed GETing room details for roomToken = " + room.roomToken + ": ", error)}
}
callback(null, [...gRooms.values()]);
return;
}.bind(this)).catch((error) => {log.error("getAll error:", error);
}.bind(this)).catch((error) => {MozLoopService.log.error("getAll error:", error);
callback(error)});
return;
},
getRoomData: function(roomID, callback) {
if (gRooms.has(roomID)) {
callback(null, gRooms.get(roomID));
getRoomData: function(localRoomId, callback) {
if (gRooms.has(localRoomId)) {
callback(null, gRooms.get(localRoomId));
} else {
callback(new Error("Room data not found or not fetched yet for room with ID " + roomID));
callback(new Error("Room data not found or not fetched yet for room with ID " + localRoomId));
}
return;
},
@ -130,6 +123,150 @@ let LoopRoomsInternal = {
onNotification: function(version, channelID) {
return;
},
createRoom: function(props, callback) {
// Always create a basic room record and launch the window, attaching
// the localRoomId. Later errors will be returned via the registered callback.
let localRoomId = MozLoopService.generateLocalID((id) => {gRooms.has(id)})
let room = {localRoomId : localRoomId};
for (let prop in props) {
room[prop] = props[prop]
}
gRooms.set(localRoomId, room);
this.addCallback(localRoomId, "RoomCreated", callback);
MozLoopService.openChatWindow(null, "", "about:loopconversation#room/" + localRoomId);
if (!"roomName" in props ||
!"expiresIn" in props ||
!"roomOwner" in props ||
!"maxSize" in props) {
this.postCallback(localRoomId, "RoomCreated",
new Error("missing required room create property"));
return localRoomId;
}
let sessionType = MozLoopService.userProfile ? LOOP_SESSION_TYPE.FXA :
LOOP_SESSION_TYPE.GUEST;
MozLoopService.hawkRequest(sessionType, "/rooms", "POST", props).then(
(response) => {
let data = JSON.parse(response.body);
for (let attr in data) {
room[attr] = data[attr]
}
delete room.expiresIn; //Do not keep this value - it is a request to the server
this.postCallback(localRoomId, "RoomCreated", null, room);
},
(error) => {
this.postCallback(localRoomId, "RoomCreated", error);
});
return localRoomId;
},
/**
* Send an update to the callbacks registered for a specific localRoomId
* for a callback type.
*
* The result set is always saved. Then each
* callback function that has been registered when this function is
* called will be called with the result set. Any new callback that
* is regsitered via addCallback will receive a copy of the last
* saved result set when registered. This allows the posting operation
* to complete before the callback is registered in an asynchronous
* operation.
*
* Callbacsk must be of the form:
* function (error, success) {...}
*
* @param {String} localRoomId Local room identifier.
* @param {String} callbackName callback type
* @param {?Error} error result or null.
* @param {?Object} success result if error argument is null.
*/
postCallback: function(localRoomId, callbackName, error, success) {
let roomCallbacks = gCallbacks.get(localRoomId);
if (!roomCallbacks) {
// No callbacks have been registered or results posted for this room.
// Initialize a record for this room and callbackName, saving the
// result set.
gCallbacks.set(localRoomId, new Map([[
callbackName,
{ callbackList: [], result: { error: error, success: success } }]]));
return;
}
let namedCallback = roomCallbacks.get(callbackName);
// A callback of this name has not been registered.
if (!namedCallback) {
roomCallbacks.set(
callbackName,
{callbackList: [], result: {error: error, success: success}});
return;
}
// Record the latest result set.
namedCallback.result = {error: error, success: success};
// Call each registerd callback passing the new result posted.
namedCallback.callbackList.forEach((callback) => {
callback(error, success);
});
},
addCallback: function(localRoomId, callbackName, callback) {
let roomCallbacks = gCallbacks.get(localRoomId);
if (!roomCallbacks) {
// No callbacks have been registered or results posted for this room.
// Initialize a record for this room and callbackName.
gCallbacks.set(localRoomId, new Map([[
callbackName,
{callbackList: [callback]}]]));
return;
}
let namedCallback = roomCallbacks.get(callbackName);
// A callback of this name has not been registered.
if (!namedCallback) {
roomCallbacks.set(
callbackName,
{callbackList: [callback]});
return;
}
// Add this callback if not already in the array
if (namedCallback.callbackList.indexOf(callback) >= 0) {
return;
}
namedCallback.callbackList.push(callback);
// If a result has been posted for this callback
// send it using this new callback function.
let result = namedCallback.result;
if (result) {
callback(result.error, result.success);
}
},
deleteCallback: function(localRoomId, callbackName, callback) {
let roomCallbacks = gCallbacks.get(localRoomId);
if (!roomCallbacks) {
return;
}
let namedCallback = roomCallbacks.get(callbackName);
if (!namedCallback) {
return;
}
let i = namedCallback.callbackList.indexOf(callback);
if (i >= 0) {
namedCallback.callbackList.splice(i, 1);
}
return;
},
};
Object.freeze(LoopRoomsInternal);
@ -156,15 +293,51 @@ this.LoopRooms = {
/**
* Return the current stored version of the data for the indicated room.
*
* @param {String} roomID Local room identifier
* @param {String} localRoomId Local room identifier
* @param {Function} callback Function that will be invoked once the operation
* finished. The first argument passed will be an
* `Error` object or `null`. The second argument will
* be the list of rooms, if it was fetched successfully.
*/
getRoomData: function(roomID, callback) {
return LoopRoomsInternal.getRoomData(roomID, callback);
getRoomData: function(localRoomId, callback) {
return LoopRoomsInternal.getRoomData(localRoomId, callback);
},
/**
* Create a room. Will both open a chat window for the new room
* and perform an exchange with the LoopServer to create the room.
* for a callback type. Callback must be of the form:
* function (error, success) {...}
*
* @param {Object} room properties to be sent to the LoopServer
* @param {Function} callback Must be of the form: function (error, success) {...}
*
* @returns {String} localRoomId assigned to this new room.
*/
createRoom: function(roomProps, callback) {
return LoopRoomsInternal.createRoom(roomProps, callback);
},
/**
* Register a callback of a specified type with a localRoomId.
*
* @param {String} localRoomId Local room identifier.
* @param {String} callbackName callback type
* @param {Function} callback Must be of the form: function (error, success) {...}
*/
addCallback: function(localRoomId, callbackName, callback) {
return LoopRoomsInternal.addCallback(localRoomId, callbackName, callback);
},
/**
* Un-register and delete a callback of a specified type for a localRoomId.
*
* @param {String} localRoomId Local room identifier.
* @param {String} callbackName callback type
* @param {Function} callback Previously passed to addCallback().
*/
deleteCallback: function(localRoomId, callbackName, callback) {
return LoopRoomsInternal.deleteCallback(localRoomId, callbackName, callback);
},
};
Object.freeze(LoopRooms);

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

@ -178,6 +178,35 @@ loop.conversation = (function(mozL10n) {
}
});
/**
* Incoming Call failed view. Displayed when a call fails.
*
* XXX Based on CallFailedView, but built specially until we flux-ify the
* incoming call views (bug 1088672).
*/
var IncomingCallFailedView = React.createClass({displayName: 'IncomingCallFailedView',
propTypes: {
cancelCall: React.PropTypes.func.isRequired
},
render: function() {
document.title = mozL10n.get("generic_failure_title");
return (
React.DOM.div({className: "call-window"},
React.DOM.h2(null, mozL10n.get("generic_failure_title")),
React.DOM.div({className: "btn-group call-action-group"},
React.DOM.button({className: "btn btn-cancel",
onClick: this.props.cancelCall},
mozL10n.get("cancel_button")
)
)
)
);
}
});
/**
* This view manages the incoming conversation views - from
* call initiation through to the actual conversation and call end.
@ -254,11 +283,13 @@ loop.conversation = (function(mozL10n) {
case "end": {
// XXX To be handled with the "failed" view state when bug 1047410 lands
if (this.state.callFailed) {
document.title = mozL10n.get("generic_failure_title");
} else {
document.title = mozL10n.get("conversation_has_ended");
return IncomingCallFailedView({
cancelCall: this.closeWindow.bind(this)}
)
}
document.title = mozL10n.get("conversation_has_ended");
var feebackAPIBaseUrl = navigator.mozLoop.getLoopCharPref(
"feedback.baseUrl");
@ -394,19 +425,25 @@ loop.conversation = (function(mozL10n) {
if (progressData.state !== "terminated")
return;
if (progressData.reason === "cancel" ||
progressData.reason === "closed") {
// XXX This would be nicer in the _abortIncomingCall function, but we need to stop
// it here for now due to server-side issues that are being fixed in bug 1088351.
// This is before the abort call to ensure that it happens before the window is
// closed.
navigator.mozLoop.stopAlerting();
// If we hit any of the termination reasons, and the user hasn't accepted
// then it seems reasonable to close the window/abort the incoming call.
//
// If the user has accepted the call, and something's happened, display
// the call failed view.
//
// https://wiki.mozilla.org/Loop/Architecture/MVP#Termination_Reasons
if (previousState === "init" || previousState === "alerting") {
this._abortIncomingCall();
return;
} else {
this.setState({callFailed: true, callStatus: "end"});
}
if (progressData.reason === "timeout") {
if (previousState === "init" || previousState === "alerting") {
this._abortIncomingCall();
} else {
this.setState({callFailed: true, callStatus: "end"});
}
}
},
/**
@ -414,7 +451,6 @@ loop.conversation = (function(mozL10n) {
* closes the websocket.
*/
_abortIncomingCall: function() {
navigator.mozLoop.stopAlerting();
this._websocket.close();
// Having a timeout here lets the logging for the websocket complete and be
// displayed on the console if both are on.
@ -644,6 +680,7 @@ loop.conversation = (function(mozL10n) {
AppControllerView: AppControllerView,
IncomingConversationView: IncomingConversationView,
IncomingCallView: IncomingCallView,
IncomingCallFailedView: IncomingCallFailedView,
init: init
};
})(document.mozL10n);

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

@ -178,6 +178,35 @@ loop.conversation = (function(mozL10n) {
}
});
/**
* Incoming Call failed view. Displayed when a call fails.
*
* XXX Based on CallFailedView, but built specially until we flux-ify the
* incoming call views (bug 1088672).
*/
var IncomingCallFailedView = React.createClass({
propTypes: {
cancelCall: React.PropTypes.func.isRequired
},
render: function() {
document.title = mozL10n.get("generic_failure_title");
return (
<div className="call-window">
<h2>{mozL10n.get("generic_failure_title")}</h2>
<div className="btn-group call-action-group">
<button className="btn btn-cancel"
onClick={this.props.cancelCall}>
{mozL10n.get("cancel_button")}
</button>
</div>
</div>
);
}
});
/**
* This view manages the incoming conversation views - from
* call initiation through to the actual conversation and call end.
@ -254,11 +283,13 @@ loop.conversation = (function(mozL10n) {
case "end": {
// XXX To be handled with the "failed" view state when bug 1047410 lands
if (this.state.callFailed) {
document.title = mozL10n.get("generic_failure_title");
} else {
document.title = mozL10n.get("conversation_has_ended");
return <IncomingCallFailedView
cancelCall={this.closeWindow.bind(this)}
/>
}
document.title = mozL10n.get("conversation_has_ended");
var feebackAPIBaseUrl = navigator.mozLoop.getLoopCharPref(
"feedback.baseUrl");
@ -394,19 +425,25 @@ loop.conversation = (function(mozL10n) {
if (progressData.state !== "terminated")
return;
if (progressData.reason === "cancel" ||
progressData.reason === "closed") {
// XXX This would be nicer in the _abortIncomingCall function, but we need to stop
// it here for now due to server-side issues that are being fixed in bug 1088351.
// This is before the abort call to ensure that it happens before the window is
// closed.
navigator.mozLoop.stopAlerting();
// If we hit any of the termination reasons, and the user hasn't accepted
// then it seems reasonable to close the window/abort the incoming call.
//
// If the user has accepted the call, and something's happened, display
// the call failed view.
//
// https://wiki.mozilla.org/Loop/Architecture/MVP#Termination_Reasons
if (previousState === "init" || previousState === "alerting") {
this._abortIncomingCall();
return;
} else {
this.setState({callFailed: true, callStatus: "end"});
}
if (progressData.reason === "timeout") {
if (previousState === "init" || previousState === "alerting") {
this._abortIncomingCall();
} else {
this.setState({callFailed: true, callStatus: "end"});
}
}
},
/**
@ -414,7 +451,6 @@ loop.conversation = (function(mozL10n) {
* closes the websocket.
*/
_abortIncomingCall: function() {
navigator.mozLoop.stopAlerting();
this._websocket.close();
// Having a timeout here lets the logging for the websocket complete and be
// displayed on the console if both are on.
@ -644,6 +680,7 @@ loop.conversation = (function(mozL10n) {
AppControllerView: AppControllerView,
IncomingConversationView: IncomingConversationView,
IncomingCallView: IncomingCallView,
IncomingCallFailedView: IncomingCallFailedView,
init: init
};
})(document.mozL10n);

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

@ -431,87 +431,7 @@ describe("loop.conversation", function() {
sandbox.stub(window, "close");
});
describe("progress - terminated - cancel", function() {
it("should stop alerting", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "cancel"
});
sinon.assert.calledOnce(navigator.mozLoop.stopAlerting);
done();
});
});
it("should close the websocket", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "cancel"
});
sinon.assert.calledOnce(icView._websocket.close);
done();
});
});
it("should close the window", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "cancel"
});
sandbox.clock.tick(1);
sinon.assert.calledOnce(window.close);
done();
});
});
});
describe("progress - terminated - closed", function() {
it("should stop alerting", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "closed"
});
sinon.assert.calledOnce(navigator.mozLoop.stopAlerting);
done();
});
});
it("should close the websocket", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "closed"
});
sinon.assert.calledOnce(icView._websocket.close);
done();
});
});
it("should close the window", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "closed"
});
sandbox.clock.tick(1);
sinon.assert.calledOnce(window.close);
done();
});
});
});
describe("progress - terminated - timeout (previousState = alerting)", function() {
describe("progress - terminated (previousState = alerting)", function() {
it("should stop alerting", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
@ -528,7 +448,7 @@ describe("loop.conversation", function() {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "timeout"
reason: "closed"
}, "alerting");
sinon.assert.calledOnce(icView._websocket.close);
@ -540,7 +460,7 @@ describe("loop.conversation", function() {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "timeout"
reason: "answered-elsewhere"
}, "alerting");
sandbox.clock.tick(1);
@ -551,21 +471,33 @@ describe("loop.conversation", function() {
});
});
describe("progress - terminated - timeout (previousState not init" +
describe("progress - terminated (previousState not init" +
" nor alerting)",
function() {
it("should set the state to end", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "timeout"
reason: "media-fail"
}, "connecting");
expect(icView.state.callStatus).eql("end");
done();
});
});
});
it("should stop alerting", function(done) {
promise.then(function() {
icView._websocket.trigger("progress", {
state: "terminated",
reason: "media-fail"
}, "connecting");
sinon.assert.calledOnce(navigator.mozLoop.stopAlerting);
done();
});
});
});
});
});
});
@ -761,12 +693,12 @@ describe("loop.conversation", function() {
});
describe("session:network-disconnected", function() {
it("should navigate to call/feedback when network disconnects",
it("should navigate to call failed when network disconnects",
function() {
conversation.trigger("session:network-disconnected");
TestUtils.findRenderedComponentWithType(icView,
sharedView.FeedbackView);
loop.conversation.IncomingCallFailedView);
});
it("should update the conversation window toolbar title",

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

@ -0,0 +1,103 @@
/* 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/. */
Cu.import("resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
"resource:///modules/Chat.jsm");
let hasTheseProps = function(a, b) {
for (let prop in a) {
if (a[prop] != b[prop]) {
return false;
}
}
return true;
}
let openChatOrig = Chat.open;
add_test(function test_openRoomsWindow() {
let roomProps = {roomName: "UX Discussion",
expiresIn: 5,
roomOwner: "Alexis",
maxSize: 2}
let roomData = {roomToken: "_nxD4V4FflQ",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
expiresAt: 1405534180}
loopServer.registerPathHandler("/rooms", (request, response) => {
if (!request.bodyInputStream) {
do_throw("empty request body");
}
let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
let data = JSON.parse(body);
do_check_true(hasTheseProps(roomProps, data));
response.setStatusLine(null, 200, "OK");
response.write(JSON.stringify(roomData));
response.processAsync();
response.finish();
});
MozLoopService.register(mockPushHandler).then(() => {
let opened = false;
let created = false;
let urlPieces = [];
Chat.open = function(contentWindow, origin, title, url) {
urlPieces = url.split('/');
do_check_eq(urlPieces[0], "about:loopconversation#room");
opened = true;
};
let returnedID = LoopRooms.createRoom(roomProps, (error, data) => {
do_check_false(error);
do_check_true(data);
do_check_true(hasTheseProps(roomData, data));
do_check_eq(data.localRoomId, urlPieces[1]);
created = true;
});
waitForCondition(function() created && opened).then(() => {
do_check_true(opened, "should open a chat window");
do_check_eq(returnedID, urlPieces[1]);
// Verify that a delayed callback, when attached,
// received the same data.
LoopRooms.addCallback(
urlPieces[1], "RoomCreated",
(error, data) => {
do_check_false(error);
do_check_true(data);
do_check_true(hasTheseProps(roomData, data));
do_check_eq(data.localRoomId, urlPieces[1]);
});
run_next_test();
}, () => {
do_throw("should have opened a chat window");
});
});
});
function run_test()
{
setupFakeLoopServer();
mockPushHandler.registrationPushURL = kEndPointUrl;
loopServer.registerPathHandler("/registration", (request, response) => {
response.setStatusLine(null, 200, "OK");
response.processAsync();
response.finish();
});
do_register_cleanup(function() {
// Revert original Chat.open implementation
Chat.open = openChatOrig;
});
run_next_test();
}

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

@ -94,14 +94,16 @@ add_test(function test_getAllRooms() {
do_check_eq(rooms[2].roomName, "Third Room Name");
let room = rooms[0];
do_check_true(room.localRoomID);
do_check_true(room.localRoomId);
do_check_false(room.currSize);
delete roomList[0].currSize;
do_check_true(hasTheseProps(roomList[0], room));
delete roomDetail.roomName;
delete room.participants;
delete roomDetail.participants;
do_check_true(hasTheseProps(roomDetail, room));
LoopRooms.getRoomData(room.localRoomID, (error, roomData) => {
LoopRooms.getRoomData(room.localRoomId, (error, roomData) => {
do_check_false(error);
do_check_true(hasTheseProps(room, roomData));

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

@ -22,3 +22,4 @@ skip-if = toolkit == 'gonk'
[test_loopservice_token_validation.js]
[test_loopservice_busy.js]
[test_rooms_getdata.js]
[test_rooms_create.js]

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

@ -1623,11 +1623,25 @@ BrowserGlue.prototype = {
// Reset homepage pref for users who have it set to start.mozilla.org
// or google.com/firefox.
const HOMEPAGE_PREF = "browser.startup.homepage";
let uri = Services.prefs.getComplexValue(HOMEPAGE_PREF,
Ci.nsIPrefLocalizedString).data;
if (uri && (uri.startsWith("http://start.mozilla.org") ||
/^https?:\/\/(www\.)?google\.[a-z.]+\/firefox/i.test(uri))) {
Services.prefs.clearUserPref(HOMEPAGE_PREF);
if (Services.prefs.prefHasUserValue(HOMEPAGE_PREF)) {
const DEFAULT =
Services.prefs.getDefaultBranch(HOMEPAGE_PREF)
.getComplexValue("", Ci.nsIPrefLocalizedString).data;
let value =
Services.prefs.getComplexValue(HOMEPAGE_PREF, Ci.nsISupportsString);
let updated =
value.data.replace(/https?:\/\/start\.mozilla\.org[^|]*/i, DEFAULT)
.replace(/https?:\/\/(www\.)?google\.[a-z.]+\/firefox[^|]*/i,
DEFAULT);
if (updated != value.data) {
if (updated == DEFAULT) {
Services.prefs.clearUserPref(HOMEPAGE_PREF);
} else {
value.data = updated;
Services.prefs.setComplexValue(HOMEPAGE_PREF,
Ci.nsISupportsString, value);
}
}
}
}

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

@ -92,6 +92,7 @@ function parseDeclarations(inputString) {
case "FUNCTION":
current += token.value + "(";
break;
case "(":
case ")":
current += token.tokenType;
break;

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

@ -163,7 +163,9 @@ const TEST_DATA = [
{name: "content", value: '"a not s\
o very long title"', priority: ""}
]
}
},
// Test calc with nested parentheses
{input: "width: calc((100% - 3em) / 2)", expected: [{name: "width", value: "calc((100% - 3em) / 2)", priority: ""}]},
];
function run_test() {

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

@ -23,7 +23,7 @@ def main(file):
appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
appdata['flags'] = ' | '.join(flags) if flags else '0'
appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
expected = ('App:vendor', 'App:name', 'App:version', 'App:buildid',
expected = ('App:vendor', 'App:name', 'App:remotingname', 'App:version', 'App:buildid',
'App:id', 'Gecko:minversion', 'Gecko:maxversion')
missing = [var for var in expected if var not in appdata]
if missing:
@ -40,6 +40,7 @@ def main(file):
NULL, // directory
"%(App:vendor)s",
"%(App:name)s",
"%(App:remotingname)s",
"%(App:version)s",
"%(App:buildid)s",
"%(App:id)s",

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

@ -18,6 +18,7 @@
[App]
Vendor=@MOZ_APP_VENDOR@
Name=@MOZ_APP_BASENAME@
RemotingName=@MOZ_APP_REMOTINGNAME@
#ifdef MOZ_APP_DISPLAYNAME
CodeName=@MOZ_APP_DISPLAYNAME@
#endif

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

@ -27,7 +27,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
for var in ('GRE_MILESTONE', 'MOZ_APP_VERSION', 'MOZ_APP_BASENAME',
'MOZ_APP_VENDOR', 'MOZ_APP_ID', 'MAR_CHANNEL_ID',
'ACCEPTED_MAR_CHANNEL_IDS'):
'ACCEPTED_MAR_CHANNEL_IDS', 'MOZ_APP_REMOTINGNAME'):
DEFINES[var] = CONFIG[var]
if CONFIG['MOZ_APP_DISPLAYNAME'] != CONFIG['MOZ_APP_BASENAME']:

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

@ -8683,6 +8683,8 @@ AC_SUBST(MOZ_CHILD_PROCESS_BUNDLE)
# - MOZ_APP_VERSION: Defines the application version number.
# - MOZ_APP_NAME: Used for e.g. the binary program file name. If not set,
# defaults to a lowercase form of MOZ_APP_BASENAME.
# - MOZ_APP_REMOTINGNAME: Used for the internal program name, which affects
# profile name and remoting. If not set, defaults to MOZ_APP_NAME.
# - MOZ_APP_PROFILE: When set, used for application.ini's
# "Profile" field, which controls profile location.
# - MOZ_APP_ID: When set, used for application.ini's "ID" field, and
@ -8693,6 +8695,10 @@ if test -z "$MOZ_APP_NAME"; then
MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
fi
if test -z "$MOZ_APP_REMOTINGNAME"; then
MOZ_APP_REMOTINGNAME=$MOZ_APP_NAME
fi
# For extensions and langpacks, we require a max version that is compatible
# across security releases. MOZ_APP_MAXVERSION is our method for doing that.
# 24.0a1 and 24.0a2 aren't affected
@ -8712,6 +8718,7 @@ AC_DEFINE_UNQUOTED(MOZ_B2G_VERSION,"$MOZ_B2G_VERSION")
AC_DEFINE_UNQUOTED(MOZ_B2G_OS_NAME,"$MOZ_B2G_OS_NAME")
AC_SUBST(MOZ_APP_NAME)
AC_SUBST(MOZ_APP_REMOTINGNAME)
AC_SUBST(MOZ_APP_DISPLAYNAME)
AC_SUBST(MOZ_APP_BASENAME)
AC_SUBST(MOZ_APP_VENDOR)
@ -9004,6 +9011,10 @@ if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK" ; then
AC_DEFINE_UNQUOTED(ATK_REV_VERSION, $ATK_REV_VERSION)
fi
if test "$MOZ_UPDATE_CHANNEL" = "aurora"; then
AC_DEFINE(MOZ_DEV_EDITION)
fi
if test "$MOZ_DEBUG"; then
A11Y_LOG=1
fi
@ -9308,6 +9319,7 @@ export MOZ_NATIVE_ZLIB
export MOZ_ZLIB_CFLAGS
export MOZ_ZLIB_LIBS
export MOZ_APP_NAME
export MOZ_APP_REMOTINGNAME
export DONT_POPULATE_VIRTUALENV=1
export PYTHON
export MOZILLA_CENTRAL_PATH=$_topsrcdir

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

@ -28,7 +28,7 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
explicit nsIScriptElement(mozilla::dom::FromParser aFromParser)
: mLineNumber(0),
: mLineNumber(1),
mAlreadyStarted(false),
mMalformed(false),
mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||

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

@ -557,6 +557,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
[test_bug927196.html]
[test_bug945152.html]
run-if = os == 'linux'
[test_bug982153.html]
[test_bug1008126.html]
run-if = os == 'linux'
[test_bug1057176.html]
@ -588,6 +589,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
[test_htmlcopyencoder.html]
[test_htmlcopyencoder.xhtml]
[test_ipc_messagemanager_blob.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_meta_viewport0.html]
[test_meta_viewport1.html]
[test_meta_viewport2.html]

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

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=982153
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 982153</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script>
var sc = document.createElement("script");
var error = null;
sc.textContent = "try {\n reference_error; } catch(e) { error = e; }";
document.documentElement.appendChild(sc);
is(error.lineNumber, 2, "Error line number must be correct");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982153">Mozilla Bug 982153</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -58,6 +58,7 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure; bug 926546
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_input_sanitization.html]
[test_input_textarea_set_value_no_scroll.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_input_typing_sanitization.html]
skip-if = buildapp == 'mulet'
[test_input_untrusted_key_events.html]

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

@ -306,20 +306,27 @@ skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
[test_aspectratio_mp4.html]
[test_audio1.html]
[test_audio2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_audioDocumentTitle.html]
skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
[test_autoplay.html]
[test_autoplay_contentEditable.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_buffered.html]
[test_bug448534.html]
skip-if = buildapp == 'mulet' || os == 'win' # bug 894922
skip-if = buildapp == 'mulet' || os == 'win' || (toolkit == 'android' && processor == 'x86') # bug 894922 #x86 only bug 914439
[test_bug463162.xhtml]
[test_bug465498.html]
skip-if = (toolkit == 'android' && processor == 'x86')
[test_bug493187.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug495145.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug495300.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug654550.html]
[test_bug686942.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug726904.html]
[test_bug874897.html]
[test_bug883173.html]
@ -330,12 +337,13 @@ skip-if = buildapp == 'mulet' || os == 'win' # bug 894922
[test_bug1018933.html]
[test_can_play_type.html]
[test_can_play_type_mpeg.html]
skip-if = buildapp == 'b2g' # bug 1021675
skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') # bug 1021675 #x86 only bug 914439
[test_can_play_type_no_ogg.html]
[test_can_play_type_ogg.html]
[test_chaining.html]
skip-if = toolkit == 'gonk' && debug
[test_clone_media_element.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_closing_connections.html]
[test_constants.html]
[test_contentDuration1.html]
@ -358,6 +366,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1
skip-if = toolkit == 'android' # bug 608634
[test_error_on_404.html]
[test_fastSeek.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_fastSeek-forwards.html]
[test_imagecapture.html]
[test_info_leak.html]
@ -365,12 +374,18 @@ skip-if = toolkit == 'android' # bug 608634
[test_invalid_reject_play.html]
[test_invalid_seek.html]
[test_load.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_candidates.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_same_resource.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_source.html]
[test_loop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_media_selection.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_media_sniffer.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_mediarecorder_avoid_recursion.html]
[test_mediarecorder_creation.html]
[test_mediarecorder_creation_fail.html]
@ -408,18 +423,25 @@ skip-if = true # bug 567954 and intermittent leaks
[test_mozHasAudio.html]
[test_networkState.html]
[test_new_audio.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_no_load_event.html]
[test_paused.html]
[test_paused_after_ended.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_events.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_events_2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_twice.html]
# Seamonkey: Bug 598252, B2G: Bug 982100, Android: Bug 758476, bug 981086
skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
[test_playback.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_playback_errors.html]
[test_playback_rate.html]
skip-if = (toolkit == 'android' && processor == 'x86') #bug 845162
[test_playback_rate_playpause.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_played.html]
skip-if = true # bug 1021794
[test_preload_actions.html]
@ -427,15 +449,20 @@ skip-if = true # bug 1021794
[test_preload_suspend.html]
skip-if = true # bug 493692
[test_progress.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_reactivate.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_readyState.html]
[test_referer.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_replay_metadata.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_reset_events_async.html]
[test_reset_src.html]
[test_resume.html]
skip-if = true # bug 1021673
[test_seek_out_of_range.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_seek-1.html]
[test_seek-2.html]
[test_seek-3.html]
@ -450,6 +477,7 @@ skip-if = true # bug 1021673
[test_seek-12.html]
[test_seek-13.html]
[test_seekable1.html]
skip-if = (toolkit == 'android' && processor == 'x86') #timeout x86 only bug 914439
[test_seekable2.html]
[test_seekable3.html]
[test_seekLies.html]
@ -458,9 +486,12 @@ skip-if = true # bug 1021673
[test_source_null.html]
[test_source_write.html]
[test_standalone.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_streams_autoplay.html]
[test_streams_element_capture.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_streams_element_capture_createObjectURL.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_streams_element_capture_playback.html]
[test_streams_element_capture_reset.html]
[test_streams_gc.html]
@ -472,10 +503,13 @@ skip-if = buildapp == 'b2g' # bug 1021682
[test_texttracklist.html]
[test_texttrackregion.html]
[test_timeupdate_small_files.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_trackelementevent.html]
[test_trackevent.html]
[test_unseekable.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_video_to_canvas.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_video_in_audio_element.html]
[test_videoDocumentTitle.html]
[test_VideoPlaybackQuality.html]

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

@ -35,6 +35,7 @@ support-files =
[test_audioBufferSourceNodeLoopStartEnd.html]
[test_audioBufferSourceNodeLoopStartEndSame.html]
[test_audioBufferSourceNodeNeutered.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_audioBufferSourceNodeNoStart.html]
[test_audioBufferSourceNodeNullBuffer.html]
[test_audioBufferSourceNodeOffset.html]

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

@ -230,6 +230,10 @@ public:
/* This call reserves but does not start the device. */
virtual nsresult Allocate(const VideoTrackConstraintsN &aConstraints,
const MediaEnginePrefs &aPrefs) = 0;
virtual bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) = 0;
protected:
explicit MediaEngineVideoSource(MediaEngineState aState)
: MediaEngineSource(aState) {}

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

@ -6,6 +6,7 @@
namespace mozilla {
using namespace mozilla::gfx;
using dom::ConstrainLongRange;
using dom::ConstrainDoubleRange;
using dom::MediaTrackConstraintSet;
@ -47,6 +48,26 @@ MediaEngineCameraVideoSource::Intersect(ConstrainLongRange& aA, const ConstrainL
return true;
}
// guts for appending data to the MSG track
bool MediaEngineCameraVideoSource::AppendToTrack(SourceMediaStream* aSource,
layers::Image* aImage,
TrackID aID,
TrackTicks delta)
{
MOZ_ASSERT(aSource);
VideoSegment segment;
nsRefPtr<layers::Image> image = aImage;
IntSize size(image ? mWidth : 0, image ? mHeight : 0);
segment.AppendFrame(image.forget(), delta, size);
// This is safe from any thread, and is safe if the track is Finished
// or Destroyed.
// This can fail if either a) we haven't added the track yet, or b)
// we've removed or finished the track.
return aSource->AppendToTrack(aID, &(segment));
}
// A special version of the algorithm for cameras that don't list capabilities.
void
MediaEngineCameraVideoSource::GuessCapability(

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

@ -28,6 +28,7 @@ public:
, mInitDone(false)
, mHasDirectListeners(false)
, mCaptureIndex(aIndex)
, mTrackID(0)
, mFps(-1)
{}
@ -60,6 +61,12 @@ public:
protected:
~MediaEngineCameraVideoSource() {}
// guts for appending data to the MSG track
virtual bool AppendToTrack(SourceMediaStream* aSource,
layers::Image* aImage,
TrackID aID,
TrackTicks delta);
static bool IsWithin(int32_t n, const dom::ConstrainLongRange& aRange);
static bool IsWithin(double n, const dom::ConstrainDoubleRange& aRange);
static int32_t Clamp(int32_t n, const dom::ConstrainLongRange& aRange);
@ -87,6 +94,7 @@ protected:
bool mInitDone;
bool mHasDirectListeners;
int mCaptureIndex;
TrackID mTrackID;
int mFps; // Track rate (30 fps by default)
webrtc::CaptureCapability mCapability; // Doesn't work on OS X.

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

@ -55,6 +55,11 @@ public:
TrackID aId,
StreamTime aDesiredTime,
TrackTicks &aLastEndTime);
virtual bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
{
return true;
}
virtual bool IsFake() {
return true;

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

@ -154,6 +154,7 @@ MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
if (mState == kStarted) {
return NS_OK;
}
mTrackID = aID;
mImageContainer = layers::LayerManager::CreateImageContainer();
NS_DispatchToMainThread(WrapRunnable(nsRefPtr<MediaEngineGonkVideoSource>(this),
@ -621,6 +622,21 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
// implicitly releases last image
mImage = image.forget();
// Push the frame into the MSG with a minimal duration. This will likely
// mean we'll still get NotifyPull calls which will then return the same
// frame again with a longer duration. However, this means we won't
// fail to get the frame in and drop frames.
// XXX The timestamp for the frame should be base on the Capture time,
// not the MSG time, and MSG should never, ever block on a (realtime)
// video frame (or even really for streaming - audio yes, video probably no).
uint32_t len = mSources.Length();
for (uint32_t i = 0; i < len; i++) {
if (mSources[i]) {
AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
}
}
}
bool

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

@ -64,6 +64,11 @@ public:
TrackID aId,
StreamTime aDesiredTime,
TrackTicks& aLastEndTime) MOZ_OVERRIDE;
virtual bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
{
return true;
}
void OnHardwareStateChange(HardwareState aState);
void GetRotation();

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

@ -32,6 +32,11 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
virtual const MediaSourceType GetMediaSource() {
return MediaSourceType::Browser;
}
virtual bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
{
return true;
}
virtual nsresult TakePhoto(PhotoCallback* aCallback)
{

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

@ -110,6 +110,9 @@ public:
void Refresh(int aIndex);
bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
protected:
~MediaEngineWebRTCVideoSource() { Shutdown(); }
@ -128,8 +131,8 @@ private:
int mMinFps; // Min rate we want to accept
MediaSourceType mMediaSource; // source of media (camera | application | screen)
static bool SatisfyConstraintSet(const dom::MediaTrackConstraintSet& aConstraints,
const webrtc::CaptureCapability& aCandidate);
static bool SatisfiesConstraintSet(const dom::MediaTrackConstraintSet& aConstraints,
const webrtc::CaptureCapability& aCandidate);
void ChooseCapability(const VideoTrackConstraintsN& aConstraints,
const MediaEnginePrefs& aPrefs);
};

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

@ -39,8 +39,10 @@ namespace mozilla {
#ifdef PR_LOGGING
extern PRLogModuleInfo* GetMediaManagerLog();
#define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
#define LOG_FRAMES(msg) PR_LOG(GetMediaManagerLog(), 6, msg)
#else
#define LOG(msg)
#define LOG_FRAMES(msg)
#endif
/**
@ -401,7 +403,7 @@ MediaEngineWebRTCAudioSource::NotifyPull(MediaStreamGraph* aGraph,
#ifdef DEBUG
TrackTicks target = aSource->TimeToTicksRoundUp(SAMPLE_FREQUENCY, aDesiredTime);
TrackTicks delta = target - aLastEndTime;
LOG(("Audio: NotifyPull: aDesiredTime %ld, target %ld, delta %ld",(int64_t) aDesiredTime, (int64_t) target, (int64_t) delta));
LOG_FRAMES(("Audio: NotifyPull: aDesiredTime %ld, target %ld, delta %ld",(int64_t) aDesiredTime, (int64_t) target, (int64_t) delta));
aLastEndTime = target;
#endif
}

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

@ -98,6 +98,22 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
// implicitly releases last image
mImage = image.forget();
// Push the frame into the MSG with a minimal duration. This will likely
// mean we'll still get NotifyPull calls which will then return the same
// frame again with a longer duration. However, this means we won't
// fail to get the frame in and drop frames.
// XXX The timestamp for the frame should be based on the Capture time,
// not the MSG time, and MSG should never, ever block on a (realtime)
// video frame (or even really for streaming - audio yes, video probably no).
// Note that MediaPipeline currently ignores the timestamps from MSG
uint32_t len = mSources.Length();
for (uint32_t i = 0; i < len; i++) {
if (mSources[i]) {
AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
}
}
return 0;
}
@ -106,7 +122,7 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
// this means that no *real* frame can be inserted during this period.
void
MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
SourceMediaStream *aSource,
SourceMediaStream* aSource,
TrackID aID,
StreamTime aDesiredTime,
TrackTicks &aLastEndTime)
@ -118,12 +134,10 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
// So mState could be kReleased here. We really don't care about the state,
// though.
// Note: we're not giving up mImage here
nsRefPtr<layers::Image> image = mImage;
TrackTicks target = aSource->TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
TrackTicks delta = target - aLastEndTime;
LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime,
(int64_t) target, (int64_t) delta, image ? "" : "<null>"));
(int64_t) target, (int64_t) delta, mImage ? "" : "<null>"));
// Bug 846188 We may want to limit incoming frames to the requested frame rate
// mFps - if you want 30FPS, and the camera gives you 60FPS, this could
@ -137,19 +151,16 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
// Doing so means a negative delta and thus messes up handling of the graph
if (delta > 0) {
// nullptr images are allowed
IntSize size(image ? mWidth : 0, image ? mHeight : 0);
segment.AppendFrame(image.forget(), delta, size);
// This can fail if either a) we haven't added the track yet, or b)
// we've removed or finished the track.
if (aSource->AppendToTrack(aID, &(segment))) {
if (AppendToTrack(aSource, mImage, aID, delta)) {
aLastEndTime = target;
}
}
}
/*static*/
bool MediaEngineWebRTCVideoSource::SatisfyConstraintSet(const MediaTrackConstraintSet &aConstraints,
const webrtc::CaptureCapability& aCandidate) {
bool
MediaEngineWebRTCVideoSource::SatisfiesConstraintSet(const MediaTrackConstraintSet &aConstraints,
const webrtc::CaptureCapability& aCandidate) {
if (!MediaEngineCameraVideoSource::IsWithin(aCandidate.width, aConstraints.mWidth) ||
!MediaEngineCameraVideoSource::IsWithin(aCandidate.height, aConstraints.mHeight)) {
return false;
@ -160,6 +171,41 @@ bool MediaEngineWebRTCVideoSource::SatisfyConstraintSet(const MediaTrackConstrai
return true;
}
typedef nsTArray<uint8_t> CapabilitySet;
// SatisfiesConstraintSets (plural) answers for the capture device as a whole
// whether it can satisfy an accumulated number of capabilitySets.
bool
MediaEngineWebRTCVideoSource::SatisfiesConstraintSets(
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
{
NS_ConvertUTF16toUTF8 uniqueId(mUniqueId);
int num = mViECapture->NumberOfCapabilities(uniqueId.get(), kMaxUniqueIdLength);
if (num <= 0) {
return true;
}
CapabilitySet candidateSet;
for (int i = 0; i < num; i++) {
candidateSet.AppendElement(i);
}
for (size_t j = 0; j < aConstraintSets.Length(); j++) {
for (size_t i = 0; i < candidateSet.Length(); ) {
webrtc::CaptureCapability cap;
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
candidateSet[i], cap);
if (!SatisfiesConstraintSet(*aConstraintSets[j], cap)) {
candidateSet.RemoveElementAt(i);
} else {
++i;
}
}
}
return !!candidateSet.Length();
}
void
MediaEngineWebRTCVideoSource::ChooseCapability(
const VideoTrackConstraintsN &aConstraints,
@ -177,9 +223,7 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
LOG(("ChooseCapability: prefs: %dx%d @%d-%dfps",
aPrefs.mWidth, aPrefs.mHeight, aPrefs.mFPS, aPrefs.mMinFPS));
typedef nsTArray<uint8_t> SourceSet;
SourceSet candidateSet;
CapabilitySet candidateSet;
for (int i = 0; i < num; i++) {
candidateSet.AppendElement(i);
}
@ -190,14 +234,14 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
webrtc::CaptureCapability cap;
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
candidateSet[i], cap);
if (!SatisfyConstraintSet(aConstraints.mRequired, cap)) {
if (!SatisfiesConstraintSet(aConstraints.mRequired, cap)) {
candidateSet.RemoveElementAt(i);
} else {
++i;
}
}
SourceSet tailSet;
CapabilitySet tailSet;
// Then apply advanced (formerly known as optional) constraints.
@ -205,12 +249,12 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
auto &array = aConstraints.mAdvanced.Value();
for (uint32_t i = 0; i < array.Length(); i++) {
SourceSet rejects;
CapabilitySet rejects;
for (uint32_t j = 0; j < candidateSet.Length();) {
webrtc::CaptureCapability cap;
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
candidateSet[j], cap);
if (!SatisfyConstraintSet(array[i], cap)) {
if (!SatisfiesConstraintSet(array[i], cap)) {
rejects.AppendElement(candidateSet[j]);
candidateSet.RemoveElementAt(j);
} else {
@ -363,6 +407,8 @@ MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
mImageContainer = layers::LayerManager::CreateImageContainer();
mState = kStarted;
mTrackID = aID;
error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
if (error == -1) {
return NS_ERROR_FAILURE;

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

@ -38,7 +38,7 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
[test_child.html]
[test_grandchild.html]
[test_not-opener.html]
skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') #x86 only
[test_opener.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_popup-navigates-children.html]

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

@ -31,7 +31,9 @@ support-files =
[test_marketplace_pkg_install.html]
skip-if = buildapp == "b2g" || toolkit == "android" # see bug 989806
[test_packaged_app_install.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_packaged_app_update.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_receipt_operations.html]
[test_signed_pkg_install.html]
[test_uninstall_errors.html]

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

@ -153,6 +153,7 @@ disabled = bug 1022281
[test_browserElement_inproc_FrameWrongURI.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_inproc_GetScreenshot.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_browserElement_inproc_GetScreenshotDppx.html]
[test_browserElement_inproc_Iconchange.html]
[test_browserElement_inproc_KeyEvents.html]
@ -200,6 +201,7 @@ skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_inproc_XFrameOptionsDeny.html]
[test_browserElement_inproc_XFrameOptionsSameOrigin.html]
[test_browserElement_oop_NextPaint.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
# Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100
[test_browserElement_inproc_Reload.html]
disabled = bug 774100

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

@ -25,27 +25,49 @@ support-files =
[test_2d.clearRect.image.offscreen.html]
[test_2d.clip.winding.html]
[test_2d.composite.canvas.color-burn.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.color-dodge.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.color.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.darken.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.destination-atop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.difference.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.exclusion.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.hard-light.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.hue.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.lighten.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.luminosity.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.multiply.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.overlay.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.saturation.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.screen.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.soft-light.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.source-out.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.destination-atop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.source-out.html]
# xor and lighter aren't well handled by cairo; they mostly work, but we don't want
# to test that
@ -112,8 +134,11 @@ skip-if = toolkit != 'cocoa'
[test_2d.composite.uncovered.fill.destination-atop.html]
skip-if = toolkit != 'cocoa'
[test_2d.composite.uncovered.image.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.uncovered.image.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.uncovered.image.source-out.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
# Tests that fail on non-Mac (bug 407107)
[test_2d.composite.uncovered.pattern.source-in.html]
skip-if = toolkit != 'cocoa'

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

@ -35,12 +35,15 @@ support-files =
[test_app_install.html]
[test_readonly.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_basic.html]
[test_basic_worker.html]
[test_changes.html]
[test_arrays.html]
[test_oop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_sync.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_sync_worker.html]
[test_bug924104.html]
[test_certifiedApp.html]

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

@ -39,6 +39,40 @@ namespace mozilla {
#ifdef MOZ_CHILD_PERMISSIONS
static bool
CheckAppTypeHelper(mozIApplication* aApp,
AssertAppProcessType aType,
const char* aCapability,
bool aIsBrowserElement)
{
bool aValid = false;
// isBrowser frames inherit their app descriptor to identify their
// data storage, but they don't inherit the capability associated
// with that descriptor.
if (aApp && (aType == ASSERT_APP_HAS_PERMISSION || !aIsBrowserElement)) {
switch (aType) {
case ASSERT_APP_HAS_PERMISSION:
case ASSERT_APP_PROCESS_PERMISSION:
if (!NS_SUCCEEDED(aApp->HasPermission(aCapability, &aValid))) {
aValid = false;
}
break;
case ASSERT_APP_PROCESS_MANIFEST_URL: {
nsAutoString manifestURL;
if (NS_SUCCEEDED(aApp->GetManifestURL(manifestURL)) &&
manifestURL.EqualsASCII(aCapability)) {
aValid = true;
}
break;
}
default:
break;
}
}
return aValid;
}
bool
AssertAppProcess(PBrowserParent* aActor,
AssertAppProcessType aType,
@ -51,32 +85,24 @@ AssertAppProcess(PBrowserParent* aActor,
TabParent* tab = static_cast<TabParent*>(aActor);
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
bool aValid = false;
// isBrowser frames inherit their app descriptor to identify their
// data storage, but they don't inherit the capability associated
// with that descriptor.
if (app && (aType == ASSERT_APP_HAS_PERMISSION || !tab->IsBrowserElement())) {
switch (aType) {
case ASSERT_APP_HAS_PERMISSION:
case ASSERT_APP_PROCESS_PERMISSION:
if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) {
aValid = false;
}
break;
case ASSERT_APP_PROCESS_MANIFEST_URL: {
nsAutoString manifestURL;
if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) &&
manifestURL.EqualsASCII(aCapability)) {
aValid = true;
}
break;
}
default:
break;
return CheckAppTypeHelper(app, aType, aCapability, tab->IsBrowserElement());
}
static bool
CheckAppStatusHelper(mozIApplication* aApp,
unsigned short aStatus)
{
bool valid = false;
if (aApp) {
unsigned short appStatus = 0;
if (NS_SUCCEEDED(aApp->GetAppStatus(&appStatus))) {
valid = appStatus == aStatus;
}
}
return aValid;
return valid;
}
bool
@ -91,16 +117,26 @@ AssertAppStatus(PBrowserParent* aActor,
TabParent* tab = static_cast<TabParent*>(aActor);
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
bool valid = false;
return CheckAppStatusHelper(app, aStatus);
}
if (app) {
unsigned short appStatus = 0;
if (NS_SUCCEEDED(app->GetAppStatus(&appStatus))) {
valid = appStatus == aStatus;
}
}
bool
AssertAppProcess(TabContext& aContext,
AssertAppProcessType aType,
const char* aCapability)
{
return valid;
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
return CheckAppTypeHelper(app, aType, aCapability, aContext.IsBrowserElement());
}
bool
AssertAppStatus(TabContext& aContext,
unsigned short aStatus)
{
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
return CheckAppStatusHelper(app, aStatus);
}
bool
@ -108,10 +144,10 @@ AssertAppProcess(PContentParent* aActor,
AssertAppProcessType aType,
const char* aCapability)
{
const InfallibleTArray<PBrowserParent*>& browsers =
aActor->ManagedPBrowserParent();
for (uint32_t i = 0; i < browsers.Length(); ++i) {
if (AssertAppProcess(browsers[i], aType, aCapability)) {
nsTArray<TabContext> contextArray =
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
if (AssertAppProcess(contextArray[i], aType, aCapability)) {
return true;
}
}
@ -130,10 +166,10 @@ bool
AssertAppStatus(PContentParent* aActor,
unsigned short aStatus)
{
const InfallibleTArray<PBrowserParent*>& browsers =
aActor->ManagedPBrowserParent();
for (uint32_t i = 0; i < browsers.Length(); ++i) {
if (AssertAppStatus(browsers[i], aStatus)) {
nsTArray<TabContext> contextArray =
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
if (AssertAppStatus(contextArray[i], aStatus)) {
return true;
}
}
@ -170,14 +206,13 @@ AssertAppPrincipal(PContentParent* aActor,
bool inBrowserElement = aPrincipal->GetIsInBrowserElement();
// Check if the permission's appId matches a child we manage.
const InfallibleTArray<PBrowserParent*>& browsers =
aActor->ManagedPBrowserParent();
for (uint32_t i = 0; i < browsers.Length(); ++i) {
TabParent* tab = static_cast<TabParent*>(browsers[i]);
if (tab->OwnOrContainingAppId() == principalAppId) {
nsTArray<TabContext> contextArray =
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
if (contextArray[i].OwnOrContainingAppId() == principalAppId) {
// If the child only runs inBrowserElement content and the principal claims
// it's not in a browser element, it's lying.
if (!tab->IsBrowserElement() || inBrowserElement) {
if (!contextArray[i].IsBrowserElement() || inBrowserElement) {
return true;
}
break;
@ -287,6 +322,21 @@ AssertAppStatus(mozilla::dom::PBrowserParent* aActor,
return true;
}
bool
AssertAppProcess(const mozilla::dom::TabContext& aContext,
AssertAppProcessType aType,
const char* aCapability)
{
return true;
}
bool
AssertAppStatus(const mozilla::dom::TabContext& aContext,
unsigned short aStatus)
{
return true;
}
bool
AssertAppProcess(mozilla::dom::PContentParent* aActor,

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

@ -15,6 +15,7 @@ class nsIPrincipal;
namespace mozilla {
namespace dom {
class TabContext;
class PBrowserParent;
class PContentParent;
}
@ -47,6 +48,24 @@ bool
AssertAppStatus(mozilla::dom::PBrowserParent* aActor,
unsigned short aStatus);
/**
* Return true if the specified browser has the specified capability.
* If this returns false, the browser didn't have the capability and
* will be killed.
*/
bool
AssertAppProcess(const mozilla::dom::TabContext& aContext,
AssertAppProcessType aType,
const char* aCapability);
/**
* Return true if the specified app has the specified status.
* If this returns false, the browser will be killed.
*/
bool
AssertAppStatus(const mozilla::dom::TabContext& aContext,
unsigned short aStatus);
/**
* Return true if any of the PBrowsers loaded in this content process
* has the specified capability. If this returns false, the process

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

@ -81,16 +81,18 @@ ContentBridgeChild::SendPBlobConstructor(PBlobChild* actor,
bool
ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentBridgeChild::SendPBrowserConstructor(aActor,
aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}
@ -121,15 +123,17 @@ ContentBridgeChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
}
PBrowserChild*
ContentBridgeChild::AllocPBrowserChild(const IPCTabContext &aContext,
ContentBridgeChild::AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentChild::AllocPBrowserChild(aContext,
return nsIContentChild::AllocPBrowserChild(aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}
@ -142,16 +146,18 @@ ContentBridgeChild::DeallocPBrowserChild(PBrowserChild* aChild)
bool
ContentBridgeChild::RecvPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return ContentChild::GetSingleton()->RecvPBrowserConstructor(aActor,
aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}

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

@ -39,25 +39,28 @@ public:
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
protected:
virtual ~ContentBridgeChild();
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool DeallocPBrowserChild(PBrowserChild*) MOZ_OVERRIDE;
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;

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

@ -87,16 +87,18 @@ ContentBridgeParent::SendPBlobConstructor(PBlobParent* actor,
PBrowserParent*
ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentBridgeParent::SendPBrowserConstructor(aActor,
aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}
@ -126,15 +128,17 @@ ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
}
PBrowserParent*
ContentBridgeParent::AllocPBrowserParent(const IPCTabContext &aContext,
ContentBridgeParent::AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentParent::AllocPBrowserParent(aContext,
return nsIContentParent::AllocPBrowserParent(aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}

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

@ -9,6 +9,7 @@
#include "mozilla/dom/PContentBridgeParent.h"
#include "mozilla/dom/nsIContentParent.h"
#include "mozilla/dom/ipc/IdType.h"
namespace mozilla {
namespace dom {
@ -33,15 +34,16 @@ public:
virtual PBrowserParent*
SendPBrowserConstructor(PBrowserParent* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
virtual uint64_t ChildID() MOZ_OVERRIDE
virtual ContentParentId ChildID() MOZ_OVERRIDE
{
return mChildID;
}
@ -57,7 +59,7 @@ public:
protected:
virtual ~ContentBridgeParent();
void SetChildID(uint64_t aId)
void SetChildID(ContentParentId aId)
{
mChildID = aId;
}
@ -86,9 +88,10 @@ protected:
DeallocPJavaScriptParent(jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
virtual PBrowserParent*
AllocPBrowserParent(const IPCTabContext &aContext,
AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool DeallocPBrowserParent(PBrowserParent*) MOZ_OVERRIDE;
@ -103,7 +106,7 @@ protected:
protected: // members
nsRefPtr<ContentBridgeParent> mSelfRef;
Transport* mTransport; // owned
uint64_t mChildID;
ContentParentId mChildID;
bool mIsForApp;
bool mIsForBrowser;

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

@ -1109,40 +1109,45 @@ ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *aChild)
}
PBrowserChild*
ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
ContentChild::AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentChild::AllocPBrowserChild(aContext,
return nsIContentChild::AllocPBrowserChild(aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}
bool
ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentChild::SendPBrowserConstructor(aActor,
aTabId,
aContext,
aChromeFlags,
aID,
aCpID,
aIsForApp,
aIsForBrowser);
}
bool
ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
@ -1166,7 +1171,7 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
// Redo InitProcessAttributes() when the app or browser is really
// launching so the attributes will be correct.
mID = aID;
mID = aCpID;
mIsForApp = aIsForApp;
mIsForBrowser = aIsForBrowser;
InitProcessAttributes();

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

@ -131,9 +131,10 @@ public:
AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
MOZ_OVERRIDE;
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser);
virtual bool DeallocPBrowserChild(PBrowserChild*);
@ -354,7 +355,7 @@ public:
// cache the value
nsString &GetIndexedDBPath();
uint64_t GetID() { return mID; }
ContentParentId GetID() { return mID; }
bool IsForApp() { return mIsForApp; }
bool IsForBrowser() { return mIsForBrowser; }
@ -370,16 +371,18 @@ public:
DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*) MOZ_OVERRIDE;
virtual bool SendPBrowserConstructor(PBrowserChild* actor,
const TabId& aTabId,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual PDocAccessibleChild* AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&) MOZ_OVERRIDE;
@ -412,7 +415,7 @@ private:
* We expect our content parent to set this ID immediately after opening a
* channel to us.
*/
uint64_t mID;
ContentParentId mID;
AppInfo mAppInfo;

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

@ -131,6 +131,7 @@
#include "gfxPrefs.h"
#include "prio.h"
#include "private/pprio.h"
#include "ContentProcessManager.h"
#if defined(ANDROID) || defined(LINUX)
#include "nsSystemInfo.h"
@ -845,17 +846,14 @@ ContentParent::PreallocatedProcessReady()
#endif
}
typedef std::map<ContentParent*, std::set<ContentParent*> > GrandchildMap;
static GrandchildMap sGrandchildProcessMap;
std::map<uint64_t, ContentParent*> sContentParentMap;
bool
ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
uint64_t* aId,
const TabId& aOpenerTabId,
ContentParentId* aCpId,
bool* aIsForApp,
bool* aIsForBrowser)
bool* aIsForBrowser,
TabId* aTabId)
{
#if 0
if (!CanOpenBrowser(aContext)) {
@ -884,40 +882,67 @@ ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
}
if (!cp) {
*aId = 0;
*aCpId = 0;
*aIsForApp = false;
*aIsForBrowser = false;
return true;
}
*aId = cp->ChildID();
*aCpId = cp->ChildID();
*aIsForApp = cp->IsForApp();
*aIsForBrowser = cp->IsForBrowser();
sContentParentMap[*aId] = cp;
auto iter = sGrandchildProcessMap.find(this);
if (iter == sGrandchildProcessMap.end()) {
std::set<ContentParent*> children;
children.insert(cp);
sGrandchildProcessMap[this] = children;
} else {
iter->second.insert(cp);
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
cpm->AddContentProcess(cp, this->ChildID());
if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID())) {
// Pre-allocate a TabId here to save one time IPC call at app startup.
*aTabId = AllocateTabId(aOpenerTabId,
aContext,
cp->ChildID());
return (*aTabId != 0);
}
return true;
return false;
}
bool
ContentParent::AnswerBridgeToChildProcess(const uint64_t& id)
ContentParent::AnswerBridgeToChildProcess(const ContentParentId& aCpId)
{
ContentParent* cp = sContentParentMap[id];
auto iter = sGrandchildProcessMap.find(this);
if (iter != sGrandchildProcessMap.end() &&
iter->second.find(cp) != iter->second.end()) {
return PContentBridge::Bridge(this, cp);
} else {
// You can't bridge to a process you didn't open!
KillHard();
return false;
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
ContentParent* cp = cpm->GetContentProcessById(aCpId);
if (cp) {
ContentParentId parentId;
if (cpm->GetParentProcessId(cp->ChildID(), &parentId) &&
parentId == this->ChildID()) {
return PContentBridge::Bridge(this, cp);
}
}
// You can't bridge to a process you didn't open!
KillHard();
return false;
}
static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement)
{
// Propagate the private-browsing status of the element's parent
// docshell to the remote docshell, via the chrome flags.
nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
MOZ_ASSERT(frameElement);
nsPIDOMWindow* win = frameElement->OwnerDoc()->GetWindow();
if (!win) {
NS_WARNING("Remote frame has no window");
return nullptr;
}
nsIDocShell* docShell = win->GetDocShell();
if (!docShell) {
NS_WARNING("Remote frame has no docshell");
return nullptr;
}
return docShell;
}
/*static*/ TabParent*
@ -931,40 +956,38 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
TabId tabId;
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
TabId openerTabId;
if (docShell) {
openerTabId = TabParent::GetTabIdFrom(docShell);
}
if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
nsRefPtr<TabParent> tp;
nsRefPtr<nsIContentParent> constructorSender;
if (isInContentProcess) {
MOZ_ASSERT(aContext.IsBrowserElement());
constructorSender =
CreateContentBridgeParent(aContext, initialPriority);
constructorSender = CreateContentBridgeParent(aContext,
initialPriority,
openerTabId,
&tabId);
} else {
if (aOpenerContentParent) {
constructorSender = aOpenerContentParent;
} else {
constructorSender =
GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
initialPriority);
}
if (aOpenerContentParent) {
constructorSender = aOpenerContentParent;
} else {
constructorSender =
GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
initialPriority);
}
tabId = AllocateTabId(openerTabId,
aContext.AsIPCTabContext(),
constructorSender->ChildID());
}
if (constructorSender) {
uint32_t chromeFlags = 0;
// Propagate the private-browsing status of the element's parent
// docshell to the remote docshell, via the chrome flags.
nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
MOZ_ASSERT(frameElement);
nsPIDOMWindow* win = frameElement->OwnerDoc()->GetWindow();
if (!win) {
NS_WARNING("Remote frame has no window");
return nullptr;
}
nsIDocShell* docShell = win->GetDocShell();
if (!docShell) {
NS_WARNING("Remote frame has no docshell");
return nullptr;
}
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (loadContext && loadContext->UsePrivateBrowsing()) {
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
@ -975,13 +998,17 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
}
nsRefPtr<TabParent> tp(new TabParent(constructorSender,
if (tabId == 0) {
return nullptr;
}
nsRefPtr<TabParent> tp(new TabParent(constructorSender, tabId,
aContext, chromeFlags));
tp->SetOwnerElement(aFrameElement);
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
// DeallocPBrowserParent() releases this ref.
tp.forget().take(),
tabId,
aContext.AsIPCTabContext(),
chromeFlags,
constructorSender->ChildID(),
@ -1001,7 +1028,10 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
nsAutoString manifestURL;
if (isInContentProcess) {
parent = CreateContentBridgeParent(aContext, initialPriority);
parent = CreateContentBridgeParent(aContext,
initialPriority,
openerTabId,
&tabId);
}
else {
nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
@ -1049,6 +1079,9 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
// Check if we can re-use the process of the parent app.
p = sAppContentParents->Get(parentAppManifestURL);
tabId = AllocateTabId(openerTabId,
aContext.AsIPCTabContext(),
p->ChildID());
}
}
}
@ -1070,21 +1103,25 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
&tookPreallocated);
MOZ_ASSERT(p);
sAppContentParents->Put(manifestURL, p);
tabId = AllocateTabId(openerTabId,
aContext.AsIPCTabContext(),
p->ChildID());
}
parent = static_cast<nsIContentParent*>(p);
}
if (!parent) {
if (!parent || (tabId == 0)) {
return nullptr;
}
uint32_t chromeFlags = 0;
nsRefPtr<TabParent> tp = new TabParent(parent, aContext, chromeFlags);
nsRefPtr<TabParent> tp = new TabParent(parent, tabId, aContext, chromeFlags);
tp->SetOwnerElement(aFrameElement);
PBrowserParent* browser = parent->SendPBrowserConstructor(
// DeallocPBrowserParent() releases this ref.
nsRefPtr<TabParent>(tp).forget().take(),
tabId,
aContext.AsIPCTabContext(),
chromeFlags,
parent->ChildID(),
@ -1127,27 +1164,33 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
/*static*/ ContentBridgeParent*
ContentParent::CreateContentBridgeParent(const TabContext& aContext,
const hal::ProcessPriority& aPriority)
const hal::ProcessPriority& aPriority,
const TabId& aOpenerTabId,
/*out*/ TabId* aTabId)
{
MOZ_ASSERT(aTabId);
ContentChild* child = ContentChild::GetSingleton();
uint64_t id;
ContentParentId cpId;
bool isForApp;
bool isForBrowser;
if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
aPriority,
&id,
aOpenerTabId,
&cpId,
&isForApp,
&isForBrowser)) {
&isForBrowser,
aTabId)) {
return nullptr;
}
if (id == 0) {
if (cpId == 0) {
return nullptr;
}
if (!child->CallBridgeToChildProcess(id)) {
if (!child->CallBridgeToChildProcess(cpId)) {
return nullptr;
}
ContentBridgeParent* parent = child->GetLastBridge();
parent->SetChildID(id);
parent->SetChildID(cpId);
parent->SetIsForApp(isForApp);
parent->SetIsForBrowser(isForBrowser);
return parent;
@ -1476,13 +1519,6 @@ ContentParent::MarkAsDead()
}
mIsAlive = false;
sGrandchildProcessMap.erase(this);
for (auto iter = sGrandchildProcessMap.begin();
iter != sGrandchildProcessMap.end();
iter++) {
iter->second.erase(this);
}
}
void
@ -1720,17 +1756,17 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
// Destroy any processes created by this ContentParent
auto iter = sGrandchildProcessMap.find(this);
if (iter != sGrandchildProcessMap.end()) {
for(auto child = iter->second.begin();
child != iter->second.end();
child++) {
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(*child, &ContentParent::ShutDownProcess,
/* closeWithError */ false));
}
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
nsTArray<ContentParentId> childIDArray =
cpm->GetAllChildProcessById(this->ChildID());
for(uint32_t i = 0; i < childIDArray.Length(); i++) {
ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(cp, &ContentParent::ShutDownProcess,
/* closeWithError */ false));
}
cpm->RemoveContentProcess(this->ChildID());
}
void
@ -1893,6 +1929,8 @@ ContentParent::ContentParent(mozIApplication* aApp,
InitInternal(aInitialPriority,
true, /* Setup off-main thread compositing */
true /* Send registered chrome */);
ContentProcessManager::GetSingleton()->AddContentProcess(this);
}
#ifdef MOZ_NUWA_PROCESS
@ -1970,6 +2008,8 @@ ContentParent::ContentParent(ContentParent* aTemplate,
InitInternal(priority,
false, /* Setup Off-main thread compositing */
false /* Send registered chrome */);
ContentProcessManager::GetSingleton()->AddContentProcess(this);
}
#endif // MOZ_NUWA_PROCESS
@ -2780,10 +2820,10 @@ ContentParent::AllocPSharedBufferManagerParent(mozilla::ipc::Transport* aTranspo
}
bool
ContentParent::RecvGetProcessAttributes(uint64_t* aId,
ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId,
bool* aIsForApp, bool* aIsForBrowser)
{
*aId = mChildID;
*aCpId = mChildID;
*aIsForApp = IsForApp();
*aIsForBrowser = mIsForBrowser;
@ -2831,15 +2871,17 @@ ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
}
PBrowserParent*
ContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
ContentParent::AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentParent::AllocPBrowserParent(aContext,
return nsIContentParent::AllocPBrowserParent(aTabId,
aContext,
aChromeFlags,
aId,
aCpId,
aIsForApp,
aIsForBrowser);
}
@ -3825,16 +3867,18 @@ ContentParent::RecvSystemMessageHandled()
PBrowserParent*
ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentParent::SendPBrowserConstructor(aActor,
aTabId,
aContext,
aChromeFlags,
aId,
aCpId,
aIsForApp,
aIsForBrowser);
}
@ -4133,6 +4177,66 @@ ContentParent::NotifyUpdatedDictionaries()
}
}
/*static*/ TabId
ContentParent::AllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aCpId)
{
TabId tabId;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
tabId = cpm->AllocateTabId(aOpenerTabId, aContext, aCpId);
}
else {
ContentChild::GetSingleton()->SendAllocateTabId(aOpenerTabId,
aContext,
aCpId,
&tabId);
}
return tabId;
}
/*static*/ void
ContentParent::DeallocateTabId(const TabId& aTabId,
const ContentParentId& aCpId)
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
ContentProcessManager::GetSingleton()->DeallocateTabId(aCpId,
aTabId);
}
else {
ContentChild::GetSingleton()->SendDeallocateTabId(aTabId);
}
}
bool
ContentParent::RecvAllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aCpId,
TabId* aTabId)
{
*aTabId = AllocateTabId(aOpenerTabId, aContext, aCpId);
if (!(*aTabId)) {
return false;
}
return true;
}
bool
ContentParent::RecvDeallocateTabId(const TabId& aTabId)
{
DeallocateTabId(aTabId, this->ChildID());
return true;
}
nsTArray<TabContext>
ContentParent::GetManagedTabContext()
{
return Move(ContentProcessManager::GetSingleton()->
GetTabContextByContentProcess(this->ChildID()));
}
} // namespace dom
} // namespace mozilla

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

@ -143,10 +143,12 @@ public:
virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
uint64_t* aId,
const TabId& aOpenerTabId,
ContentParentId* aCpId,
bool* aIsForApp,
bool* aIsForBrowser) MOZ_OVERRIDE;
virtual bool AnswerBridgeToChildProcess(const uint64_t& id) MOZ_OVERRIDE;
bool* aIsForBrowser,
TabId* aTabId) MOZ_OVERRIDE;
virtual bool AnswerBridgeToChildProcess(const ContentParentId& aCpId) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
@ -179,6 +181,13 @@ public:
TestShellParent* GetTestShellSingleton();
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
static TabId
AllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aCpId);
static void
DeallocateTabId(const TabId& aTabId, const ContentParentId& aCpId);
void ReportChildAlreadyBlocked();
bool RequestRunToCompletion();
@ -217,7 +226,7 @@ public:
*/
void KillHard();
uint64_t ChildID() MOZ_OVERRIDE { return mChildID; }
ContentParentId ChildID() MOZ_OVERRIDE { return mChildID; }
const nsString& AppManifestURL() const { return mAppManifestURL; }
bool IsPreallocated();
@ -282,6 +291,14 @@ public:
PBlobParent* aActor,
const BlobConstructorParams& aParams) MOZ_OVERRIDE;
virtual bool RecvAllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aCpId,
TabId* aTabId) MOZ_OVERRIDE;
virtual bool RecvDeallocateTabId(const TabId& aTabId) MOZ_OVERRIDE;
nsTArray<TabContext> GetManagedTabContext();
protected:
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
@ -310,15 +327,18 @@ private:
static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
static ContentBridgeParent* CreateContentBridgeParent(const TabContext& aContext,
const hal::ProcessPriority& aPriority);
const hal::ProcessPriority& aPriority,
const TabId& aOpenerTabId,
/*out*/ TabId* aTabId);
// Hide the raw constructor methods since we don't want client code
// using them.
virtual PBrowserParent* SendPBrowserConstructor(
PBrowserParent* actor,
const TabId& aTabId,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
using PContentParent::SendPTestShellConstructor;
@ -409,7 +429,7 @@ private:
AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
MOZ_OVERRIDE;
virtual bool RecvGetProcessAttributes(uint64_t* aId,
virtual bool RecvGetProcessAttributes(ContentParentId* aCpId,
bool* aIsForApp,
bool* aIsForBrowser) MOZ_OVERRIDE;
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline,
@ -420,9 +440,10 @@ private:
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
virtual bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) MOZ_OVERRIDE;
virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool DeallocPBrowserParent(PBrowserParent* frame) MOZ_OVERRIDE;
@ -692,7 +713,7 @@ private:
GeckoChildProcessHost* mSubprocess;
ContentParent* mOpener;
uint64_t mChildID;
ContentParentId mChildID;
int32_t mGeolocationWatchID;
nsString mAppManifestURL;

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

@ -0,0 +1,276 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* 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 "ContentProcessManager.h"
#include "ContentParent.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsPrintfCString.h"
// XXX need another bug to move this to a common header.
#ifdef DISABLE_ASSERTS_FOR_FUZZING
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
#else
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
#endif
namespace mozilla {
namespace dom {
static uint64_t gTabId = 0;
/* static */
StaticAutoPtr<ContentProcessManager>
ContentProcessManager::sSingleton;
/* static */ ContentProcessManager*
ContentProcessManager::GetSingleton()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (!sSingleton) {
sSingleton = new ContentProcessManager();
ClearOnShutdown(&sSingleton);
}
return sSingleton;
}
void
ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
const ContentParentId& aParentCpId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aChildCp);
ContentProcessInfo info;
info.mCp = aChildCp;
info.mParentCpId = aParentCpId;
mContentParentMap[aChildCp->ChildID()] = info;
}
void
ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
mContentParentMap.erase(aChildCpId);
for (auto iter = mContentParentMap.begin();
iter != mContentParentMap.end();
++iter) {
if (!iter->second.mChildrenCpId.empty()) {
iter->second.mChildrenCpId.erase(aChildCpId);
}
}
}
bool
ContentProcessManager::AddGrandchildProcess(const ContentParentId& aParentCpId,
const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aParentCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
return false;
}
iter->second.mChildrenCpId.insert(aChildCpId);
return true;
}
bool
ContentProcessManager::GetParentProcessId(const ContentParentId& aChildCpId,
/*out*/ ContentParentId* aParentCpId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return false;
}
*aParentCpId = iter->second.mParentCpId;
return true;
}
ContentParent*
ContentProcessManager::GetContentProcessById(const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return nullptr;
}
return iter->second.mCp;
}
nsTArray<ContentParentId>
ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
{
MOZ_ASSERT(NS_IsMainThread());
nsTArray<ContentParentId> cpIdArray;
auto iter = mContentParentMap.find(aParentCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return Move(cpIdArray);
}
for (auto cpIter = iter->second.mChildrenCpId.begin();
cpIter != iter->second.mChildrenCpId.end();
++cpIter) {
cpIdArray.AppendElement(*cpIter);
}
return Move(cpIdArray);
}
TabId
ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return TabId(0);
}
struct RemoteFrameInfo info;
const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
// If it's a PopupIPCTabContext, it's the case that a TabChild want to
// open a new tab. aOpenerTabId has to be it's parent frame's opener id.
if (appBrowser.type() == IPCTabAppBrowserContext::TPopupIPCTabContext) {
auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
return TabId(0);
}
info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
MOZ_ASSERT(ipcContext.opener().type() == PBrowserOrId::TTabId);
remoteFrameIter = iter->second.mRemoteFrames.find(ipcContext.opener().get_TabId());
if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
ASSERT_UNLESS_FUZZING("Failed to find tab id.");
return TabId(0);
}
info.mContext = remoteFrameIter->second.mContext;
}
else {
MaybeInvalidTabContext tc(aContext);
if (!tc.IsValid()) {
NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
"the child process. (%s)",
tc.GetInvalidReason()).get());
return TabId(0);
}
info.mOpenerTabId = aOpenerTabId;
info.mContext = tc.GetTabContext();
}
mUniqueId = ++gTabId;
iter->second.mRemoteFrames[mUniqueId] = info;
return mUniqueId;
}
void
ContentProcessManager::DeallocateTabId(const ContentParentId& aChildCpId,
const TabId& aChildTabId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return;
}
auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
iter->second.mRemoteFrames.erase(aChildTabId);
}
}
nsTArray<uint64_t>
ContentProcessManager::GetAppIdsByContentProcess(const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
nsTArray<uint64_t> appIdArray;
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return Move(appIdArray);
}
for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
remoteFrameIter != iter->second.mRemoteFrames.end();
++remoteFrameIter) {
appIdArray.AppendElement(remoteFrameIter->second.mContext.OwnOrContainingAppId());
}
return Move(appIdArray);
}
nsTArray<TabContext>
ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
{
MOZ_ASSERT(NS_IsMainThread());
nsTArray<TabContext> tabContextArray;
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return Move(tabContextArray);
}
for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
remoteFrameIter != iter->second.mRemoteFrames.end();
++remoteFrameIter) {
tabContextArray.AppendElement(remoteFrameIter->second.mContext);
}
return Move(tabContextArray);
}
bool
ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
const TabId& aChildTabId,
/*out*/TabId* aOpenerTabId)
{
MOZ_ASSERT(NS_IsMainThread());
auto iter = mContentParentMap.find(aChildCpId);
if (NS_WARN_IF(iter == mContentParentMap.end())) {
ASSERT_UNLESS_FUZZING();
return false;
}
auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
ASSERT_UNLESS_FUZZING();
return false;
}
*aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
return true;
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* 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/. */
#ifndef mozilla_dom_ContentProcessManager_h
#define mozilla_dom_ContentProcessManager_h
#include <map>
#include <set>
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/TabContext.h"
#include "mozilla/dom/ipc/IdType.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class ContentParent;
struct RemoteFrameInfo
{
TabId mOpenerTabId;
TabContext mContext;
};
struct ContentProcessInfo
{
ContentParent* mCp;
ContentParentId mParentCpId;
std::set<ContentParentId> mChildrenCpId;
std::map<TabId, RemoteFrameInfo> mRemoteFrames;
};
class ContentProcessManager MOZ_FINAL
{
public:
static ContentProcessManager* GetSingleton();
~ContentProcessManager() {MOZ_COUNT_DTOR(ContentProcessManager);};
/**
* Add a new content process into the map.
* If aParentCpId is not 0, it's a nested content process.
*/
void AddContentProcess(ContentParent* aChildCp,
const ContentParentId& aParentCpId = ContentParentId(0));
/**
* Remove the content process by id.
*/
void RemoveContentProcess(const ContentParentId& aChildCpId);
/**
* Add a grandchild content process into the map.
* aParentCpId must be already added in the map by AddContentProcess().
*/
bool AddGrandchildProcess(const ContentParentId& aParentCpId,
const ContentParentId& aChildCpId);
/**
* Get the parent process's id by child process's id.
* Used to check if a child really belongs to the parent.
*/
bool GetParentProcessId(const ContentParentId& aChildCpId,
/*out*/ ContentParentId* aParentCpId);
/**
* Return the ContentParent pointer by id.
*/
ContentParent* GetContentProcessById(const ContentParentId& aChildCpId);
/**
* Return a list of all child process's id.
*/
nsTArray<ContentParentId>
GetAllChildProcessById(const ContentParentId& aParentCpId);
/**
* Allocate a tab id for the given content process's id.
* Used when a content process wants to create a new tab. aOpenerTabId and
* aContext are saved in RemoteFrameInfo, which is a part of ContentProcessInfo.
* We can use the tab id and process id to locate the TabContext for future use.
*/
TabId AllocateTabId(const TabId& aOpenerTabId,
const IPCTabContext& aContext,
const ContentParentId& aChildCpId);
/**
* Remove the RemoteFrameInfo by the given process and tab id.
*/
void DeallocateTabId(const ContentParentId& aChildCpId,
const TabId& aChildTabId);
/**
* Get all app ids which are inside the given content process.
* XXX Currently not used. Plan to be used for bug 1020186.
*/
nsTArray<uint64_t>
GetAppIdsByContentProcess(const ContentParentId& aChildCpId);
/**
* Get all TabContext which are inside the given content process.
* Used for AppProcessChecker to cehck app status.
*/
nsTArray<TabContext>
GetTabContextByContentProcess(const ContentParentId& aChildCpId);
/**
* Query a tab's opener id by the given process and tab id.
* XXX Currently not used. Plan to be used for bug 1020179.
*/
bool GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
const TabId& aChildTabId,
/*out*/ TabId* aOpenerTabId);
private:
static StaticAutoPtr<ContentProcessManager> sSingleton;
TabId mUniqueId;
std::map<ContentParentId, ContentProcessInfo> mContentParentMap;
ContentProcessManager() {MOZ_COUNT_CTOR(ContentProcessManager);};
};
} // namespace dom
} // namespace mozilla
#endif

74
dom/ipc/IdType.h Normal file
Просмотреть файл

@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#ifndef mozilla_dom_IdType_h
#define mozilla_dom_IdType_h
#include "ipc/IPCMessageUtils.h"
namespace IPC {
template<typename T> struct ParamTraits;
}
namespace mozilla {
namespace dom {
class ContentParent;
class TabParent;
template<typename T>
class IdType
{
friend struct IPC::ParamTraits<IdType<T>>;
public:
IdType() : mId(0) {}
explicit IdType(uint64_t aId) : mId(aId) {}
operator uint64_t() const { return mId; }
IdType& operator=(uint64_t aId)
{
mId = aId;
return *this;
}
bool operator<(const IdType& rhs)
{
return mId < rhs.mId;
}
private:
uint64_t mId;
};
typedef IdType<TabParent> TabId;
typedef IdType<ContentParent> ContentParentId;
} // namespace dom
} // namespace mozilla
namespace IPC {
template<typename T>
struct ParamTraits<mozilla::dom::IdType<T>>
{
typedef mozilla::dom::IdType<T> paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mId);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mId);
}
};
}
#endif

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

@ -0,0 +1,21 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=c: */
/* 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 protocol PBrowser;
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
namespace mozilla {
namespace dom {
union PBrowserOrId
{
nullable PBrowser;
TabId;
};
} // namespace dom
} // namespace mozilla

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

@ -67,6 +67,8 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::dom::quota::PersistenceType from "mozilla/dom/quota/PersistenceType.h";
using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
using gfxIntSize from "nsSize.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
union ChromeRegistryItem
{
@ -385,8 +387,8 @@ both:
// access to (in the form of a TabChild).
//
// Keep the last 3 attributes in sync with GetProcessAttributes!
async PBrowser(IPCTabContext context, uint32_t chromeFlags,
uint64_t id, bool isForApp, bool isForBrowser);
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
ContentParentId cpId, bool isForApp, bool isForBrowser);
async PBlob(BlobConstructorParams params);
@ -520,15 +522,16 @@ parent:
* Keep the return values in sync with PBrowser()!
*/
sync GetProcessAttributes()
returns (uint64_t id, bool isForApp, bool isForBrowser);
returns (ContentParentId cpId, bool isForApp, bool isForBrowser);
sync GetXPCOMProcessAttributes()
returns (bool isOffline, nsString[] dictionaries,
ClipboardCapabilities clipboardCaps);
sync CreateChildProcess(IPCTabContext context,
ProcessPriority priority)
returns (uint64_t id, bool isForApp, bool isForBrowser);
intr BridgeToChildProcess(uint64_t id);
ProcessPriority priority,
TabId openerTabId)
returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId);
intr BridgeToChildProcess(ContentParentId cpId);
async PJavaScript();
@ -743,6 +746,14 @@ parent:
returns (int32_t refCnt, int32_t dBRefCnt, int32_t sliceRefCnt,
bool result);
/**
* Tell the chrome process there is an creation of PBrowser.
* return a system-wise unique Id.
*/
sync AllocateTabId(TabId openerTabId, IPCTabContext context, ContentParentId cpId)
returns (TabId tabId);
async DeallocateTabId(TabId tabId);
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);

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

@ -14,6 +14,8 @@ include JavaScriptTypes;
include PTabContext;
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
namespace mozilla {
namespace dom {
@ -41,8 +43,8 @@ parent:
both:
// Both the parent and the child can construct the PBrowser.
// See the comment in PContent::PBrowser().
async PBrowser(IPCTabContext context, uint32_t chromeFlags,
uint64_t id, bool isForApp, bool isForBrowser);
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
ContentParentId cpId, bool isForApp, bool isForBrowser);
async PBlob(BlobConstructorParams params);

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

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include PBrowserOrId;
using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
@ -27,7 +27,7 @@ namespace dom {
// it.
struct PopupIPCTabContext
{
PBrowser opener;
PBrowserOrId opener;
bool isBrowserElement;
};

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

@ -472,14 +472,15 @@ ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
ContentParent* aContentParent)
{
nsRefPtr<ParticularProcessPriorityManager> pppm;
mParticularManagers.Get(aContentParent->ChildID(), &pppm);
uint64_t cpId = aContentParent->ChildID();
mParticularManagers.Get(cpId, &pppm);
if (!pppm) {
pppm = new ParticularProcessPriorityManager(aContentParent);
pppm->Init();
mParticularManagers.Put(aContentParent->ChildID(), pppm);
mParticularManagers.Put(cpId, pppm);
FireTestOnlyObserverNotification("process-created",
nsPrintfCString("%lld", aContentParent->ChildID()));
nsPrintfCString("%lld", cpId));
}
return pppm.forget();

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

@ -733,11 +733,11 @@ private:
StaticRefPtr<TabChild> sPreallocatedTab;
/*static*/
std::map<uint64_t, nsRefPtr<TabChild> >&
std::map<TabId, nsRefPtr<TabChild>>&
TabChild::NestedTabChildMap()
{
MOZ_ASSERT(NS_IsMainThread());
static std::map<uint64_t, nsRefPtr<TabChild> > sNestedTabChildMap;
static std::map<TabId, nsRefPtr<TabChild>> sNestedTabChildMap;
return sNestedTabChildMap;
}
@ -750,6 +750,7 @@ TabChild::PreloadSlowThings()
// not connected to any manager. Any attempt to use the TabChild
// in IPC will crash.
nsRefPtr<TabChild> tab(new TabChild(nullptr,
TabId(0),
TabContext(), /* chromeFlags */ 0));
if (!NS_SUCCEEDED(tab->Init()) ||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
@ -780,6 +781,7 @@ TabChild::PreloadSlowThings()
/*static*/ already_AddRefed<TabChild>
TabChild::Create(nsIContentChild* aManager,
const TabId& aTabId,
const TabContext &aContext,
uint32_t aChromeFlags)
{
@ -793,18 +795,20 @@ TabChild::Create(nsIContentChild* aManager,
MOZ_ASSERT(!child->mTriedBrowserInit);
child->mManager = aManager;
child->SetTabId(aTabId);
child->SetTabContext(aContext);
child->NotifyTabContextUpdated();
return child.forget();
}
nsRefPtr<TabChild> iframe = new TabChild(aManager,
nsRefPtr<TabChild> iframe = new TabChild(aManager, aTabId,
aContext, aChromeFlags);
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
}
TabChild::TabChild(nsIContentChild* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags)
: TabContext(aContext)
@ -827,8 +831,8 @@ TabChild::TabChild(nsIContentChild* aManager,
, mIgnoreKeyPressEvent(false)
, mActiveElementManager(new ActiveElementManager())
, mHasValidInnerSize(false)
, mUniqueId(0)
, mDestroyed(false)
, mUniqueId(aTabId)
{
if (!sActiveDurationMsSet) {
Preferences::AddIntVarCache(&sActiveDurationMs,
@ -836,6 +840,12 @@ TabChild::TabChild(nsIContentChild* aManager,
sActiveDurationMs);
sActiveDurationMsSet = true;
}
// preloaded TabChild should not be added to child map
if (mUniqueId) {
MOZ_ASSERT(NestedTabChildMap().find(mUniqueId) == NestedTabChildMap().end());
NestedTabChildMap()[mUniqueId] = this;
}
}
NS_IMETHODIMP
@ -1433,26 +1443,36 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
{
*aReturn = nullptr;
nsRefPtr<TabChild> newChild =
new TabChild(ContentChild::GetSingleton(),
/* TabContext */ *this, /* chromeFlags */ 0);
if (!NS_SUCCEEDED(newChild->Init())) {
return NS_ERROR_ABORT;
}
ContentChild* cc = ContentChild::GetSingleton();
const TabId openerTabId = GetTabId();
// We must use PopupIPCTabContext here; ContentParent will not accept the
// result of this->AsIPCTabContext() (which will be a
// BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
// reasons.
PopupIPCTabContext context;
context.openerChild() = this;
context.opener() = openerTabId;
context.isBrowserElement() = IsBrowserElement();
ContentChild* cc = static_cast<ContentChild*>(Manager());
IPCTabContext ipcContext(context, mScrolling);
TabId tabId;
cc->SendAllocateTabId(openerTabId,
ipcContext,
cc->GetID(),
&tabId);
nsRefPtr<TabChild> newChild = new TabChild(ContentChild::GetSingleton(), tabId,
/* TabContext */ *this, /* chromeFlags */ 0);
if (NS_FAILED(newChild->Init())) {
return NS_ERROR_ABORT;
}
context.opener() = this;
unused << Manager()->SendPBrowserConstructor(
// We release this ref in DeallocPBrowserChild
nsRefPtr<TabChild>(newChild).forget().take(),
IPCTabContext(context, mScrolling), /* chromeFlags */ 0,
tabId, IPCTabContext(context, mScrolling), /* chromeFlags */ 0,
cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
nsAutoCString spec;
@ -1562,8 +1582,8 @@ TabChild::ActorDestroy(ActorDestroyReason why)
CompositorChild* compositorChild = static_cast<CompositorChild*>(CompositorChild::Get());
compositorChild->CancelNotifyAfterRemotePaint(this);
if (Id() != 0) {
NestedTabChildMap().erase(Id());
if (GetTabId() != 0) {
NestedTabChildMap().erase(GetTabId());
}
}

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

@ -34,6 +34,7 @@
#include "mozilla/EventForwards.h"
#include "mozilla/layers/CompositorTypes.h"
#include "nsIWebBrowserChrome3.h"
#include "mozilla/dom/ipc/IdType.h"
class nsICachedFileDescriptorListener;
class nsIDOMWindowUtils;
@ -254,7 +255,7 @@ class TabChild MOZ_FINAL : public TabChildBase,
typedef mozilla::layers::ActiveElementManager ActiveElementManager;
public:
static std::map<uint64_t, nsRefPtr<TabChild> >& NestedTabChildMap();
static std::map<TabId, nsRefPtr<TabChild>>& NestedTabChildMap();
public:
/**
@ -266,26 +267,13 @@ public:
/** Return a TabChild with the given attributes. */
static already_AddRefed<TabChild>
Create(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
Create(nsIContentChild* aManager, const TabId& aTabId, const TabContext& aContext, uint32_t aChromeFlags);
bool IsRootContentDocument();
const uint64_t Id() const {
return mUniqueId;
}
static uint64_t
GetTabChildId(TabChild* aTabChild)
{
MOZ_ASSERT(NS_IsMainThread());
if (aTabChild->Id() != 0) {
return aTabChild->Id();
}
static uint64_t sId = 0;
sId++;
aTabChild->mUniqueId = sId;
NestedTabChildMap()[sId] = aTabChild;
return sId;
const TabId GetTabId() const {
MOZ_ASSERT(mUniqueId != 0);
return mUniqueId;
}
NS_DECL_ISUPPORTS_INHERITED
@ -516,7 +504,10 @@ private:
*
* |aIsBrowserElement| indicates whether we're a browser (but not an app).
*/
TabChild(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
TabChild(nsIContentChild* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags);
nsresult Init();
@ -564,6 +555,14 @@ private:
void SendPendingTouchPreventedResponse(bool aPreventDefault,
const ScrollableLayerGuid& aGuid);
void SetTabId(const TabId& aTabId)
{
MOZ_ASSERT(mUniqueId == 0);
mUniqueId = aTabId;
NestedTabChildMap()[mUniqueId] = this;
}
class CachedFileDescriptorInfo;
class CachedFileDescriptorCallbackRunnable;
@ -606,8 +605,8 @@ private:
bool mIgnoreKeyPressEvent;
nsRefPtr<ActiveElementManager> mActiveElementManager;
bool mHasValidInnerSize;
uint64_t mUniqueId;
bool mDestroyed;
TabId mUniqueId;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};

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

@ -256,8 +256,8 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
TabContext *context;
if (ipcContext.openerParent()) {
context = static_cast<TabParent*>(ipcContext.openerParent());
if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
context = static_cast<TabParent*>(ipcContext.opener().get_PBrowserParent());
if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
// If the TabParent corresponds to a browser element, then it can only
// open other browser elements, for security reasons. We should have
@ -267,8 +267,13 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
"open a non-browser tab.";
return;
}
} else if (ipcContext.openerChild()) {
context = static_cast<TabChild*>(ipcContext.openerChild());
} else if (ipcContext.opener().type() == PBrowserOrId::TPBrowserChild) {
context = static_cast<TabChild*>(ipcContext.opener().get_PBrowserChild());
} else if (ipcContext.opener().type() == PBrowserOrId::TTabId) {
// We should never get here because this PopupIPCTabContext is only
// used for allocating a new tab id, not for allocating a PBrowser.
mInvalidReason = "Child process tried to open an tab without the opener information.";
return;
} else {
// This should be unreachable because PopupIPCTabContext::opener is not a
// nullable field.

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

@ -218,7 +218,10 @@ NS_IMPL_ISUPPORTS(TabParent,
nsISecureBrowserUI,
nsISupportsWeakReference)
TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags)
TabParent::TabParent(nsIContentParent* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags)
: TabContext(aContext)
, mFrameElement(nullptr)
, mIMESelectionAnchor(0)
@ -242,6 +245,7 @@ TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uin
, mAppPackageFileDescriptorSent(false)
, mSendOfflineStatus(true)
, mChromeFlags(aChromeFlags)
, mTabId(aTabId)
{
MOZ_ASSERT(aManager);
}
@ -318,7 +322,13 @@ TabParent::Recv__delete__()
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
Manager()->AsContentParent()->NotifyTabDestroyed(this, mMarkedDestroying);
ContentParent::DeallocateTabId(mTabId,
Manager()->AsContentParent()->ChildID());
}
else {
ContentParent::DeallocateTabId(mTabId, ContentParentId(0));
}
return true;
}
@ -1648,6 +1658,16 @@ TabParent::GetFrom(nsIContent* aContent)
return GetFrom(frameLoader);
}
/*static*/ TabId
TabParent::GetTabIdFrom(nsIDocShell *docShell)
{
nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
if (tabChild) {
return static_cast<TabChild*>(tabChild.get())->GetTabId();
}
return TabId(0);
}
RenderFrameParent*
TabParent::GetRenderFrame()
{

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

@ -11,6 +11,7 @@
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/dom/PFilePickerParent.h"
#include "mozilla/dom/TabContext.h"
#include "mozilla/dom/ipc/IdType.h"
#include "nsCOMPtr.h"
#include "nsIAuthPromptProvider.h"
#include "nsIBrowserDOMWindow.h"
@ -28,6 +29,7 @@ class nsIURI;
class nsIWidget;
class nsILoadContext;
class CpowHolder;
class nsIDocShell;
namespace mozilla {
@ -67,7 +69,10 @@ public:
// nsITabParent
NS_DECL_NSITABPARENT
TabParent(nsIContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags);
TabParent(nsIContentParent* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags);
Element* GetOwnerElement() const { return mFrameElement; }
void SetOwnerElement(Element* aElement);
@ -322,6 +327,7 @@ public:
static TabParent* GetFrom(nsFrameLoader* aFrameLoader);
static TabParent* GetFrom(nsIContent* aContent);
static TabId GetTabIdFrom(nsIDocShell* docshell);
nsIContentParent* Manager() { return mManager; }
@ -333,6 +339,11 @@ public:
already_AddRefed<nsIWidget> GetWidget() const;
const TabId GetTabId() const
{
return mTabId;
}
protected:
bool ReceiveMessage(const nsString& aMessage,
bool aSync,
@ -435,6 +446,8 @@ private:
uint32_t mChromeFlags;
nsCOMPtr<nsILoadContext> mLoadContext;
TabId mTabId;
};
} // namespace dom

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

@ -11,6 +11,7 @@ EXPORTS += [
EXPORTS.mozilla.dom.ipc += [
'BlobChild.h',
'BlobParent.h',
'IdType.h',
'nsIRemoteBlob.h',
]
@ -20,6 +21,7 @@ EXPORTS.mozilla.dom += [
'ContentChild.h',
'ContentParent.h',
'ContentProcess.h',
'ContentProcessManager.h',
'CPOWManagerGetter.h',
'CrashReporterChild.h',
'CrashReporterParent.h',
@ -47,6 +49,7 @@ UNIFIED_SOURCES += [
'ContentBridgeParent.cpp',
'ContentParent.cpp',
'ContentProcess.cpp',
'ContentProcessManager.cpp',
'CrashReporterParent.cpp',
'FilePickerParent.cpp',
'nsIContentChild.cpp',
@ -77,6 +80,7 @@ IPDL_SOURCES += [
'PBlob.ipdl',
'PBlobStream.ipdl',
'PBrowser.ipdl',
'PBrowserOrId.ipdlh',
'PColorPicker.ipdl',
'PContent.ipdl',
'PContentBridge.ipdl',

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

@ -50,9 +50,10 @@ nsIContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild)
}
PBrowserChild*
nsIContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
nsIContentChild::AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
@ -69,7 +70,7 @@ nsIContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
}
nsRefPtr<TabChild> child =
TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
TabChild::Create(this, aTabId, tc.GetTabContext(), aChromeFlags);
// The ref here is released in DeallocPBrowserChild.
return child.forget().take();

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

@ -7,6 +7,8 @@
#ifndef mozilla_dom_nsIContentChild_h
#define mozilla_dom_nsIContentChild_h
#include "mozilla/dom/ipc/IdType.h"
#include "nsISupports.h"
#include "nsTArrayForwardDeclare.h"
#include "mozilla/dom/CPOWManagerGetter.h"
@ -52,18 +54,20 @@ public:
virtual bool
SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) = 0;
protected:
virtual jsipc::PJavaScriptChild* AllocPJavaScriptChild();
virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser);
virtual bool DeallocPBrowserChild(PBrowserChild*);

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

@ -24,6 +24,13 @@
using namespace mozilla::jsipc;
// XXX need another bug to move this to a common header.
#ifdef DISABLE_ASSERTS_FOR_FUZZING
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
#else
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
#endif
namespace mozilla {
namespace dom {
@ -74,14 +81,19 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
// (PopupIPCTabContext lets the child process prove that it has access to
// the app it's trying to open.)
if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
return false;
}
const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent.");
return false;
}
auto opener = static_cast<TabParent*>(popupContext.opener().get_PBrowserParent());
if (!opener) {
NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
return false;
}
@ -89,7 +101,7 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
// the content to access data it's not supposed to.
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
return false;
}
@ -105,14 +117,14 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
}
PBrowserParent*
nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
unused << aChromeFlags;
unused << aId;
unused << aCpId;
unused << aIsForApp;
unused << aIsForBrowser;
@ -122,7 +134,7 @@ nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
MaybeInvalidTabContext tc(aContext);
MOZ_ASSERT(tc.IsValid());
TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(), aChromeFlags);
// We release this ref in DeallocPBrowserParent()
NS_ADDREF(parent);

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

@ -7,6 +7,8 @@
#ifndef mozilla_dom_nsIContentParent_h
#define mozilla_dom_nsIContentParent_h
#include "mozilla/dom/ipc/IdType.h"
#include "nsFrameMessageManager.h"
#include "nsISupports.h"
#include "mozilla/dom/CPOWManagerGetter.h"
@ -49,7 +51,7 @@ public:
BlobParent* GetOrCreateActorForBlob(File* aBlob);
virtual uint64_t ChildID() = 0;
virtual ContentParentId ChildID() = 0;
virtual bool IsForApp() = 0;
virtual bool IsForBrowser() = 0;
@ -59,9 +61,10 @@ public:
virtual PBrowserParent* SendPBrowserConstructor(
PBrowserParent* actor,
const TabId& aTabId,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser) NS_WARN_UNUSED_RESULT = 0;
@ -75,9 +78,10 @@ protected: // IPDL methods
virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const ContentParentId& aCpId,
const bool& aIsForApp,
const bool& aIsForBrowser);
virtual bool DeallocPBrowserParent(PBrowserParent* frame);

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

@ -287,7 +287,7 @@ public:
uint64_t aWindowID,
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
nsTArray<nsCOMPtr<nsIMediaDevice> >* aDevices)
nsTArray<nsRefPtr<MediaDevice>>* aDevices)
: mDevices(aDevices)
, mWindowID(aWindowID)
, mManager(MediaManager::GetInstance())
@ -338,7 +338,7 @@ public:
private:
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
nsAutoPtr<nsTArray<nsCOMPtr<nsIMediaDevice> > > mDevices;
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
uint64_t mWindowID;
nsRefPtr<MediaManager> mManager;
};
@ -371,14 +371,6 @@ protected:
*/
NS_IMPL_ISUPPORTS(MediaDevice, nsIMediaDevice)
MediaDevice* MediaDevice::Create(MediaEngineVideoSource* source) {
return new VideoDevice(source);
}
MediaDevice* MediaDevice::Create(MediaEngineAudioSource* source) {
return new AudioDevice(source);
}
MediaDevice::MediaDevice(MediaEngineSource* aSource)
: mHasFacingMode(false)
, mSource(aSource) {
@ -421,9 +413,50 @@ VideoDevice::VideoDevice(MediaEngineVideoSource* aSource)
mMediaSource = aSource->GetMediaSource();
}
/**
* Helper functions that implement the constraints algorithm from
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
*/
// Reminder: add handling for new constraints both here and in GetSources below!
bool
VideoDevice::SatisfiesConstraintSets(
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
{
// Interrogate device-inherent properties first.
for (size_t i = 0; i < aConstraintSets.Length(); i++) {
auto& c = *aConstraintSets[i];
if (c.mFacingMode.WasPassed()) {
nsString s;
GetFacingMode(s);
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
static_cast<uint32_t>(c.mFacingMode.Value())].value)) {
return false;
}
}
nsString s;
GetMediaSource(s);
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
static_cast<uint32_t>(c.mMediaSource)].value)) {
return false;
}
}
// Forward request to underlying object to interrogate per-mode capabilities.
return GetSource()->SatisfiesConstraintSets(aConstraintSets);
}
AudioDevice::AudioDevice(MediaEngineAudioSource* aSource)
: MediaDevice(aSource) {}
bool
AudioDevice::SatisfiesConstraintSets(
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
{
// TODO: Add audio-specific constraints
return true;
}
NS_IMETHODIMP
MediaDevice::GetName(nsAString& aName)
{
@ -484,16 +517,16 @@ MediaDevice::GetMediaSource(nsAString& aMediaSource)
return NS_OK;
}
MediaEngineVideoSource*
VideoDevice::Source*
VideoDevice::GetSource()
{
return static_cast<MediaEngineVideoSource*>(&*mSource);
return static_cast<Source*>(&*mSource);
}
MediaEngineAudioSource*
AudioDevice::Source*
AudioDevice::GetSource()
{
return static_cast<MediaEngineAudioSource*>(&*mSource);
return static_cast<Source*>(&*mSource);
}
/**
@ -886,61 +919,24 @@ GetInvariant(const OwningBooleanOrMediaTrackConstraints &aUnion) {
aUnion.GetAsMediaTrackConstraints() : empty;
}
/**
* Helper functions that implement the constraints algorithm from
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
*/
// Reminder: add handling for new constraints both here and in GetSources below!
static bool SatisfyConstraintSet(const MediaEngineVideoSource *,
const MediaTrackConstraintSet &aConstraints,
nsIMediaDevice &aCandidate)
{
nsString s;
if (aConstraints.mFacingMode.WasPassed()) {
aCandidate.GetFacingMode(s);
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
uint32_t(aConstraints.mFacingMode.Value())].value)) {
return false;
}
}
aCandidate.GetMediaSource(s);
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
uint32_t(aConstraints.mMediaSource)].value)) {
return false;
}
// TODO: Add more video-specific constraints
return true;
}
static bool SatisfyConstraintSet(const MediaEngineAudioSource *,
const MediaTrackConstraintSet &aConstraints,
nsIMediaDevice &aCandidate)
{
// TODO: Add audio-specific constraints
return true;
}
typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
// Source getter that constrains list returned
template<class SourceType, class ConstraintsType>
static SourceSet *
template<class DeviceType, class ConstraintsType>
static void
GetSources(MediaEngine *engine,
ConstraintsType &aConstraints,
void (MediaEngine::* aEnumerate)(MediaSourceType, nsTArray<nsRefPtr<SourceType> >*),
void (MediaEngine::* aEnumerate)(MediaSourceType,
nsTArray<nsRefPtr<typename DeviceType::Source> >*),
nsTArray<nsRefPtr<DeviceType>>& aResult,
const char* media_device_name = nullptr)
{
ScopedDeletePtr<SourceSet> result(new SourceSet);
typedef nsTArray<nsRefPtr<DeviceType>> SourceSet;
const SourceType * const type = nullptr;
nsString deviceName;
// First collect sources
SourceSet candidateSet;
{
nsTArray<nsRefPtr<SourceType> > sources;
nsTArray<nsRefPtr<typename DeviceType::Source> > sources;
// all MediaSourceEnums are contained in MediaSourceType
(engine->*aEnumerate)((MediaSourceType)((int)aConstraints.mMediaSource), &sources);
/**
@ -953,11 +949,11 @@ static SourceSet *
sources[i]->GetName(deviceName);
if (media_device_name && strlen(media_device_name) > 0) {
if (deviceName.EqualsASCII(media_device_name)) {
candidateSet.AppendElement(MediaDevice::Create(sources[i]));
candidateSet.AppendElement(new DeviceType(sources[i]));
break;
}
} else {
candidateSet.AppendElement(MediaDevice::Create(sources[i]));
candidateSet.AppendElement(new DeviceType(sources[i]));
}
}
}
@ -970,16 +966,22 @@ static SourceSet *
// this media-type. The spec requires these to fail, so getting them out of
// the way early provides a necessary invariant for the remaining algorithm
// which maximizes code-reuse by ignoring constraints of the other type
// (specifically, SatisfyConstraintSet is reused for the advanced algorithm
// (specifically, SatisfiesConstraintSets is reused for the advanced algorithm
// where the spec requires it to ignore constraints of the other type)
return result.forget();
return;
}
// Now on to the actual algorithm: First apply required constraints.
// Stack constraintSets that pass, starting with the required one, because the
// whole stack must be re-satisfied each time a capability-set is ruled out
// (this avoids storing state and pushing algorithm into the lower-level code).
nsTArray<const MediaTrackConstraintSet*> aggregateConstraints;
aggregateConstraints.AppendElement(&c.mRequired);
for (uint32_t i = 0; i < candidateSet.Length();) {
// Overloading instead of template specialization keeps things local
if (!SatisfyConstraintSet(type, c.mRequired, *candidateSet[i])) {
if (!candidateSet[i]->SatisfiesConstraintSets(aggregateConstraints)) {
candidateSet.RemoveElementAt(i);
} else {
++i;
@ -1018,9 +1020,10 @@ static SourceSet *
auto &array = c.mAdvanced.Value();
for (int i = 0; i < int(array.Length()); i++) {
aggregateConstraints.AppendElement(&array[i]);
SourceSet rejects;
for (uint32_t j = 0; j < candidateSet.Length();) {
if (!SatisfyConstraintSet(type, array[i], *candidateSet[j])) {
if (!candidateSet[j]->SatisfiesConstraintSets(aggregateConstraints)) {
rejects.AppendElement(candidateSet[j]);
candidateSet.RemoveElementAt(j);
} else {
@ -1028,14 +1031,16 @@ static SourceSet *
}
}
(candidateSet.Length()? tailSet : candidateSet).MoveElementsFrom(rejects);
if (!candidateSet.Length()) {
aggregateConstraints.RemoveElementAt(aggregateConstraints.Length() - 1);
}
}
}
// TODO: Proper non-ordered handling of nonrequired constraints (Bug 907352)
result->MoveElementsFrom(candidateSet);
result->MoveElementsFrom(tailSet);
return result.forget();
aResult.MoveElementsFrom(candidateSet);
aResult.MoveElementsFrom(tailSet);
}
/**
@ -1193,29 +1198,28 @@ public:
MOZ_ASSERT(mError);
if (IsOn(mConstraints.mVideo)) {
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
ScopedDeletePtr<SourceSet> sources(GetSources(backend, constraints,
&MediaEngine::EnumerateVideoDevices));
nsTArray<nsRefPtr<VideoDevice>> sources;
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources);
if (!sources->Length()) {
if (!sources.Length()) {
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
return NS_ERROR_FAILURE;
}
// Pick the first available device.
mVideoDevice = do_QueryObject((*sources)[0]);
mVideoDevice = sources[0];
LOG(("Selected video device"));
}
if (IsOn(mConstraints.mAudio)) {
AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
ScopedDeletePtr<SourceSet> sources (GetSources(backend, constraints,
&MediaEngine::EnumerateAudioDevices));
nsTArray<nsRefPtr<AudioDevice>> sources;
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources);
if (!sources->Length()) {
if (!sources.Length()) {
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
return NS_ERROR_FAILURE;
}
// Pick the first available device.
mAudioDevice = do_QueryObject((*sources)[0]);
mAudioDevice = sources[0];
LOG(("Selected audio device"));
}
@ -1341,20 +1345,26 @@ public:
else
backend = mManager->GetBackend(mWindowId);
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
ScopedDeletePtr<SourceSet> final(new SourceSet);
if (IsOn(mConstraints.mVideo)) {
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
ScopedDeletePtr<SourceSet> s(GetSources(backend, constraints,
&MediaEngine::EnumerateVideoDevices,
mLoopbackVideoDevice.get()));
final->MoveElementsFrom(*s);
nsTArray<nsRefPtr<VideoDevice>> s;
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, s,
mLoopbackVideoDevice.get());
for (uint32_t i = 0; i < s.Length(); i++) {
final->AppendElement(s[i]);
}
}
if (IsOn(mConstraints.mAudio)) {
AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
ScopedDeletePtr<SourceSet> s (GetSources(backend, constraints,
&MediaEngine::EnumerateAudioDevices,
mLoopbackAudioDevice.get()));
final->MoveElementsFrom(*s);
nsTArray<nsRefPtr<AudioDevice>> s;
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, s,
mLoopbackAudioDevice.get());
for (uint32_t i = 0; i < s.Length(); i++) {
final->AppendElement(s[i]);
}
}
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,

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

@ -46,6 +46,7 @@ namespace dom {
struct MediaStreamConstraints;
class NavigatorUserMediaSuccessCallback;
class NavigatorUserMediaErrorCallback;
struct MediaTrackConstraintSet;
}
#ifdef PR_LOGGING
@ -501,9 +502,6 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIMEDIADEVICE
static MediaDevice* Create(MediaEngineVideoSource* source);
static MediaDevice* Create(MediaEngineAudioSource* source);
protected:
virtual ~MediaDevice() {}
explicit MediaDevice(MediaEngineSource* aSource);
@ -518,17 +516,25 @@ protected:
class VideoDevice : public MediaDevice
{
public:
explicit VideoDevice(MediaEngineVideoSource* aSource);
typedef MediaEngineVideoSource Source;
explicit VideoDevice(Source* aSource);
NS_IMETHOD GetType(nsAString& aType);
MediaEngineVideoSource* GetSource();
Source* GetSource();
bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
};
class AudioDevice : public MediaDevice
{
public:
explicit AudioDevice(MediaEngineAudioSource* aSource);
typedef MediaEngineAudioSource Source;
explicit AudioDevice(Source* aSource);
NS_IMETHOD GetType(nsAString& aType);
MediaEngineAudioSource* GetSource();
Source* GetSource();
bool SatisfiesConstraintSets(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
};
// we could add MediaManager if needed

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

@ -4,52 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsRenderingContext.h"
#include <string.h> // for strlen
#include <algorithm> // for min
#include "gfxColor.h" // for gfxRGBA
#include "gfxMatrix.h" // for gfxMatrix
#include "gfxPoint.h" // for gfxPoint, gfxSize
#include "gfxRect.h" // for gfxRect
#include "gfxTypes.h" // for gfxFloat
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/mozalloc.h" // for operator delete[], etc
#include "nsBoundingMetrics.h" // for nsBoundingMetrics
#include "nsCharTraits.h" // for NS_IS_LOW_SURROGATE
#include "nsDebug.h" // for NS_ERROR
#include "nsPoint.h" // for nsPoint
#include "nsRect.h" // for nsRect, nsIntRect
#include "nsRegion.h" // for nsIntRegionRectIterator, etc
// Hard limit substring lengths to 8000 characters ... this lets us statically
// size the cluster buffer array in FindSafeLength
#define MAX_GFX_TEXT_BUF_SIZE 8000
/*static*/ int32_t
nsRenderingContext::FindSafeLength(const char16_t *aString, uint32_t aLength,
uint32_t aMaxChunkLength)
{
if (aLength <= aMaxChunkLength)
return aLength;
int32_t len = aMaxChunkLength;
// Ensure that we don't break inside a surrogate pair
while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
len--;
}
if (len == 0) {
// We don't want our caller to go into an infinite loop, so don't
// return zero. It's hard to imagine how we could actually get here
// unless there are languages that allow clusters of arbitrary size.
// If there are and someone feeds us a 500+ character cluster, too
// bad.
return aMaxChunkLength;
}
return len;
}
//////////////////////////////////////////////////////////////////////
//// nsRenderingContext
void
nsRenderingContext::Init(gfxContext *aThebesContext)
@ -63,77 +17,3 @@ nsRenderingContext::Init(DrawTarget *aDrawTarget)
{
Init(new gfxContext(aDrawTarget));
}
//
// text
//
void
nsRenderingContext::SetTextRunRTL(bool aIsRTL)
{
mFontMetrics->SetTextRunRTL(aIsRTL);
}
void
nsRenderingContext::SetFont(nsFontMetrics *aFontMetrics)
{
mFontMetrics = aFontMetrics;
}
int32_t
nsRenderingContext::GetMaxChunkLength()
{
return std::min(mFontMetrics->GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
}
nscoord
nsRenderingContext::GetWidth(char16_t aC)
{
return GetWidth(&aC, 1);
}
nscoord
nsRenderingContext::GetWidth(const nsString& aString)
{
return GetWidth(aString.get(), aString.Length());
}
nscoord
nsRenderingContext::GetWidth(const char16_t *aString, uint32_t aLength)
{
uint32_t maxChunkLength = GetMaxChunkLength();
nscoord width = 0;
while (aLength > 0) {
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
width += mFontMetrics->GetWidth(aString, len, this);
aLength -= len;
aString += len;
}
return width;
}
nsBoundingMetrics
nsRenderingContext::GetBoundingMetrics(const char16_t* aString,
uint32_t aLength)
{
uint32_t maxChunkLength = GetMaxChunkLength();
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
// Assign directly in the first iteration. This ensures that
// negative ascent/descent can be returned and the left bearing
// is properly initialized.
nsBoundingMetrics totalMetrics
= mFontMetrics->GetBoundingMetrics(aString, len, this);
aLength -= len;
aString += len;
while (aLength > 0) {
len = FindSafeLength(aString, aLength, maxChunkLength);
nsBoundingMetrics metrics
= mFontMetrics->GetBoundingMetrics(aString, len, this);
totalMetrics += metrics;
aLength -= len;
aString += len;
}
return totalMetrics;
}

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

@ -6,31 +6,22 @@
#ifndef NSRENDERINGCONTEXT__H__
#define NSRENDERINGCONTEXT__H__
#include <stdint.h> // for uint32_t
#include <sys/types.h> // for int32_t
#include "gfxContext.h" // for gfxContext
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/gfx/2D.h"
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsBoundingMetrics.h" // for nsBoundingMetrics
#include "nsColor.h" // for nscolor
#include "nsCoord.h" // for nscoord, NSToIntRound
#include "nsFontMetrics.h" // for nsFontMetrics
#include "nsISupports.h" // for NS_INLINE_DECL_REFCOUNTING, etc
#include "nsString.h" // for nsString
#include "nscore.h" // for char16_t
#include "gfxContext.h"
#include "mozilla/Attributes.h"
#include "nsISupportsImpl.h"
#include "nsRefPtr.h"
class nsIntRegion;
struct nsPoint;
struct nsRect;
namespace mozilla {
namespace gfx {
class DrawTarget;
}
}
class nsRenderingContext MOZ_FINAL
{
typedef mozilla::gfx::DrawTarget DrawTarget;
public:
nsRenderingContext() {}
NS_INLINE_DECL_REFCOUNTING(nsRenderingContext)
void Init(gfxContext* aThebesContext);
@ -40,31 +31,11 @@ public:
gfxContext *ThebesContext() { return mThebes; }
DrawTarget *GetDrawTarget() { return mThebes->GetDrawTarget(); }
// Text
void SetFont(nsFontMetrics *aFontMetrics);
nsFontMetrics *FontMetrics() { return mFontMetrics; } // may be null
void SetTextRunRTL(bool aIsRTL);
nscoord GetWidth(char16_t aC);
nscoord GetWidth(const nsString& aString);
nscoord GetWidth(const char16_t *aString, uint32_t aLength);
nsBoundingMetrics GetBoundingMetrics(const char16_t *aString,
uint32_t aLength);
int32_t GetMaxChunkLength();
static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
uint32_t aMaxChunkLength);
private:
// Private destructor, to discourage deletion outside of Release():
~nsRenderingContext()
{
}
~nsRenderingContext() {}
nsRefPtr<gfxContext> mThebes;
nsRefPtr<nsFontMetrics> mFontMetrics;
};
#endif // NSRENDERINGCONTEXT__H__

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

@ -66,21 +66,27 @@ support-files =
# [test_bug478398.html]
# disabled - See bug 579139
[test_bug490949.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug496292.html]
[test_bug497665.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug512435.html]
[test_bug552605-1.html]
[test_bug552605-2.html]
[test_bug553982.html]
[test_bug601470.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug614392.html]
[test_bug657191.html]
[test_bug671906.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug733553.html]
[test_bug767779.html]
[test_bug865919.html]
[test_bug89419-1.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_bug89419-2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_animation_operators.html]
[test_drawDiscardedImage.html]
skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost connection to device.

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

@ -0,0 +1,13 @@
function reportCompare (expected, actual) {
var actual_t = typeof actual;
var output = "";
output += "x" + actual_t + " ";
expected != actual;
output += undefined;
}
gczeal(7,1);
for (var i=0; i<900; i++) {
reportCompare("abc", function() {});
reportCompare(null, 10);
}

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

@ -119,6 +119,10 @@ class CompactBufferWriter
MOZ_ASSERT(byte <= 0xFF);
enoughMemory_ &= buffer_.append(byte);
}
void writeByteAt(uint32_t pos, uint32_t byte) {
MOZ_ASSERT(byte <= 0xFF);
buffer_[pos] = byte;
}
void writeUnsigned(uint32_t value) {
do {
uint8_t byte = ((value & 0x7F) << 1) | (value > 0x7F);
@ -126,6 +130,15 @@ class CompactBufferWriter
value >>= 7;
} while (value);
}
void writeUnsignedAt(uint32_t pos, uint32_t value, uint32_t original) {
MOZ_ASSERT(value <= original);
do {
uint8_t byte = ((value & 0x7F) << 1) | (original > 0x7F);
writeByteAt(pos++, byte);
value >>= 7;
original >>= 7;
} while (original);
}
void writeSigned(int32_t v) {
bool isNegative = v < 0;
uint32_t value = isNegative ? -v : v;

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

@ -275,7 +275,7 @@ class RInstructionResults
bool initialized_;
public:
RInstructionResults(IonJSFrameLayout *fp);
explicit RInstructionResults(IonJSFrameLayout *fp);
RInstructionResults(RInstructionResults&& src);
RInstructionResults& operator=(RInstructionResults&& rhs);
@ -310,7 +310,7 @@ struct MaybeReadFallback
const NoGCValue unreadablePlaceholder_;
const FallbackConsequence consequence;
MaybeReadFallback(const Value &placeholder = UndefinedValue())
explicit MaybeReadFallback(const Value &placeholder = UndefinedValue())
: maybeCx(nullptr),
activation(nullptr),
frame(nullptr),

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

@ -233,7 +233,7 @@ class LSimdSignMaskX4 : public LInstructionHelper<1, 1, 0>
class LSimdSwizzleBase : public LInstructionHelper<1, 1, 0>
{
public:
LSimdSwizzleBase(const LAllocation &base)
explicit LSimdSwizzleBase(const LAllocation &base)
{
setOperand(0, base);
}
@ -257,7 +257,7 @@ class LSimdSwizzleI : public LSimdSwizzleBase
{
public:
LIR_HEADER(SimdSwizzleI);
LSimdSwizzleI(const LAllocation &base) : LSimdSwizzleBase(base)
explicit LSimdSwizzleI(const LAllocation &base) : LSimdSwizzleBase(base)
{}
};
// Shuffles a float32x4 into another float32x4 vector.
@ -265,7 +265,7 @@ class LSimdSwizzleF : public LSimdSwizzleBase
{
public:
LIR_HEADER(SimdSwizzleF);
LSimdSwizzleF(const LAllocation &base) : LSimdSwizzleBase(base)
explicit LSimdSwizzleF(const LAllocation &base) : LSimdSwizzleBase(base)
{}
};
@ -4203,7 +4203,7 @@ class LTypedObjectUnsizedLength : public LInstructionHelper<1, 1, 0>
public:
LIR_HEADER(TypedObjectUnsizedLength)
LTypedObjectUnsizedLength(const LAllocation &object) {
explicit LTypedObjectUnsizedLength(const LAllocation &object) {
setOperand(0, object);
}
const LAllocation *object() {

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

@ -1234,12 +1234,13 @@ class LSnapshot : public TempObject
};
struct SafepointNunboxEntry {
uint32_t typeVreg;
LAllocation type;
LAllocation payload;
SafepointNunboxEntry() { }
SafepointNunboxEntry(LAllocation type, LAllocation payload)
: type(type), payload(payload)
SafepointNunboxEntry(uint32_t typeVreg, LAllocation type, LAllocation payload)
: typeVreg(typeVreg), type(type), payload(payload)
{ }
};
@ -1322,7 +1323,6 @@ class LSafepoint : public TempObject
, valueSlots_(alloc)
#ifdef JS_NUNBOX32
, nunboxParts_(alloc)
, partialNunboxes_(0)
#endif
, slotsOrElementsSlots_(alloc)
{
@ -1441,8 +1441,8 @@ class LSafepoint : public TempObject
#ifdef JS_NUNBOX32
bool addNunboxParts(LAllocation type, LAllocation payload) {
bool result = nunboxParts_.append(NunboxEntry(type, payload));
bool addNunboxParts(uint32_t typeVreg, LAllocation type, LAllocation payload) {
bool result = nunboxParts_.append(NunboxEntry(typeVreg, type, payload));
if (result)
assertInvariants();
return result;
@ -1454,52 +1454,49 @@ class LSafepoint : public TempObject
return true;
if (nunboxParts_[i].type == LUse(typeVreg, LUse::ANY)) {
nunboxParts_[i].type = type;
partialNunboxes_--;
return true;
}
}
partialNunboxes_++;
// vregs for nunbox pairs are adjacent, with the type coming first.
uint32_t payloadVreg = typeVreg + 1;
bool result = nunboxParts_.append(NunboxEntry(type, LUse(payloadVreg, LUse::ANY)));
bool result = nunboxParts_.append(NunboxEntry(typeVreg, type, LUse(payloadVreg, LUse::ANY)));
if (result)
assertInvariants();
return result;
}
bool hasNunboxType(LAllocation type) const {
if (type.isArgument())
return true;
if (type.isStackSlot() && hasValueSlot(type.toStackSlot()->slot() + 1))
return true;
for (size_t i = 0; i < nunboxParts_.length(); i++) {
if (nunboxParts_[i].type == type)
return true;
}
return false;
}
bool addNunboxPayload(uint32_t payloadVreg, LAllocation payload) {
for (size_t i = 0; i < nunboxParts_.length(); i++) {
if (nunboxParts_[i].payload == payload)
return true;
if (nunboxParts_[i].payload == LUse(payloadVreg, LUse::ANY)) {
partialNunboxes_--;
nunboxParts_[i].payload = payload;
return true;
}
}
partialNunboxes_++;
// vregs for nunbox pairs are adjacent, with the type coming first.
uint32_t typeVreg = payloadVreg - 1;
bool result = nunboxParts_.append(NunboxEntry(LUse(typeVreg, LUse::ANY), payload));
bool result = nunboxParts_.append(NunboxEntry(typeVreg, LUse(typeVreg, LUse::ANY), payload));
if (result)
assertInvariants();
return result;
}
LAllocation findTypeAllocation(uint32_t typeVreg) {
// Look for some allocation for the specified type vreg, to go with a
// partial nunbox entry for the payload. Note that we don't need to
// look at the value slots in the safepoint, as these aren't used by
// register allocators which add partial nunbox entries.
for (size_t i = 0; i < nunboxParts_.length(); i++) {
if (nunboxParts_[i].typeVreg == typeVreg && !nunboxParts_[i].type.isUse())
return nunboxParts_[i].type;
}
return LUse(typeVreg, LUse::ANY);
}
#ifdef DEBUG
bool hasNunboxPayload(LAllocation payload) const {
if (payload.isArgument())
return true;
@ -1511,15 +1508,12 @@ class LSafepoint : public TempObject
}
return false;
}
#endif
NunboxList &nunboxParts() {
return nunboxParts_;
}
uint32_t partialNunboxes() {
return partialNunboxes_;
}
#elif JS_PUNBOX64
void addValueRegister(Register reg) {

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

@ -609,14 +609,18 @@ LinearScanAllocator::populateSafepoints()
// in a register, or the payload is in a register. In
// both cases, we don't have a contiguous spill so we
// add a torn entry.
if (!safepoint->addNunboxParts(*typeAlloc, *payloadAlloc))
uint32_t typeVreg = type->def()->virtualRegister();
if (!safepoint->addNunboxParts(typeVreg, *typeAlloc, *payloadAlloc))
return false;
// If the nunbox is stored in multiple places, we need to
// trace all of them to allow the GC to relocate objects.
if (payloadAlloc->isGeneralReg() && isSpilledAt(payloadInterval, inputOf(ins))) {
if (!safepoint->addNunboxParts(*typeAlloc, *payload->canonicalSpill()))
if (!safepoint->addNunboxParts(typeVreg, *typeAlloc,
*payload->canonicalSpill()))
{
return false;
}
}
}
#endif

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

@ -299,18 +299,29 @@ SafepointWriter::writeNunboxParts(LSafepoint *safepoint)
// Safepoints are permitted to have partially filled in entries for nunboxes,
// provided that only the type is live and not the payload. Omit these from
// the written safepoint.
uint32_t partials = safepoint->partialNunboxes();
stream_.writeUnsigned(entries.length() - partials);
size_t pos = stream_.length();
stream_.writeUnsigned(entries.length());
size_t count = 0;
for (size_t i = 0; i < entries.length(); i++) {
SafepointNunboxEntry &entry = entries[i];
if (entry.type.isUse() || entry.payload.isUse()) {
partials--;
if (entry.payload.isUse()) {
// No allocation associated with the payload.
continue;
}
if (entry.type.isUse()) {
// No allocation associated with the type. Look for another
// safepoint entry with an allocation for the type.
entry.type = safepoint->findTypeAllocation(entry.typeVreg);
if (entry.type.isUse())
continue;
}
count++;
uint16_t header = 0;
header |= (AllocationToPartKind(entry.type) << TYPE_KIND_SHIFT);
@ -337,7 +348,8 @@ SafepointWriter::writeNunboxParts(LSafepoint *safepoint)
stream_.writeUnsigned(payloadVal);
}
MOZ_ASSERT(partials == 0);
// Update the stream with the actual number of safepoint entries written.
stream_.writeUnsignedAt(pos, count, entries.length());
}
#endif

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

@ -4686,7 +4686,7 @@ GCRuntime::endMarkingZoneGroup()
JSRuntime *runtime;\
virtual void run() MOZ_OVERRIDE;\
public:\
name (JSRuntime *rt) : runtime(rt) {}\
explicit name (JSRuntime *rt) : runtime(rt) {}\
}
MAKE_GC_PARALLEL_TASK(SweepAtomsTask);
MAKE_GC_PARALLEL_TASK(SweepInnerViewsTask);

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

@ -1106,12 +1106,12 @@ struct TypeObject : public gc::TenuredCell
}
void addFlags(TypeObjectFlags flags) {
MOZ_ASSERT(!needsSweep());
maybeSweep(nullptr);
flags_ |= flags;
}
void clearFlags(TypeObjectFlags flags) {
MOZ_ASSERT(!needsSweep());
maybeSweep(nullptr);
flags_ &= ~flags;
}

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

@ -308,13 +308,18 @@ class TypedArrayObjectTemplate : public TypedArrayObject
makeTypedInstance(JSContext *cx, uint32_t len, gc::AllocKind allocKind)
{
const Class *clasp = instanceClass();
bool largeAllocation = len * sizeof(NativeType) >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH;
if (len * sizeof(NativeType) >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH) {
JSObject *obj = NewBuiltinClassInstance(cx, clasp, allocKind, SingletonObject);
if (!obj)
return nullptr;
return &obj->as<TypedArrayObject>();
}
jsbytecode *pc;
RootedScript script(cx, cx->currentScript(&pc));
NewObjectKind newKind = script
? UseNewTypeForInitializer(script, pc, clasp)
: (largeAllocation ? SingletonObject : GenericObject);
: GenericObject;
RootedObject obj(cx, NewBuiltinClassInstance(cx, clasp, allocKind, newKind));
if (!obj)
return nullptr;

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsBidiPresUtils.h"
#include "nsFontMetrics.h"
#include "nsGkAtoms.h"
#include "nsPresContext.h"
#include "nsRenderingContext.h"
@ -2054,42 +2055,51 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText,
return NS_OK;
}
class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor : public nsBidiPresUtils::BidiProcessor {
class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor MOZ_FINAL
: public nsBidiPresUtils::BidiProcessor
{
public:
nsIRenderingContextBidiProcessor(nsRenderingContext* aCtx,
nsRenderingContext* aTextRunConstructionContext,
nsFontMetrics* aFontMetrics,
const nsPoint& aPt)
: mCtx(aCtx), mTextRunConstructionContext(aTextRunConstructionContext), mPt(aPt) { }
: mCtx(aCtx)
, mTextRunConstructionContext(aTextRunConstructionContext)
, mFontMetrics(aFontMetrics)
, mPt(aPt)
{}
~nsIRenderingContextBidiProcessor()
{
mCtx->SetTextRunRTL(false);
mFontMetrics->SetTextRunRTL(false);
}
virtual void SetText(const char16_t* aText,
int32_t aLength,
nsBidiDirection aDirection) MOZ_OVERRIDE
{
mTextRunConstructionContext->SetTextRunRTL(aDirection==NSBIDI_RTL);
mFontMetrics->SetTextRunRTL(aDirection==NSBIDI_RTL);
mText = aText;
mLength = aLength;
}
virtual nscoord GetWidth() MOZ_OVERRIDE
{
return mTextRunConstructionContext->GetWidth(mText, mLength);
return nsLayoutUtils::AppUnitWidthOfString(mText, mLength, *mFontMetrics,
*mTextRunConstructionContext);
}
virtual void DrawText(nscoord aXOffset,
nscoord) MOZ_OVERRIDE
{
mCtx->FontMetrics()->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
mCtx, mTextRunConstructionContext);
mFontMetrics->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
mCtx, mTextRunConstructionContext);
}
private:
nsRenderingContext* mCtx;
nsRenderingContext* mTextRunConstructionContext;
nsFontMetrics* mFontMetrics;
nsPoint mPt;
const char16_t* mText;
int32_t mLength;
@ -2101,6 +2111,7 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const char16_t* a
nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsRenderingContext& aTextRunConstructionContext,
nsFontMetrics& aFontMetrics,
Mode aMode,
nscoord aX,
nscoord aY,
@ -2108,7 +2119,10 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const char16_t* a
int32_t aPosResolveCount,
nscoord* aWidth)
{
nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
nsIRenderingContextBidiProcessor processor(&aRenderingContext,
&aTextRunConstructionContext,
&aFontMetrics,
nsPoint(aX, aY));
nsBidi bidiEngine;
return ProcessText(aText, aLength, aBaseLevel, aPresContext, processor,
aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine);

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

@ -18,6 +18,7 @@
struct BidiParagraphData;
struct BidiLineData;
class nsFontMetrics;
class nsIFrame;
class nsBlockFrame;
class nsPresContext;
@ -206,24 +207,29 @@ public:
nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsRenderingContext& aTextRunConstructionContext,
nsFontMetrics& aFontMetrics,
nscoord aX,
nscoord aY,
nsBidiPositionResolve* aPosResolve = nullptr,
int32_t aPosResolveCount = 0)
{
return ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
aTextRunConstructionContext,
aFontMetrics,
MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
}
static nscoord MeasureTextWidth(const char16_t* aText,
int32_t aLength,
nsBidiLevel aBaseLevel,
nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext)
nsRenderingContext& aRenderingContext,
nsFontMetrics& aFontMetrics)
{
nscoord length;
nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext,
aRenderingContext, aRenderingContext,
aFontMetrics,
MODE_MEASURE, 0, 0, nullptr, 0, &length);
return NS_SUCCEEDED(rv) ? length : 0;
}
@ -360,6 +366,7 @@ private:
nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsRenderingContext& aTextRunConstructionContext,
nsFontMetrics& aFontMetrics,
Mode aMode,
nscoord aX, // DRAW only
nscoord aY, // DRAW only

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

@ -13,6 +13,7 @@
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsITimer.h"
#include "nsFrameSelection.h"
#include "nsIFrame.h"

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

@ -11,6 +11,8 @@
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "nsCharTraits.h"
#include "nsFontMetrics.h"
#include "nsPresContext.h"
#include "nsIContent.h"
#include "nsIDOMHTMLDocument.h"
@ -3185,6 +3187,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
*/
bool
nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
nsFontMetrics& aFontMetrics,
const char16_t* aText,
int32_t aBaseWidth,
int32_t aBaseInx,
@ -3197,7 +3200,9 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
int32_t range = aEndInx - aStartInx;
if ((range == 1) || (range == 2 && NS_IS_HIGH_SURROGATE(aText[aStartInx]))) {
aIndex = aStartInx + aBaseInx;
aTextWidth = aRendContext->GetWidth(aText, aIndex);
aTextWidth = nsLayoutUtils::AppUnitWidthOfString(aText, aIndex,
aFontMetrics,
*aRendContext);
return true;
}
@ -3207,7 +3212,9 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
if (NS_IS_HIGH_SURROGATE(aText[inx-1]))
inx++;
int32_t textWidth = aRendContext->GetWidth(aText, inx);
int32_t textWidth = nsLayoutUtils::AppUnitWidthOfString(aText, inx,
aFontMetrics,
*aRendContext);
int32_t fullWidth = aBaseWidth + textWidth;
if (fullWidth == aCursorPos) {
@ -3216,12 +3223,16 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
return true;
} else if (aCursorPos < fullWidth) {
aTextWidth = aBaseWidth;
if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, aStartInx, inx, aCursorPos, aIndex, aTextWidth)) {
if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
aBaseInx, aStartInx, inx, aCursorPos, aIndex,
aTextWidth)) {
return true;
}
} else {
aTextWidth = fullWidth;
if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, inx, aEndInx, aCursorPos, aIndex, aTextWidth)) {
if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
aBaseInx, inx, aEndInx, aCursorPos, aIndex,
aTextWidth)) {
return true;
}
}
@ -4628,8 +4639,94 @@ nsLayoutUtils::GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
}
// Hard limit substring lengths to 8000 characters ... this lets us statically
// size the cluster buffer array in FindSafeLength
#define MAX_GFX_TEXT_BUF_SIZE 8000
static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
uint32_t aMaxChunkLength)
{
if (aLength <= aMaxChunkLength)
return aLength;
int32_t len = aMaxChunkLength;
// Ensure that we don't break inside a surrogate pair
while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
len--;
}
if (len == 0) {
// We don't want our caller to go into an infinite loop, so don't
// return zero. It's hard to imagine how we could actually get here
// unless there are languages that allow clusters of arbitrary size.
// If there are and someone feeds us a 500+ character cluster, too
// bad.
return aMaxChunkLength;
}
return len;
}
static int32_t GetMaxChunkLength(nsFontMetrics& aFontMetrics)
{
return std::min(aFontMetrics.GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
}
nscoord
nsLayoutUtils::AppUnitWidthOfString(const nsString& aString,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext)
{
return AppUnitWidthOfString(aString.get(), aString.Length(),
aFontMetrics, aContext);
}
nscoord
nsLayoutUtils::AppUnitWidthOfString(const char16_t *aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext)
{
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
nscoord width = 0;
while (aLength > 0) {
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
width += aFontMetrics.GetWidth(aString, len, &aContext);
aLength -= len;
aString += len;
}
return width;
}
nsBoundingMetrics
nsLayoutUtils::AppUnitBoundsOfString(const char16_t* aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext)
{
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
// Assign directly in the first iteration. This ensures that
// negative ascent/descent can be returned and the left bearing
// is properly initialized.
nsBoundingMetrics totalMetrics =
aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
aLength -= len;
aString += len;
while (aLength > 0) {
len = FindSafeLength(aString, aLength, maxChunkLength);
nsBoundingMetrics metrics =
aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
totalMetrics += metrics;
aLength -= len;
aString += len;
}
return totalMetrics;
}
void
nsLayoutUtils::DrawString(const nsIFrame* aFrame,
nsFontMetrics& aFontMetrics,
nsRenderingContext* aContext,
const char16_t* aString,
int32_t aLength,
@ -4644,12 +4741,13 @@ nsLayoutUtils::DrawString(const nsIFrame* aFrame,
aStyleContext : aFrame->StyleContext());
rv = nsBidiPresUtils::RenderText(aString, aLength, level,
presContext, *aContext, *aContext,
aFontMetrics,
aPoint.x, aPoint.y);
}
if (NS_FAILED(rv))
{
aContext->SetTextRunRTL(false);
DrawUniDirString(aString, aLength, aPoint, *aContext);
aFontMetrics.SetTextRunRTL(false);
DrawUniDirString(aString, aLength, aPoint, aFontMetrics, *aContext);
}
}
@ -4657,33 +4755,33 @@ void
nsLayoutUtils::DrawUniDirString(const char16_t* aString,
uint32_t aLength,
nsPoint aPoint,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext)
{
nscoord x = aPoint.x;
nscoord y = aPoint.y;
nsFontMetrics* fm = aContext.FontMetrics();
uint32_t maxChunkLength = aContext.GetMaxChunkLength();
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
if (aLength <= maxChunkLength) {
fm->DrawString(aString, aLength, x, y, &aContext, &aContext);
aFontMetrics.DrawString(aString, aLength, x, y, &aContext, &aContext);
return;
}
bool isRTL = fm->GetTextRunRTL();
bool isRTL = aFontMetrics.GetTextRunRTL();
// If we're drawing right to left, we must start at the end.
if (isRTL) {
x += aContext.GetWidth(aString, aLength);
x += nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
aContext);
}
while (aLength > 0) {
int32_t len = nsRenderingContext::FindSafeLength(aString, aLength, maxChunkLength);
nscoord width = fm->GetWidth(aString, len, &aContext);
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
nscoord width = aFontMetrics.GetWidth(aString, len, &aContext);
if (isRTL) {
x -= width;
}
fm->DrawString(aString, len, x, y, &aContext, &aContext);
aFontMetrics.DrawString(aString, len, x, y, &aContext, &aContext);
if (!isRTL) {
x += width;
}
@ -4695,6 +4793,7 @@ nsLayoutUtils::DrawUniDirString(const char16_t* aString,
nscoord
nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
nsRenderingContext* aContext,
nsFontMetrics& aFontMetrics,
const char16_t* aString,
int32_t aLength)
{
@ -4703,10 +4802,12 @@ nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
nsBidiLevel level =
nsBidiPresUtils::BidiLevelFromStyle(aFrame->StyleContext());
return nsBidiPresUtils::MeasureTextWidth(aString, aLength,
level, presContext, *aContext);
level, presContext, *aContext,
aFontMetrics);
}
aContext->SetTextRunRTL(false);
return aContext->GetWidth(aString, aLength);
aFontMetrics.SetTextRunRTL(false);
return nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
*aContext);
}
/* static */ void
@ -7175,7 +7276,6 @@ nsLayoutUtils::SetBSizeFromFontMetrics(const nsIFrame* aFrame,
nsRefPtr<nsFontMetrics> fm;
float inflation = nsLayoutUtils::FontSizeInflationFor(aFrame);
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm), inflation);
aReflowState.rendContext->SetFont(fm);
if (fm) {
// Compute final height of the frame.

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

@ -8,6 +8,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/ArrayUtils.h"
#include "nsBoundingMetrics.h"
#include "nsChangeHint.h"
#include "nsAutoPtr.h"
#include "nsFrameList.h"
@ -958,6 +959,7 @@ public:
*/
static bool
BinarySearchForPosition(nsRenderingContext* acx,
nsFontMetrics& aFontMetrics,
const char16_t* aText,
int32_t aBaseWidth,
int32_t aBaseInx,
@ -1317,7 +1319,25 @@ public:
static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
nscoord aY, nscoord aAscent);
static nscoord AppUnitWidthOfString(char16_t aC,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext) {
return AppUnitWidthOfString(&aC, 1, aFontMetrics, aContext);
}
static nscoord AppUnitWidthOfString(const nsString& aString,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
static nscoord AppUnitWidthOfString(const char16_t *aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
static void DrawString(const nsIFrame* aFrame,
nsFontMetrics& aFontMetrics,
nsRenderingContext* aContext,
const char16_t* aString,
int32_t aLength,
@ -1330,10 +1350,12 @@ public:
static void DrawUniDirString(const char16_t* aString,
uint32_t aLength,
nsPoint aPoint,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
static nscoord GetStringWidth(const nsIFrame* aFrame,
nsRenderingContext* aContext,
nsFontMetrics& aFontMetrics,
const char16_t* aString,
int32_t aLength);

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

@ -6,6 +6,7 @@
#include "mozilla/DebugOnly.h"
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsTextControlFrame.h"
#include "nsIPlaintextEditor.h"
#include "nsCaret.h"
@ -155,7 +156,6 @@ nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext,
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet),
aFontSizeInflation);
NS_ENSURE_SUCCESS(rv, rv);
aRenderingContext->SetFont(fontMet);
lineHeight =
nsHTMLReflowState::CalcLineHeight(GetContent(), StyleContext(),

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

@ -12,6 +12,7 @@
#include "nsCaret.h"
#include "nsContentUtils.h"
#include "nsCSSAnonBoxes.h"
#include "nsFontMetrics.h"
#include "nsGfxScrollFrame.h"
#include "nsIScrollableFrame.h"
#include "nsLayoutUtils.h"
@ -238,8 +239,7 @@ nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(mFrame));
aCtx->SetFont(fm);
nsLayoutUtils::DrawString(mFrame, aCtx, mStyle->mString.get(),
nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(),
mStyle->mString.Length(), pt);
}
}
@ -763,8 +763,8 @@ TextOverflow::Marker::SetupString(nsIFrame* aFrame)
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(aFrame));
rc->SetFont(fm);
mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, mStyle->mString.get(),
mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, *fm,
mStyle->mString.get(),
mStyle->mString.Length());
}
mIntrinsicISize = mWidth;

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

@ -6,6 +6,7 @@
/* rendering object for HTML <br> elements */
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsFrame.h"
#include "nsPresContext.h"
#include "nsLineLayout.h"
@ -118,7 +119,6 @@ BRFrame::Reflow(nsPresContext* aPresContext,
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(this));
aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed?
if (fm) {
nscoord logicalHeight = aReflowState.CalcLineHeight();
finalSize.BSize(wm) = logicalHeight;

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

@ -18,6 +18,7 @@
#include "nsBlockReflowContext.h"
#include "nsBlockReflowState.h"
#include "nsBulletFrame.h"
#include "nsFontMetrics.h"
#include "nsLineBox.h"
#include "nsLineLayout.h"
#include "nsPlaceholderFrame.h"
@ -2513,7 +2514,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(this));
aState.mReflowState.rendContext->SetFont(fm); // FIXME: needed?
nscoord minAscent =
nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight);
@ -3065,10 +3065,10 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Now compute the collapsed margin-block-start value into
// aState.mPrevBEndMargin, assuming that all child margins
// collapse down to clearanceFrame.
nsBlockReflowContext::ComputeCollapsedBStartMargin(reflowState,
&aState.mPrevBEndMargin,
clearanceFrame,
&mayNeedRetry);
brc.ComputeCollapsedBStartMargin(reflowState,
&aState.mPrevBEndMargin,
clearanceFrame,
&mayNeedRetry);
// XXX optimization; we could check the collapsing children to see if they are sure
// to require clearance, and so avoid retrying them
@ -3101,10 +3101,10 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the collapsed margin again, ignoring the incoming margin this time
mayNeedRetry = false;
nsBlockReflowContext::ComputeCollapsedBStartMargin(reflowState,
&aState.mPrevBEndMargin,
clearanceFrame,
&mayNeedRetry);
brc.ComputeCollapsedBStartMargin(reflowState,
&aState.mPrevBEndMargin,
clearanceFrame,
&mayNeedRetry);
}
}
@ -5855,9 +5855,9 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
floatRS.mDiscoveredClearance = nullptr;
// Only first in flow gets a top margin.
if (!aFloat->GetPrevInFlow()) {
nsBlockReflowContext::ComputeCollapsedBStartMargin(floatRS, &margin,
clearanceFrame,
&mayNeedRetry);
brc.ComputeCollapsedBStartMargin(floatRS, &margin,
clearanceFrame,
&mayNeedRetry);
if (mayNeedRetry && !clearanceFrame) {
floatRS.mDiscoveredClearance = &clearanceFrame;

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

@ -57,8 +57,10 @@ nsBlockReflowContext::ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
bool* aBlockIsEmpty)
{
WritingMode wm = aRS.GetWritingMode();
// Include frame's block-start margin
aMargin->Include(aRS.ComputedLogicalMargin().BStart(wm));
WritingMode parentWM = mMetrics.GetWritingMode();
// Include block-start element of frame's margin
aMargin->Include(aRS.ComputedLogicalMargin().ConvertTo(parentWM, wm).BStart(parentWM));
// The inclusion of the block-end margin when empty is done by the caller
// since it doesn't need to be done by the top-level (non-recursive)
@ -174,8 +176,8 @@ nsBlockReflowContext::ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
if (isEmpty) {
WritingMode innerWM = innerReflowState.GetWritingMode();
LogicalMargin innerMargin =
innerReflowState.ComputedLogicalMargin().ConvertTo(wm, innerWM);
aMargin->Include(innerMargin.BEnd(wm));
innerReflowState.ComputedLogicalMargin().ConvertTo(parentWM, innerWM);
aMargin->Include(innerMargin.BEnd(parentWM));
}
}
if (outerReflowState != &aRS) {

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

@ -54,9 +54,11 @@ public:
}
/**
* Computes the collapsed block-start margin for a block whose reflow state
* is in aRS.
* The computed margin is added into aMargin.
* Computes the collapsed block-start margin (in the context's parent's
* writing mode) for a block whose reflow state is in aRS.
* The computed margin is added into aMargin, whose writing mode is the
* parent's mode as found in mMetrics.GetWritingMode(); note this may not be
* the block's own writing mode as found in aRS.
* If aClearanceFrame is null then this is the first optimistic pass which
* shall assume that no frames have clearance, and we clear the HasClearance
* on all frames encountered.
@ -70,11 +72,11 @@ public:
* We return true if we changed the clearance state of any line and marked it
* dirty.
*/
static bool ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
nsCollapsingMargin* aMargin,
nsIFrame* aClearanceFrame,
bool* aMayNeedRetry,
bool* aIsEmpty = nullptr);
bool ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
nsCollapsingMargin* aMargin,
nsIFrame* aClearanceFrame,
bool* aMayNeedRetry,
bool* aIsEmpty = nullptr);
protected:
nsPresContext* mPresContext;

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

@ -13,6 +13,7 @@
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/MathAlgorithms.h"
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsGkAtoms.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValueInlines.h"
@ -428,7 +429,6 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
GetFontSizeInflation());
GetListItemText(text);
aRenderingContext.SetFont(fm);
nscoord ascent = fm->MaxAscent();
aPt.MoveBy(padding.left, padding.top);
aPt.y = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineY(
@ -437,7 +437,7 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
if (!presContext->BidiEnabled() && HasRTLChars(text)) {
presContext->SetBidiEnabled();
}
nsLayoutUtils::DrawString(this, &aRenderingContext,
nsLayoutUtils::DrawString(this, *fm, &aRenderingContext,
text.get(), text.Length(), aPt);
break;
}
@ -601,9 +601,8 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
default:
GetListItemText(text);
finalSize.BSize(wm) = fm->MaxHeight();
aRenderingContext->SetFont(fm);
finalSize.ISize(wm) =
nsLayoutUtils::GetStringWidth(this, aRenderingContext,
nsLayoutUtils::GetStringWidth(this, aRenderingContext, *fm,
text.get(), text.Length());
aMetrics.SetBlockStartAscent(fm->MaxAscent());
break;
@ -862,7 +861,9 @@ nsBulletFrame::GetSpokenText(nsAString& aText)
bool isBullet;
style->GetSpokenCounterText(mOrdinal, GetWritingMode(), aText, isBullet);
if (isBullet) {
aText.Append(' ');
if (!style->IsNone()) {
aText.Append(' ');
}
} else {
nsAutoString prefix, suffix;
style->GetPrefix(prefix);

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

@ -2167,7 +2167,7 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
!IsSideCaption(frame, mStyleDisplay) &&
mStyleDisplay->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE &&
!flexContainerFrame) {
CalculateBlockSideMargins(AvailableWidth(), ComputedWidth(), aFrameType);
CalculateBlockSideMargins(AvailableISize(), ComputedISize(), aFrameType);
}
}
}
@ -2313,47 +2313,67 @@ nsCSSOffsetState::InitOffsets(nscoord aHorizontalPercentBasis,
//
// Note: the width unit is not auto when this is called
void
nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
nscoord aComputedWidth,
nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailISize,
nscoord aComputedISize,
nsIAtom* aFrameType)
{
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedWidth &&
NS_UNCONSTRAINEDSIZE != aAvailWidth,
"have unconstrained width; this should only result from "
"very large sizes, not attempts at intrinsic width "
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedISize &&
NS_UNCONSTRAINEDSIZE != aAvailISize,
"have unconstrained inline-size; this should only result from "
"very large sizes, not attempts at intrinsic inline-size "
"calculation");
nscoord sum = ComputedPhysicalMargin().left + ComputedPhysicalBorderPadding().left +
aComputedWidth + ComputedPhysicalBorderPadding().right + ComputedPhysicalMargin().right;
if (sum == aAvailWidth)
nscoord sum = ComputedLogicalMargin().IStartEnd(mWritingMode) +
ComputedLogicalBorderPadding().IStartEnd(mWritingMode) + aComputedISize;
if (sum == aAvailISize) {
// The sum is already correct
return;
}
// Determine the left and right margin values. The width value
// Determine the start and end margin values. The isize value
// remains constant while we do this.
// Calculate how much space is available for margins
nscoord availMarginSpace = aAvailWidth - sum;
nscoord availMarginSpace = aAvailISize - sum;
LogicalMargin margin = ComputedLogicalMargin();
// If the available margin space is negative, then don't follow the
// usual overconstraint rules.
if (availMarginSpace < 0) {
if (mCBReflowState &&
mCBReflowState->mStyleVisibility->mDirection == NS_STYLE_DIRECTION_RTL) {
ComputedPhysicalMargin().left += availMarginSpace;
mCBReflowState->GetWritingMode().IsBidiLTR() !=
mWritingMode.IsBidiLTR()) {
margin.IStart(mWritingMode) += availMarginSpace;
} else {
ComputedPhysicalMargin().right += availMarginSpace;
margin.IEnd(mWritingMode) += availMarginSpace;
}
SetComputedLogicalMargin(margin);
return;
}
// The css2 spec clearly defines how block elements should behave
// in section 10.3.3.
bool isAutoLeftMargin =
eStyleUnit_Auto == mStyleMargin->mMargin.GetLeftUnit();
bool isAutoRightMargin =
eStyleUnit_Auto == mStyleMargin->mMargin.GetRightUnit();
if (!isAutoLeftMargin && !isAutoRightMargin) {
bool isAutoStartMargin, isAutoEndMargin;
const nsStyleSides& styleSides = mStyleMargin->mMargin;
if (mWritingMode.IsVertical()) {
if (mWritingMode.IsBidiLTR()) {
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
} else {
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
}
} else {
if (mWritingMode.IsBidiLTR()) {
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
} else {
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
}
}
if (!isAutoStartMargin && !isAutoEndMargin) {
// Neither margin is 'auto' so we're over constrained. Use the
// 'direction' property of the parent to tell which margin to
// ignore
@ -2370,19 +2390,27 @@ nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
(prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)) {
isAutoLeftMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
isAutoRightMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
if (prs->mWritingMode.IsBidiLTR()) {
isAutoStartMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
isAutoEndMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
} else {
isAutoStartMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
isAutoEndMargin =
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
}
}
// Otherwise apply the CSS rules, and ignore one margin by forcing
// it to 'auto', depending on 'direction'.
else if (mCBReflowState &&
NS_STYLE_DIRECTION_RTL == mCBReflowState->mStyleVisibility->mDirection) {
isAutoLeftMargin = true;
mCBReflowState->GetWritingMode().IsBidiLTR() !=
mWritingMode.IsBidiLTR()) {
isAutoStartMargin = true;
}
else {
isAutoRightMargin = true;
isAutoEndMargin = true;
}
}
@ -2390,18 +2418,19 @@ nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
// The computed margins need not be zero because the 'auto' could come from
// overconstraint or from HTML alignment so values need to be accumulated
if (isAutoLeftMargin) {
if (isAutoRightMargin) {
if (isAutoStartMargin) {
if (isAutoEndMargin) {
// Both margins are 'auto' so the computed addition should be equal
nscoord forLeft = availMarginSpace / 2;
ComputedPhysicalMargin().left += forLeft;
ComputedPhysicalMargin().right += availMarginSpace - forLeft;
nscoord forStart = availMarginSpace / 2;
margin.IStart(mWritingMode) += forStart;
margin.IEnd(mWritingMode) += availMarginSpace - forStart;
} else {
ComputedPhysicalMargin().left += availMarginSpace;
margin.IStart(mWritingMode) += availMarginSpace;
}
} else if (isAutoRightMargin) {
ComputedPhysicalMargin().right += availMarginSpace;
} else if (isAutoEndMargin) {
margin.IEnd(mWritingMode) += availMarginSpace;
}
SetComputedLogicalMargin(margin);
}
#define NORMAL_LINE_HEIGHT_FACTOR 1.2f // in term of emHeight

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

@ -117,13 +117,20 @@ public:
nsMargin& ComputedPhysicalBorderPadding() { return mComputedBorderPadding; }
nsMargin& ComputedPhysicalPadding() { return mComputedPadding; }
LogicalMargin ComputedLogicalMargin() const
const LogicalMargin ComputedLogicalMargin() const
{ return LogicalMargin(mWritingMode, mComputedMargin); }
LogicalMargin ComputedLogicalBorderPadding() const
const LogicalMargin ComputedLogicalBorderPadding() const
{ return LogicalMargin(mWritingMode, mComputedBorderPadding); }
LogicalMargin ComputedLogicalPadding() const
const LogicalMargin ComputedLogicalPadding() const
{ return LogicalMargin(mWritingMode, mComputedPadding); }
void SetComputedLogicalMargin(const LogicalMargin& aMargin)
{ mComputedMargin = aMargin.GetPhysicalMargin(mWritingMode); }
void SetComputedLogicalBorderPadding(const LogicalMargin& aMargin)
{ mComputedBorderPadding = aMargin.GetPhysicalMargin(mWritingMode); }
void SetComputedLogicalPadding(const LogicalMargin& aMargin)
{ mComputedPadding = aMargin.GetPhysicalMargin(mWritingMode); }
WritingMode GetWritingMode() const { return mWritingMode; }
protected:
@ -803,8 +810,8 @@ protected:
nscoord* aInsideBoxSizing,
nscoord* aOutsideBoxSizing);
void CalculateBlockSideMargins(nscoord aAvailWidth,
nscoord aComputedWidth,
void CalculateBlockSideMargins(nscoord aAvailISize,
nscoord aComputedISize,
nsIAtom* aFrameType);
};

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

@ -17,6 +17,7 @@
#include "mozilla/MouseEvents.h"
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsIImageLoadingContent.h"
#include "nsString.h"
#include "nsPrintfCString.h"
@ -1012,11 +1013,12 @@ nsImageFrame::MeasureString(const char16_t* aString,
int32_t aLength,
nscoord aMaxWidth,
uint32_t& aMaxFit,
nsRenderingContext& aContext)
nsRenderingContext& aContext,
nsFontMetrics& aFontMetrics)
{
nscoord totalWidth = 0;
aContext.FontMetrics()->SetTextRunRTL(false);
nscoord spaceWidth = aContext.FontMetrics()->SpaceWidth();
aFontMetrics.SetTextRunRTL(false);
nscoord spaceWidth = aFontMetrics.SpaceWidth();
aMaxFit = 0;
while (aLength > 0) {
@ -1033,7 +1035,7 @@ nsImageFrame::MeasureString(const char16_t* aString,
// Measure this chunk of text, and see if it fits
nscoord width =
nsLayoutUtils::GetStringWidth(this, &aContext, aString, len);
nsLayoutUtils::GetStringWidth(this, &aContext, aFontMetrics, aString, len);
bool fits = (totalWidth + width) <= aMaxWidth;
// If it fits on the line, or it's the first word we've processed then
@ -1080,7 +1082,6 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(this));
aRenderingContext.SetFont(fm);
// Format the text to display within the formatting rect
@ -1105,7 +1106,7 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
// Determine how much of the text to display on this line
uint32_t maxFit; // number of characters that fit
nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
aRenderingContext);
aRenderingContext, *fm);
// Display the text
nsresult rv = NS_ERROR_FAILURE;
@ -1115,17 +1116,17 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
aPresContext, aRenderingContext,
aRenderingContext,
aRenderingContext, *fm,
aRect.XMost() - strWidth, y + maxAscent);
else
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
aPresContext, aRenderingContext,
aRenderingContext,
aRenderingContext, *fm,
aRect.x, y + maxAscent);
}
if (NS_FAILED(rv)) {
nsLayoutUtils::DrawUniDirString(str, maxFit,
nsPoint(aRect.x, y + maxAscent),
nsPoint(aRect.x, y + maxAscent), *fm,
aRenderingContext);
}

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

@ -21,6 +21,7 @@
#include "nsIReflowCallback.h"
#include "nsTObserverArray.h"
class nsFontMetrics;
class nsImageMap;
class nsIURI;
class nsILoadGroup;
@ -205,7 +206,8 @@ protected:
int32_t aLength,
nscoord aMaxWidth,
uint32_t& aMaxFit,
nsRenderingContext& aContext);
nsRenderingContext& aContext,
nsFontMetrics& aFontMetrics);
void DisplayAltText(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,

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

@ -12,6 +12,7 @@
#include "SVGTextFrame.h"
#include "nsBlockFrame.h"
#include "nsFontMetrics.h"
#include "nsStyleConsts.h"
#include "nsContainerFrame.h"
#include "nsFloatManager.h"
@ -1101,16 +1102,16 @@ nsLineLayout::AllowForStartMargin(PerFrameData* pfd,
// the frame we will properly avoid adding in the starting margin.
pfd->mMargin.IStart(frameWM) = 0;
} else {
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableWidth(),
"have unconstrained width; this should only result from "
"very large sizes, not attempts at intrinsic width "
"calculation");
if (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth()) {
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableISize(),
"have unconstrained inline-size; this should only result "
"from very large sizes, not attempts at intrinsic "
"inline-size calculation");
if (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedISize()) {
// For inline-ish and text-ish things (which don't compute widths
// in the reflow state), adjust available width to account for the
// in the reflow state), adjust available inline-size to account for the
// start margin. The end margin will be accounted for when we
// finish flowing the frame.
aReflowState.AvailableWidth() -= pfd->mMargin.IStart(frameWM);
aReflowState.AvailableISize() -= pfd->mMargin.IStart(frameWM);
}
}
}
@ -1589,7 +1590,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
GetInflationForBlockDirAlignment(spanFrame, mInflationMinFontSize);
nsLayoutUtils::GetFontMetricsForFrame(spanFrame, getter_AddRefs(fm),
inflation);
mBlockReflowState->rendContext->SetFont(fm);
bool preMode = mStyleText->WhiteSpaceIsSignificant();

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

@ -7,6 +7,7 @@
#include "mozilla/gfx/2D.h"
#include "nsDeviceContext.h"
#include "nsFontMetrics.h"
#include "nsLayoutUtils.h"
#include "nsPresContext.h"
#include "nsRenderingContext.h"
@ -236,12 +237,14 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
//------------------------------------------------------------------------------
nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
const nsRect& aRect,
int32_t aJust,
const nsString& aStr)
{
nscoord width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
aFontMetrics,
aStr.get(), aStr.Length());
nscoord x = aRect.x;
@ -273,6 +276,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
// @param aHeight - the height of the font
void
nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
nsHeaderFooterEnum aHeaderFooter,
const nsString& aStrLeft,
const nsString& aStrCenter,
@ -290,17 +294,17 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
nscoord strSpace = aRect.width / numStrs;
if (!aStrLeft.IsEmpty()) {
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
nsIPrintSettings::kJustLeft, aStrLeft, aRect, aAscent,
aHeight, strSpace);
}
if (!aStrCenter.IsEmpty()) {
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
nsIPrintSettings::kJustCenter, aStrCenter, aRect, aAscent,
aHeight, strSpace);
}
if (!aStrRight.IsEmpty()) {
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
nsIPrintSettings::kJustRight, aStrRight, aRect, aAscent,
aHeight, strSpace);
}
@ -317,6 +321,7 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
// @param aWidth - available width for the string
void
nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
nsHeaderFooterEnum aHeaderFooter,
int32_t aJust,
const nsString& aStr,
@ -342,7 +347,8 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
return; // bail is empty string
}
// find how much text fits, the "position" is the size of the available area
if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, text, 0, 0, 0, len,
if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, aFontMetrics,
text, 0, 0, 0, len,
int32_t(contentWidth), indx, textWidth)) {
if (indx < len-1 ) {
// we can't fit in all the text
@ -369,7 +375,7 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
}
// cacl the x and y positions of the text
nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
nscoord x = GetXPosition(aRenderingContext, aFontMetrics, aRect, aJust, str);
nscoord y;
if (aHeaderFooter == eHeader) {
y = aRect.y + mPD->mEdgePaperMargin.top;
@ -385,7 +391,9 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
gfx->Clip(NSRectToSnappedRect(aRect, PresContext()->AppUnitsPerDevPixel(),
*drawTarget));
aRenderingContext.ThebesContext()->SetColor(NS_RGB(0,0,0));
nsLayoutUtils::DrawString(this, &aRenderingContext, str.get(), str.Length(), nsPoint(x, y + aAscent));
nsLayoutUtils::DrawString(this, aFontMetrics, &aRenderingContext,
str.get(), str.Length(),
nsPoint(x, y + aAscent));
gfx->Restore();
}
}
@ -597,8 +605,6 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
pc->GetTextPerfMetrics(),
*getter_AddRefs(fontMet));
aRenderingContext.SetFont(fontMet);
nscoord ascent = 0;
nscoord visibleHeight = 0;
if (fontMet) {
@ -611,7 +617,7 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft));
mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter));
mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight));
DrawHeaderFooter(aRenderingContext, eHeader,
DrawHeaderFooter(aRenderingContext, *fontMet, eHeader,
headerLeft, headerCenter, headerRight,
rect, ascent, visibleHeight);
@ -619,7 +625,7 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft));
mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter));
mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight));
DrawHeaderFooter(aRenderingContext, eFooter,
DrawHeaderFooter(aRenderingContext, *fontMet, eFooter,
footerLeft, footerCenter, footerRight,
rect, ascent, visibleHeight);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше