зеркало из https://github.com/mozilla/gecko-dev.git
Merge b2g-inbound to m-c.
This commit is contained in:
Коммит
1e0482e1c1
|
@ -30,6 +30,10 @@ function LOG(s) {
|
||||||
dump("== Payment flow == " + s + "\n");
|
dump("== Payment flow == " + s + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LOGE(s) {
|
||||||
|
dump("== Payment flow ERROR == " + s + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (_debug) {
|
if (_debug) {
|
||||||
LOG("Frame script injected");
|
LOG("Frame script injected");
|
||||||
}
|
}
|
||||||
|
@ -43,6 +47,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||||
"nsIUUIDGenerator");
|
"nsIUUIDGenerator");
|
||||||
|
|
||||||
#ifdef MOZ_B2G_RIL
|
#ifdef MOZ_B2G_RIL
|
||||||
|
Cu.import('resource://gre/modules/ObjectWrapper.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "gRil",
|
||||||
|
"@mozilla.org/ril;1",
|
||||||
|
"nsIRadioInterfaceLayer");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
|
XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
|
||||||
"@mozilla.org/ril/content-helper;1",
|
"@mozilla.org/ril/content-helper;1",
|
||||||
"nsIIccProvider");
|
"nsIIccProvider");
|
||||||
|
@ -59,6 +69,7 @@ const kSilentSmsReceivedTopic = "silent-sms-received";
|
||||||
const kMozSettingsChangedObserverTopic = "mozsettings-changed";
|
const kMozSettingsChangedObserverTopic = "mozsettings-changed";
|
||||||
|
|
||||||
const kRilDefaultDataServiceId = "ril.data.defaultServiceId";
|
const kRilDefaultDataServiceId = "ril.data.defaultServiceId";
|
||||||
|
const kRilDefaultPaymentServiceId = "ril.payment.defaultServiceId";
|
||||||
|
|
||||||
const MOBILEMESSAGECALLBACK_CID =
|
const MOBILEMESSAGECALLBACK_CID =
|
||||||
Components.ID("{b484d8c9-6be4-4f94-ab60-c9c7ebcc853d}");
|
Components.ID("{b484d8c9-6be4-4f94-ab60-c9c7ebcc853d}");
|
||||||
|
@ -71,8 +82,8 @@ function SilentSmsRequest() {
|
||||||
|
|
||||||
SilentSmsRequest.prototype = {
|
SilentSmsRequest.prototype = {
|
||||||
__exposedProps__: {
|
__exposedProps__: {
|
||||||
onsuccess: 'rw',
|
onsuccess: "rw",
|
||||||
onerror: 'rw'
|
onerror: "rw"
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileMessageCallback]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileMessageCallback]),
|
||||||
|
@ -95,33 +106,69 @@ SilentSmsRequest.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
notifySendMessageFailed: function notifySendMessageFailed(aError) {
|
notifySendMessageFailed: function notifySendMessageFailed(aError) {
|
||||||
if (_debug) {
|
LOGE("Error sending silent message " + aError);
|
||||||
LOG("Error sending silent message " + aError);
|
|
||||||
}
|
|
||||||
this._onerror(aError);
|
this._onerror(aError);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function PaymentSettings() {
|
function PaymentSettings() {
|
||||||
this.dataServiceId = 0;
|
|
||||||
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
|
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
|
||||||
gSettingsService.createLock().get(kRilDefaultDataServiceId, this);
|
|
||||||
|
[kRilDefaultDataServiceId, kRilDefaultPaymentServiceId].forEach(setting => {
|
||||||
|
gSettingsService.createLock().get(setting, this);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
PaymentSettings.prototype = {
|
PaymentSettings.prototype = {
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISettingsServiceCallback,
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISettingsServiceCallback,
|
||||||
Ci.nsIObserver]),
|
Ci.nsIObserver]),
|
||||||
|
|
||||||
|
dataServiceId: 0,
|
||||||
|
_paymentServiceId: 0,
|
||||||
|
|
||||||
|
get paymentServiceId() {
|
||||||
|
return this._paymentServiceId;
|
||||||
|
},
|
||||||
|
|
||||||
|
set paymentServiceId(serviceId) {
|
||||||
|
// We allow the payment provider to set the service ID that will be used
|
||||||
|
// for the payment process.
|
||||||
|
// This service ID will be the one used by the silent SMS flow.
|
||||||
|
// If the payment is done with an external SIM, the service ID must be set
|
||||||
|
// to null.
|
||||||
|
if (serviceId != null && serviceId >= gRil.numRadioInterfaces) {
|
||||||
|
LOGE("Invalid service ID " + serviceId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSettingsService.createLock().set(kRilDefaultPaymentServiceId,
|
||||||
|
serviceId, null);
|
||||||
|
this._paymentServiceId = serviceId;
|
||||||
|
},
|
||||||
|
|
||||||
|
setServiceId: function(aName, aValue) {
|
||||||
|
switch (aName) {
|
||||||
|
case kRilDefaultDataServiceId:
|
||||||
|
this.dataServiceId = aValue;
|
||||||
|
if (_debug) {
|
||||||
|
LOG("dataServiceId " + this.dataServiceId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kRilDefaultPaymentServiceId:
|
||||||
|
this._paymentServiceId = aValue;
|
||||||
|
if (_debug) {
|
||||||
|
LOG("paymentServiceId " + this._paymentServiceId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
handle: function(aName, aValue) {
|
handle: function(aName, aValue) {
|
||||||
if (aName != kRilDefaultDataServiceId) {
|
if (aName != kRilDefaultDataServiceId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dataServiceId = aValue;
|
this.setServiceId(aName, aValue);
|
||||||
|
|
||||||
if (_debug) {
|
|
||||||
LOG("dataServiceId " + this.dataServiceId);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
observe: function(aSubject, aTopic, aData) {
|
observe: function(aSubject, aTopic, aData) {
|
||||||
|
@ -131,21 +178,15 @@ PaymentSettings.prototype = {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let setting = JSON.parse(aData);
|
let setting = JSON.parse(aData);
|
||||||
if (!setting.key || setting.key !== kRilDefaultDataServiceId) {
|
if (!setting.key ||
|
||||||
|
(setting.key !== kRilDefaultDataServiceId &&
|
||||||
|
setting.key !== kRilDefaultPaymentServiceId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.setServiceId(setting.key, setting.value);
|
||||||
this.dataServiceId = setting.value;
|
|
||||||
|
|
||||||
if (_debug) {
|
|
||||||
LOG("dataServiceId " + setting.value);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (_debug) {
|
LOGE(e);
|
||||||
LOG(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
cleanup: function() {
|
cleanup: function() {
|
||||||
|
@ -163,19 +204,18 @@ let gBrowser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
let PaymentProvider = {
|
let PaymentProvider = {
|
||||||
#ifdef MOZ_B2G_RIL
|
#ifdef MOZ_B2G_RIL
|
||||||
__exposedProps__: {
|
__exposedProps__: {
|
||||||
paymentSuccess: 'r',
|
paymentSuccess: "r",
|
||||||
paymentFailed: 'r',
|
paymentFailed: "r",
|
||||||
iccIds: 'r',
|
paymentServiceId: "rw",
|
||||||
mcc: 'r',
|
iccInfo: "r",
|
||||||
mnc: 'r',
|
sendSilentSms: "r",
|
||||||
sendSilentSms: 'r',
|
observeSilentSms: "r",
|
||||||
observeSilentSms: 'r',
|
removeSilentSmsObserver: "r"
|
||||||
removeSilentSmsObserver: 'r'
|
|
||||||
},
|
},
|
||||||
#else
|
#else
|
||||||
__exposedProps__: {
|
__exposedProps__: {
|
||||||
paymentSuccess: 'r',
|
paymentSuccess: "r",
|
||||||
paymentFailed: 'r'
|
paymentFailed: "r"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -242,9 +282,7 @@ let PaymentProvider = {
|
||||||
},
|
},
|
||||||
|
|
||||||
paymentFailed: function paymentFailed(aErrorMsg) {
|
paymentFailed: function paymentFailed(aErrorMsg) {
|
||||||
if (_debug) {
|
LOGE("paymentFailed " + aErrorMsg);
|
||||||
LOG("paymentFailed " + aErrorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
PaymentProvider._closePaymentFlowDialog(function notifyError() {
|
PaymentProvider._closePaymentFlowDialog(function notifyError() {
|
||||||
if (!gRequestId) {
|
if (!gRequestId) {
|
||||||
|
@ -256,22 +294,45 @@ let PaymentProvider = {
|
||||||
},
|
},
|
||||||
|
|
||||||
#ifdef MOZ_B2G_RIL
|
#ifdef MOZ_B2G_RIL
|
||||||
// Bug 938993. Support Multi-SIM for Payments.
|
get paymentServiceId() {
|
||||||
|
return this._settings.paymentServiceId;
|
||||||
|
},
|
||||||
|
|
||||||
|
set paymentServiceId(serviceId) {
|
||||||
|
this._settings.paymentServiceId = serviceId;
|
||||||
|
},
|
||||||
|
|
||||||
|
// We expose to the payment provider the information of all the SIMs
|
||||||
|
// available in the device. iccInfo is an object of this form:
|
||||||
|
// {
|
||||||
|
// "serviceId1": {
|
||||||
|
// mcc: <string>,
|
||||||
|
// mnc: <string>,
|
||||||
|
// iccId: <string>,
|
||||||
|
// dataPrimary: <boolean>
|
||||||
|
// },
|
||||||
|
// "serviceIdN": {...}
|
||||||
|
// }
|
||||||
get iccInfo() {
|
get iccInfo() {
|
||||||
delete this.iccInfo;
|
if (!this._iccInfo) {
|
||||||
return this.iccInfo = iccProvider.getIccInfo(this._settings.dataServiceId);
|
this._iccInfo = {};
|
||||||
},
|
for (let i = 0; i < gRil.numRadioInterfaces; i++) {
|
||||||
|
let info = iccProvider.getIccInfo(i);
|
||||||
|
if (!info) {
|
||||||
|
LOGE("Tried to get the ICC info for an invalid service ID " + i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
get iccIds() {
|
this._iccInfo[i] = {
|
||||||
return [this.iccInfo.iccid];
|
iccId: info.iccid,
|
||||||
},
|
mcc: info.mcc,
|
||||||
|
mnc: info.mnc,
|
||||||
|
dataPrimary: i == this._settings.dataServiceId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get mcc() {
|
return ObjectWrapper.wrap(this._iccInfo, content);
|
||||||
return [this.iccInfo.mcc];
|
|
||||||
},
|
|
||||||
|
|
||||||
get mnc() {
|
|
||||||
return [this.iccInfo.mnc];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_silentNumbers: null,
|
_silentNumbers: null,
|
||||||
|
@ -283,7 +344,21 @@ let PaymentProvider = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = new SilentSmsRequest();
|
let request = new SilentSmsRequest();
|
||||||
smsService.send(aNumber, aMessage, true, request);
|
|
||||||
|
if (this._settings.paymentServiceId === null) {
|
||||||
|
LOGE("No payment service ID set. Cannot send silent SMS");
|
||||||
|
let runnable = {
|
||||||
|
run: function run() {
|
||||||
|
request.notifySendMessageFailed("NO_PAYMENT_SERVICE_ID");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Services.tm.currentThread.dispatch(runnable,
|
||||||
|
Ci.nsIThread.DISPATCH_NORMAL);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
smsService.send(this._settings.paymentServiceId, aNumber, aMessage, true,
|
||||||
|
request);
|
||||||
return request;
|
return request;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -349,6 +424,21 @@ let PaymentProvider = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the service ID is null it means that the payment provider asked the
|
||||||
|
// user for her MSISDN, so we are in a MT only SMS auth flow. In this case
|
||||||
|
// we manually set the service ID to the one corresponding with the SIM
|
||||||
|
// that received the SMS.
|
||||||
|
if (this._settings.paymentServiceId === null) {
|
||||||
|
let i = 0;
|
||||||
|
while(i < gRil.numRadioInterfaces) {
|
||||||
|
if (this.iccInfo[i].iccId === aSubject.iccId) {
|
||||||
|
this._settings.paymentServiceId = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._silentSmsObservers[number].forEach(function(callback) {
|
this._silentSmsObservers[number].forEach(function(callback) {
|
||||||
callback(aSubject);
|
callback(aSubject);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||||
|
const { Services } = Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
|
var processId;
|
||||||
|
|
||||||
|
function peekChildId(aSubject, aTopic, aData) {
|
||||||
|
Services.obs.removeObserver(peekChildId, 'recording-device-events');
|
||||||
|
Services.obs.removeObserver(peekChildId, 'recording-device-ipc-events');
|
||||||
|
let props = aSubject.QueryInterface(Ci.nsIPropertyBag2);
|
||||||
|
if (props.hasKey('childID')) {
|
||||||
|
processId = props.get('childID');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageListener('init-chrome-event', function(message) {
|
||||||
|
// listen mozChromeEvent and forward to content process.
|
||||||
|
let browser = Services.wm.getMostRecentWindow('navigator:browser');
|
||||||
|
let type = message.type;
|
||||||
|
browser.addEventListener('mozChromeEvent', function(event) {
|
||||||
|
let details = event.detail;
|
||||||
|
if (details.type === type) {
|
||||||
|
sendAsyncMessage('chrome-event', details);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
Services.obs.addObserver(peekChildId, 'recording-device-events', false);
|
||||||
|
Services.obs.addObserver(peekChildId, 'recording-device-ipc-events', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
addMessageListener('fake-content-shutdown', function(message) {
|
||||||
|
let props = Cc["@mozilla.org/hash-property-bag;1"]
|
||||||
|
.createInstance(Ci.nsIWritablePropertyBag2);
|
||||||
|
if (processId) {
|
||||||
|
props.setPropertyAsUint64('childID', processId);
|
||||||
|
}
|
||||||
|
Services.obs.notifyObservers(props, 'recording-device-ipc-events', 'content-shutdown');
|
||||||
|
});
|
|
@ -0,0 +1,82 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// resolve multiple promise in parallel
|
||||||
|
function expectAll(aValue) {
|
||||||
|
let deferred = new Promise(function(resolve, reject) {
|
||||||
|
let countdown = aValue.length;
|
||||||
|
let resolutionValues = new Array(countdown);
|
||||||
|
|
||||||
|
for (let i = 0; i < aValue.length; i++) {
|
||||||
|
let index = i;
|
||||||
|
aValue[i].then(function(val) {
|
||||||
|
resolutionValues[index] = val;
|
||||||
|
if (--countdown === 0) {
|
||||||
|
resolve(resolutionValues);
|
||||||
|
}
|
||||||
|
}, reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TestInit() {
|
||||||
|
let url = SimpleTest.getTestFileURL("RecordingStatusChromeScript.js")
|
||||||
|
let script = SpecialPowers.loadChromeScript(url);
|
||||||
|
|
||||||
|
let helper = {
|
||||||
|
finish: function () {
|
||||||
|
script.destroy();
|
||||||
|
},
|
||||||
|
fakeShutdown: function () {
|
||||||
|
script.sendAsyncMessage('fake-content-shutdown', {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
script.addMessageListener('chrome-event', function (message) {
|
||||||
|
if (helper.hasOwnProperty('onEvent')) {
|
||||||
|
helper.onEvent(message);
|
||||||
|
} else {
|
||||||
|
ok(false, 'unexpected message: ' + JSON.stringify(message));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
script.sendAsyncMessage("init-chrome-event", {
|
||||||
|
type: 'recording-status'
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.resolve(helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectEvent(expected, eventHelper) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
eventHelper.onEvent = function(message) {
|
||||||
|
delete eventHelper.onEvent;
|
||||||
|
ok(message, JSON.stringify(message));
|
||||||
|
is(message.type, 'recording-status', 'event type: ' + message.type);
|
||||||
|
is(message.active, expected.active, 'recording active: ' + message.active);
|
||||||
|
is(message.isAudio, expected.isAudio, 'audio recording active: ' + message.isAudio);
|
||||||
|
is(message.isVideo, expected.isVideo, 'video recording active: ' + message.isVideo);
|
||||||
|
resolve(eventHelper);
|
||||||
|
};
|
||||||
|
info('waiting for recording-status');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectStream(params, callback) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var req = navigator.mozGetUserMedia(
|
||||||
|
params,
|
||||||
|
function(stream) {
|
||||||
|
ok(true, 'create media stream');
|
||||||
|
callback(stream);
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
ok(false, 'fail to create media stream');
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
info('waiting for gUM result');
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Iframe for Recording Status</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="RecordingStatusHelper.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
|
||||||
|
var localStream;
|
||||||
|
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
switch (event.data) {
|
||||||
|
case 'start':
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStream = stream;
|
||||||
|
event.source.postMessage('start-finished', window.location.origin);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
localStream.stop();
|
||||||
|
localStream = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,10 @@
|
||||||
|
[DEFAULT]
|
||||||
|
support-files =
|
||||||
|
RecordingStatusChromeScript.js
|
||||||
|
RecordingStatusHelper.js
|
||||||
|
file_getusermedia_iframe.html
|
||||||
|
|
||||||
|
[test_recordingStatus_basic.html]
|
||||||
|
[test_recordingStatus_multiple_requests.html]
|
||||||
|
[test_recordingStatus_iframe.html]
|
||||||
|
[test_recordingStatus_kill_content_process.html]
|
|
@ -0,0 +1,7 @@
|
||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
MOCHITEST_MANIFESTS += ['mochitest.ini']
|
|
@ -0,0 +1,121 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for Recording Status</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="RecordingStatusHelper.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let localStreams = [];
|
||||||
|
TestInit().then(function(eventHelper) {
|
||||||
|
/* step 1: create one audio stream
|
||||||
|
* expect: see one mozChromeEvent for audio recording start.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 2: close the audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false,
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop audio stream');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
/* step 3: create one video stream
|
||||||
|
* expect: see one mozChromeEvent for video recording start
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: true
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ video: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 4: close the audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false,
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop video stream');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
/* step 3: create one audio/video stream
|
||||||
|
* expect: see one mozChromeEvent for audio/video recording start
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: true
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
video: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 4: close the audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false,
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop audio/video stream');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
eventHelper.finish();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure Promise API is enabled
|
||||||
|
SpecialPowers.pushPrefEnv({
|
||||||
|
"set": [
|
||||||
|
["dom.promise.enabled", true],
|
||||||
|
['media.navigator.permission.disabled', true]
|
||||||
|
]
|
||||||
|
}, test);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,73 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for Recording Status in iframe</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="RecordingStatusHelper.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<iframe id="gum-iframe"></iframe>
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
TestInit().then(function(eventHelper) {
|
||||||
|
/* step 1: load iframe whilch creates audio stream
|
||||||
|
* expect: see one mozChromeEvent for audio recording start.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let loadDeferred = new Promise(function(resolve, reject) {
|
||||||
|
let gumIframe = document.getElementById('gum-iframe');
|
||||||
|
gumIframe.src = 'file_getusermedia_iframe.html';
|
||||||
|
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
if (event.data === 'start-finished') {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
gumIframe.onload = function() {
|
||||||
|
info('start audio stream in iframe');
|
||||||
|
gumIframe.contentWindow.postMessage('start', window.location.origin);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, loadDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 2: close the audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let win = document.getElementById('gum-iframe').contentWindow;
|
||||||
|
win.postMessage('stop', window.location.origin);
|
||||||
|
info('stop audio stream in iframe');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
eventHelper.finish();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure Promise API is enabled
|
||||||
|
SpecialPowers.pushPrefEnv({
|
||||||
|
"set": [
|
||||||
|
["dom.promise.enabled", true],
|
||||||
|
['media.navigator.permission.disabled', true]
|
||||||
|
]
|
||||||
|
}, test);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,74 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for Recording Status after process shutdown</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="RecordingStatusHelper.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let localStreams = [];
|
||||||
|
TestInit().then(function(eventHelper) {
|
||||||
|
/* step 1: load iframe whilch creates audio stream
|
||||||
|
* expect: see one mozChromeEvent for audio recording start.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) { localStreams.push(stream); });
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 2: create video stream
|
||||||
|
* expect: see one mozChromeEvent for audio recording start.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: true
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ video: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) { localStreams.push(stream); });
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 3: close the audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
eventHelper.fakeShutdown();
|
||||||
|
info('simulate content process been killed');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
eventHelper.finish();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure Promise API is enabled
|
||||||
|
SpecialPowers.pushPrefEnv({
|
||||||
|
"set": [
|
||||||
|
["dom.promise.enabled", true],
|
||||||
|
['media.navigator.permission.disabled', true]
|
||||||
|
]
|
||||||
|
}, test);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,110 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for Recording Status with multiple gUM requests</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="RecordingStatusHelper.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let localStreams = [];
|
||||||
|
TestInit().then(function(eventHelper) {
|
||||||
|
/* step 1: create one audio stream
|
||||||
|
* expect: see one mozChromeEvent for recording start.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 2: create another audio stream
|
||||||
|
* expect: no mozChromeEvent after audio stream is created
|
||||||
|
*/
|
||||||
|
let gumDeferred = expectStream({ audio: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([Promise.resolve(eventHelper), gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 3: create video stream
|
||||||
|
* expect: see one mozChromeEvent for recording start
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: true,
|
||||||
|
isVideo: true
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
let gumDeferred = expectStream({ video: true,
|
||||||
|
fake: true
|
||||||
|
}, function(stream) {
|
||||||
|
localStreams.push(stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
return expectAll([eventDeferred, gumDeferred]);
|
||||||
|
}).then(function([eventHelper]) {
|
||||||
|
/* step 4: stop first audio stream
|
||||||
|
* expect: no mozChromeEvent after first audio stream is stopped
|
||||||
|
*/
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop the first audio stream');
|
||||||
|
return Promise.resolve(eventHelper);
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
/* step 5: stop the second audio stream
|
||||||
|
* expect: see one mozChromeEvent for audio recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: true,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: true
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop the second audio stream');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
/* step 6: stop the video stream
|
||||||
|
* expect: see one mozChromeEvent for video recording stop.
|
||||||
|
*/
|
||||||
|
let eventDeferred = expectEvent({ active: false,
|
||||||
|
isAudio: false,
|
||||||
|
isVideo: false
|
||||||
|
}, eventHelper);
|
||||||
|
|
||||||
|
localStreams.shift().stop();
|
||||||
|
info('stop the video stream');
|
||||||
|
return eventDeferred;
|
||||||
|
}).then(function(eventHelper) {
|
||||||
|
eventHelper.finish();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure Promise API is enabled
|
||||||
|
SpecialPowers.pushPrefEnv({
|
||||||
|
"set": [
|
||||||
|
["dom.promise.enabled", true],
|
||||||
|
['media.navigator.permission.disabled', true]
|
||||||
|
]
|
||||||
|
}, test);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -8,4 +8,6 @@ DEFINES['AB_CD'] = CONFIG['MOZ_UI_LOCALE']
|
||||||
DEFINES['PACKAGE'] = 'browser'
|
DEFINES['PACKAGE'] = 'browser'
|
||||||
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
||||||
|
|
||||||
JAR_MANIFESTS += ['jar.mn']
|
JAR_MANIFESTS += ['jar.mn']
|
||||||
|
|
||||||
|
TEST_DIRS += ['content/test/mochitest']
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"revision": "5116c92a2905f6646d7049ddd1e1ab68eeb278d9",
|
"revision": "407993cc2cef77f8c8d0415f11996889ed18dc56",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f382061fe95750d584a9078175c421a36892afc9"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -7035,7 +7035,7 @@ if test "$OS_TARGET" = Android; then
|
||||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=memswap,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
|
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=memswap,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
|
||||||
fi
|
fi
|
||||||
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
|
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
|
||||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=__pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2"
|
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=__pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2,--wrap=tgkill"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -2693,7 +2693,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
|
||||||
|
|
||||||
AppDownloadManager.remove(aNewApp.manifestURL);
|
AppDownloadManager.remove(aNewApp.manifestURL);
|
||||||
|
|
||||||
return [id, newManifest];
|
return [oldApp.id, newManifest];
|
||||||
|
|
||||||
}).bind(this)).then(
|
}).bind(this)).then(
|
||||||
aOnSuccess,
|
aOnSuccess,
|
||||||
|
@ -3150,7 +3150,8 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
|
||||||
aOldApp.appStatus = AppsUtils.getAppManifestStatus(newManifest);
|
aOldApp.appStatus = AppsUtils.getAppManifestStatus(newManifest);
|
||||||
|
|
||||||
this._saveEtag(aIsUpdate, aOldApp, aRequestChannel, aHash, newManifest);
|
this._saveEtag(aIsUpdate, aOldApp, aRequestChannel, aHash, newManifest);
|
||||||
this._checkOrigin(aIsSigned, aOldApp, newManifest, aIsUpdate);
|
this._checkOrigin(aIsSigned || aIsLocalFileInstall, aOldApp, newManifest,
|
||||||
|
aIsUpdate);
|
||||||
this._getIds(aIsSigned, aZipReader, converter, aNewApp, aOldApp, aIsUpdate);
|
this._getIds(aIsSigned, aZipReader, converter, aNewApp, aOldApp, aIsUpdate);
|
||||||
|
|
||||||
return newManifest;
|
return newManifest;
|
||||||
|
@ -3231,7 +3232,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
|
||||||
|
|
||||||
if (aIsUpdate) {
|
if (aIsUpdate) {
|
||||||
// Changing the origin during an update is not allowed.
|
// Changing the origin during an update is not allowed.
|
||||||
if (uri.prePath != app.origin) {
|
if (uri.prePath != aOldApp.origin) {
|
||||||
throw "INVALID_ORIGIN_CHANGE";
|
throw "INVALID_ORIGIN_CHANGE";
|
||||||
}
|
}
|
||||||
// Nothing else to do for an update... since the
|
// Nothing else to do for an update... since the
|
||||||
|
@ -3239,24 +3240,25 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
|
||||||
// app nor can we have a duplicated origin
|
// app nor can we have a duplicated origin
|
||||||
} else {
|
} else {
|
||||||
debug("Setting origin to " + uri.prePath +
|
debug("Setting origin to " + uri.prePath +
|
||||||
" for " + app.manifestURL);
|
" for " + aOldApp.manifestURL);
|
||||||
let newId = uri.prePath.substring(6); // "app://".length
|
let newId = uri.prePath.substring(6); // "app://".length
|
||||||
if (newId in this.webapps) {
|
if (newId in this.webapps) {
|
||||||
throw "DUPLICATE_ORIGIN";
|
throw "DUPLICATE_ORIGIN";
|
||||||
}
|
}
|
||||||
aOldApp.origin = uri.prePath;
|
aOldApp.origin = uri.prePath;
|
||||||
// Update the registry.
|
// Update the registry.
|
||||||
|
let oldId = aOldApp.id;
|
||||||
aOldApp.id = newId;
|
aOldApp.id = newId;
|
||||||
this.webapps[newId] = aOldApp;
|
this.webapps[newId] = aOldApp;
|
||||||
delete this.webapps[aId];
|
delete this.webapps[oldId];
|
||||||
// Rename the directories where the files are installed.
|
// Rename the directories where the files are installed.
|
||||||
[DIRECTORY_NAME, "TmpD"].forEach(function(aDir) {
|
[DIRECTORY_NAME, "TmpD"].forEach(function(aDir) {
|
||||||
let parent = FileUtils.getDir(aDir, ["webapps"], true, true);
|
let parent = FileUtils.getDir(aDir, ["webapps"], true, true);
|
||||||
let dir = FileUtils.getDir(aDir, ["webapps", aId], true, true);
|
let dir = FileUtils.getDir(aDir, ["webapps", oldId], true, true);
|
||||||
dir.moveTo(parent, newId);
|
dir.moveTo(parent, newId);
|
||||||
});
|
});
|
||||||
// Signals that we need to swap the old id with the new app.
|
// Signals that we need to swap the old id with the new app.
|
||||||
this.broadcastMessage("Webapps:RemoveApp", { id: aId });
|
this.broadcastMessage("Webapps:RemoveApp", { id: oldId });
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: newId,
|
this.broadcastMessage("Webapps:AddApp", { id: newId,
|
||||||
app: aOldApp });
|
app: aOldApp });
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,18 +586,33 @@ BrowserElementParent.prototype = {
|
||||||
_sendTouchEvent: function(type, identifiers, touchesX, touchesY,
|
_sendTouchEvent: function(type, identifiers, touchesX, touchesY,
|
||||||
radiisX, radiisY, rotationAngles, forces,
|
radiisX, radiisY, rotationAngles, forces,
|
||||||
count, modifiers) {
|
count, modifiers) {
|
||||||
this._sendAsyncMsg("send-touch-event", {
|
|
||||||
"type": type,
|
let tabParent = this._frameLoader.tabParent;
|
||||||
"identifiers": identifiers,
|
if (tabParent && tabParent.useAsyncPanZoom) {
|
||||||
"touchesX": touchesX,
|
tabParent.injectTouchEvent(type,
|
||||||
"touchesY": touchesY,
|
identifiers,
|
||||||
"radiisX": radiisX,
|
touchesX,
|
||||||
"radiisY": radiisY,
|
touchesY,
|
||||||
"rotationAngles": rotationAngles,
|
radiisX,
|
||||||
"forces": forces,
|
radiisY,
|
||||||
"count": count,
|
rotationAngles,
|
||||||
"modifiers": modifiers
|
forces,
|
||||||
});
|
count,
|
||||||
|
modifiers);
|
||||||
|
} else {
|
||||||
|
this._sendAsyncMsg("send-touch-event", {
|
||||||
|
"type": type,
|
||||||
|
"identifiers": identifiers,
|
||||||
|
"touchesX": touchesX,
|
||||||
|
"touchesY": touchesY,
|
||||||
|
"radiisX": radiisX,
|
||||||
|
"radiisY": radiisY,
|
||||||
|
"rotationAngles": rotationAngles,
|
||||||
|
"forces": forces,
|
||||||
|
"count": count,
|
||||||
|
"modifiers": modifiers
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_goBack: function() {
|
_goBack: function() {
|
||||||
|
|
|
@ -5,8 +5,19 @@
|
||||||
|
|
||||||
#include "domstubs.idl"
|
#include "domstubs.idl"
|
||||||
|
|
||||||
// Sole purpose is to be able to identify the concrete class nsTabParent
|
[scriptable, uuid(c402d6c2-837d-11e3-b47c-3c970e9f4238)]
|
||||||
[uuid(95c7c50b-6677-456f-9f1e-885e1cc272dc)]
|
|
||||||
interface nsITabParent : nsISupports
|
interface nsITabParent : nsISupports
|
||||||
{
|
{
|
||||||
|
void injectTouchEvent(in AString aType,
|
||||||
|
[array, size_is(count)] in uint32_t aIdentifiers,
|
||||||
|
[array, size_is(count)] in int32_t aXs,
|
||||||
|
[array, size_is(count)] in int32_t aYs,
|
||||||
|
[array, size_is(count)] in uint32_t aRxs,
|
||||||
|
[array, size_is(count)] in uint32_t aRys,
|
||||||
|
[array, size_is(count)] in float aRotationAngles,
|
||||||
|
[array, size_is(count)] in float aForces,
|
||||||
|
in uint32_t count,
|
||||||
|
in long aModifiers);
|
||||||
|
|
||||||
|
readonly attribute boolean useAsyncPanZoom;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1897,5 +1897,49 @@ TabParent::GetLoadContext()
|
||||||
return loadContext.forget();
|
return loadContext.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TabParent::InjectTouchEvent(const nsAString& aType,
|
||||||
|
uint32_t* aIdentifiers,
|
||||||
|
int32_t* aXs,
|
||||||
|
int32_t* aYs,
|
||||||
|
uint32_t* aRxs,
|
||||||
|
uint32_t* aRys,
|
||||||
|
float* aRotationAngles,
|
||||||
|
float* aForces,
|
||||||
|
uint32_t aCount,
|
||||||
|
int32_t aModifiers)
|
||||||
|
{
|
||||||
|
uint32_t msg;
|
||||||
|
nsContentUtils::GetEventIdAndAtom(aType, NS_TOUCH_EVENT, &msg);
|
||||||
|
if (msg != NS_TOUCH_START && msg != NS_TOUCH_MOVE &&
|
||||||
|
msg != NS_TOUCH_END && msg != NS_TOUCH_CANCEL) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetTouchEvent event(true, msg, nullptr);
|
||||||
|
event.modifiers = aModifiers;
|
||||||
|
event.time = PR_IntervalNow();
|
||||||
|
|
||||||
|
event.touches.SetCapacity(aCount);
|
||||||
|
for (uint32_t i = 0; i < aCount; ++i) {
|
||||||
|
nsRefPtr<Touch> t = new Touch(aIdentifiers[i],
|
||||||
|
nsIntPoint(aXs[i], aYs[i]),
|
||||||
|
nsIntPoint(aRxs[i], aRys[i]),
|
||||||
|
aRotationAngles[i],
|
||||||
|
aForces[i]);
|
||||||
|
event.touches.AppendElement(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendRealTouchEvent(event);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
|
||||||
|
{
|
||||||
|
*useAsyncPanZoom = UseAsyncPanZoom();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tabs
|
} // namespace tabs
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -59,6 +59,9 @@ class TabParent : public PBrowserParent
|
||||||
typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
|
typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// nsITabParent
|
||||||
|
NS_DECL_NSITABPARENT
|
||||||
|
|
||||||
TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags);
|
TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags);
|
||||||
virtual ~TabParent();
|
virtual ~TabParent();
|
||||||
Element* GetOwnerElement() const { return mFrameElement; }
|
Element* GetOwnerElement() const { return mFrameElement; }
|
||||||
|
|
|
@ -91,6 +91,7 @@ let NotificationDB = {
|
||||||
var promise = OS.File.open(NOTIFICATION_STORE_PATH, {create: true});
|
var promise = OS.File.open(NOTIFICATION_STORE_PATH, {create: true});
|
||||||
promise.then(
|
promise.then(
|
||||||
function onSuccess(handle) {
|
function onSuccess(handle) {
|
||||||
|
handle.close();
|
||||||
callback && callback();
|
callback && callback();
|
||||||
},
|
},
|
||||||
function onFailure(reason) {
|
function onFailure(reason) {
|
||||||
|
|
|
@ -174,6 +174,9 @@ public:
|
||||||
RefPtr<UnixSocketConsumer> mConsumer;
|
RefPtr<UnixSocketConsumer> mConsumer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void FireSocketError();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* libevent triggered functions that reads data from socket when available and
|
* libevent triggered functions that reads data from socket when available and
|
||||||
* guarenteed non-blocking. Only to be called on IO thread.
|
* guarenteed non-blocking. Only to be called on IO thread.
|
||||||
|
@ -487,29 +490,47 @@ void ShutdownSocketTask::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UnixSocketImpl::Accept()
|
UnixSocketImpl::FireSocketError()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
if (!mConnector) {
|
// Clean up watchers, statuses, fds
|
||||||
NS_WARNING("No connector object available!");
|
mReadWatcher.StopWatchingFileDescriptor();
|
||||||
return;
|
mWriteWatcher.StopWatchingFileDescriptor();
|
||||||
}
|
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||||
|
mFd.reset(-1);
|
||||||
|
|
||||||
|
// Tell the main thread we've errored
|
||||||
|
nsRefPtr<OnSocketEventTask> t =
|
||||||
|
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||||
|
NS_DispatchToMainThread(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UnixSocketImpl::Accept()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(mConnector);
|
||||||
|
|
||||||
// This will set things we don't particularly care about, but it will hand
|
// This will set things we don't particularly care about, but it will hand
|
||||||
// back the correct structure size which is what we do care about.
|
// back the correct structure size which is what we do care about.
|
||||||
if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) {
|
if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) {
|
||||||
NS_WARNING("Cannot create socket address!");
|
NS_WARNING("Cannot create socket address!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFd.get() < 0) {
|
if (mFd.get() < 0) {
|
||||||
mFd = mConnector->Create();
|
mFd = mConnector->Create();
|
||||||
if (mFd.get() < 0) {
|
if (mFd.get() < 0) {
|
||||||
|
NS_WARNING("Cannot create socket fd!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetSocketFlags()) {
|
if (!SetSocketFlags()) {
|
||||||
|
NS_WARNING("Cannot set socket flags!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,6 +538,7 @@ UnixSocketImpl::Accept()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
CHROMIUM_LOG("...bind(%d) gave errno %d", mFd.get(), errno);
|
CHROMIUM_LOG("...bind(%d) gave errno %d", mFd.get(), errno);
|
||||||
#endif
|
#endif
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,15 +546,13 @@ UnixSocketImpl::Accept()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
CHROMIUM_LOG("...listen(%d) gave errno %d", mFd.get(), errno);
|
CHROMIUM_LOG("...listen(%d) gave errno %d", mFd.get(), errno);
|
||||||
#endif
|
#endif
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mConnector->SetUpListenSocket(mFd)) {
|
if (!mConnector->SetUpListenSocket(mFd)) {
|
||||||
NS_WARNING("Could not set up listen socket!");
|
NS_WARNING("Could not set up listen socket!");
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
FireSocketError();
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,15 +565,13 @@ void
|
||||||
UnixSocketImpl::Connect()
|
UnixSocketImpl::Connect()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(mConnector);
|
||||||
if (!mConnector) {
|
|
||||||
NS_WARNING("No connector object available!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFd.get() < 0) {
|
if (mFd.get() < 0) {
|
||||||
mFd = mConnector->Create();
|
mFd = mConnector->Create();
|
||||||
if (mFd.get() < 0) {
|
if (mFd.get() < 0) {
|
||||||
|
NS_WARNING("Cannot create socket fd!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,15 +580,14 @@ UnixSocketImpl::Connect()
|
||||||
|
|
||||||
if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) {
|
if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) {
|
||||||
NS_WARNING("Cannot create socket address!");
|
NS_WARNING("Cannot create socket address!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select non-blocking IO.
|
// Select non-blocking IO.
|
||||||
if (-1 == fcntl(mFd.get(), F_SETFL, O_NONBLOCK)) {
|
if (-1 == fcntl(mFd.get(), F_SETFL, O_NONBLOCK)) {
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
NS_WARNING("Cannot set nonblock!");
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
FireSocketError();
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,20 +600,12 @@ UnixSocketImpl::Connect()
|
||||||
int current_opts = fcntl(mFd.get(), F_GETFL, 0);
|
int current_opts = fcntl(mFd.get(), F_GETFL, 0);
|
||||||
if (-1 == current_opts) {
|
if (-1 == current_opts) {
|
||||||
NS_WARNING("Cannot get socket opts!");
|
NS_WARNING("Cannot get socket opts!");
|
||||||
mFd.reset(-1);
|
FireSocketError();
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) {
|
if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) {
|
||||||
NS_WARNING("Cannot set socket opts to blocking!");
|
NS_WARNING("Cannot set socket opts to blocking!");
|
||||||
mFd.reset(-1);
|
FireSocketError();
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,20 +625,19 @@ UnixSocketImpl::Connect()
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
CHROMIUM_LOG("Socket connect errno=%d\n", errno);
|
CHROMIUM_LOG("Socket connect errno=%d\n", errno);
|
||||||
#endif
|
#endif
|
||||||
mFd.reset(-1);
|
FireSocketError();
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetSocketFlags()) {
|
if (!SetSocketFlags()) {
|
||||||
|
NS_WARNING("Cannot set socket flags!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mConnector->SetUp(mFd)) {
|
if (!mConnector->SetUp(mFd)) {
|
||||||
NS_WARNING("Could not set up socket!");
|
NS_WARNING("Could not set up socket!");
|
||||||
|
FireSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,30 +870,19 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||||
|
|
||||||
if (ret || error) {
|
if (ret || error) {
|
||||||
NS_WARNING("getsockopt failure on async socket connect!");
|
NS_WARNING("getsockopt failure on async socket connect!");
|
||||||
mFd.reset(-1);
|
FireSocketError();
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetSocketFlags()) {
|
if (!SetSocketFlags()) {
|
||||||
mFd.reset(-1);
|
NS_WARNING("Cannot set socket flags!");
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
FireSocketError();
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mConnector->SetUp(mFd)) {
|
if (!mConnector->SetUp(mFd)) {
|
||||||
NS_WARNING("Could not set up socket!");
|
NS_WARNING("Could not set up socket!");
|
||||||
mFd.reset(-1);
|
FireSocketError();
|
||||||
nsRefPtr<OnSocketEventTask> t =
|
|
||||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
|
||||||
NS_DispatchToMainThread(t);
|
|
||||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
|
@ -25,6 +27,10 @@
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
extern "C" MFBT_API int tgkill(pid_t tgid, pid_t tid, int signalno) {
|
||||||
|
return syscall(__NR_tgkill, tgid, tid, signalno);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the wrappers to a selected set of pthread and system-level functions
|
* Provides the wrappers to a selected set of pthread and system-level functions
|
||||||
* as the basis for implementing Zygote-like preforking mechanism.
|
* as the basis for implementing Zygote-like preforking mechanism.
|
||||||
|
@ -62,7 +68,6 @@ int __real_pipe2(int __pipedes[2], int flags);
|
||||||
int __real_pipe(int __pipedes[2]);
|
int __real_pipe(int __pipedes[2]);
|
||||||
int __real_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent);
|
int __real_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent);
|
||||||
int __real_close(int aFd);
|
int __real_close(int aFd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REAL(s) __real_##s
|
#define REAL(s) __real_##s
|
||||||
|
@ -139,6 +144,8 @@ TLSInfoList;
|
||||||
#define NUWA_STACK_SIZE (1024 * 32)
|
#define NUWA_STACK_SIZE (1024 * 32)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NATIVE_THREAD_NAME_LENGTH 16
|
||||||
|
|
||||||
struct thread_info : public mozilla::LinkedListElement<thread_info> {
|
struct thread_info : public mozilla::LinkedListElement<thread_info> {
|
||||||
pthread_t origThreadID;
|
pthread_t origThreadID;
|
||||||
pthread_t recreatedThreadID;
|
pthread_t recreatedThreadID;
|
||||||
|
@ -160,6 +167,10 @@ struct thread_info : public mozilla::LinkedListElement<thread_info> {
|
||||||
|
|
||||||
pthread_mutex_t *reacquireMutex;
|
pthread_mutex_t *reacquireMutex;
|
||||||
void *stk;
|
void *stk;
|
||||||
|
|
||||||
|
pid_t origNativeThreadID;
|
||||||
|
pid_t recreatedNativeThreadID;
|
||||||
|
char nativeThreadName[NATIVE_THREAD_NAME_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct thread_info thread_info_t;
|
typedef struct thread_info thread_info_t;
|
||||||
|
@ -212,6 +223,7 @@ static TLSKeySet sTLSKeys;
|
||||||
*/
|
*/
|
||||||
static pthread_mutex_t sThreadFreezeLock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t sThreadFreezeLock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static thread_info_t sMainThread;
|
||||||
static LinkedList<thread_info_t> sAllThreads;
|
static LinkedList<thread_info_t> sAllThreads;
|
||||||
static int sThreadCount = 0;
|
static int sThreadCount = 0;
|
||||||
static int sThreadFreezeCount = 0;
|
static int sThreadFreezeCount = 0;
|
||||||
|
@ -277,6 +289,32 @@ GetThreadInfo(pthread_t threadID) {
|
||||||
return tinfo;
|
return tinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get thread info using the specified native thread ID.
|
||||||
|
*
|
||||||
|
* @return thread_info_t with nativeThreadID == specified threadID
|
||||||
|
*/
|
||||||
|
static thread_info_t*
|
||||||
|
GetThreadInfo(pid_t threadID) {
|
||||||
|
if (sIsNuwaProcess) {
|
||||||
|
REAL(pthread_mutex_lock)(&sThreadCountLock);
|
||||||
|
}
|
||||||
|
thread_info_t *thrinfo = nullptr;
|
||||||
|
for (thread_info_t *tinfo = sAllThreads.getFirst();
|
||||||
|
tinfo;
|
||||||
|
tinfo = tinfo->getNext()) {
|
||||||
|
if (tinfo->origNativeThreadID == threadID) {
|
||||||
|
thrinfo = tinfo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sIsNuwaProcess) {
|
||||||
|
pthread_mutex_unlock(&sThreadCountLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return thrinfo;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(HAVE_THREAD_TLS_KEYWORD)
|
#if !defined(HAVE_THREAD_TLS_KEYWORD)
|
||||||
/**
|
/**
|
||||||
* Get thread info of the current thread.
|
* Get thread info of the current thread.
|
||||||
|
@ -449,6 +487,7 @@ thread_info_new(void) {
|
||||||
tinfo->recrFunc = nullptr;
|
tinfo->recrFunc = nullptr;
|
||||||
tinfo->recrArg = nullptr;
|
tinfo->recrArg = nullptr;
|
||||||
tinfo->recreatedThreadID = 0;
|
tinfo->recreatedThreadID = 0;
|
||||||
|
tinfo->recreatedNativeThreadID = 0;
|
||||||
tinfo->reacquireMutex = nullptr;
|
tinfo->reacquireMutex = nullptr;
|
||||||
tinfo->stk = malloc(NUWA_STACK_SIZE);
|
tinfo->stk = malloc(NUWA_STACK_SIZE);
|
||||||
pthread_attr_init(&tinfo->threadAttr);
|
pthread_attr_init(&tinfo->threadAttr);
|
||||||
|
@ -497,6 +536,7 @@ _thread_create_startup(void *arg) {
|
||||||
|
|
||||||
SET_THREAD_INFO(tinfo);
|
SET_THREAD_INFO(tinfo);
|
||||||
tinfo->origThreadID = REAL(pthread_self)();
|
tinfo->origThreadID = REAL(pthread_self)();
|
||||||
|
tinfo->origNativeThreadID = gettid();
|
||||||
|
|
||||||
pthread_cleanup_push(thread_info_cleanup, tinfo);
|
pthread_cleanup_push(thread_info_cleanup, tinfo);
|
||||||
|
|
||||||
|
@ -619,6 +659,7 @@ RestoreTLSInfo(thread_info_t *tinfo) {
|
||||||
|
|
||||||
SET_THREAD_INFO(tinfo);
|
SET_THREAD_INFO(tinfo);
|
||||||
tinfo->recreatedThreadID = REAL(pthread_self)();
|
tinfo->recreatedThreadID = REAL(pthread_self)();
|
||||||
|
tinfo->recreatedNativeThreadID = gettid();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" MFBT_API int
|
extern "C" MFBT_API int
|
||||||
|
@ -1215,6 +1256,27 @@ __wrap_close(int aFd) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" MFBT_API int
|
||||||
|
__wrap_tgkill(pid_t tgid, pid_t tid, int signalno)
|
||||||
|
{
|
||||||
|
if (sIsNuwaProcess) {
|
||||||
|
return tgkill(tgid, tid, signalno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tid == sMainThread.origNativeThreadID) {
|
||||||
|
return tgkill(tgid, sMainThread.recreatedNativeThreadID, signalno);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_info_t *tinfo = (tid == sMainThread.origNativeThreadID ?
|
||||||
|
&sMainThread :
|
||||||
|
GetThreadInfo(tid));
|
||||||
|
if (!tinfo) {
|
||||||
|
return tgkill(tgid, tid, signalno);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tgkill(tgid, tinfo->recreatedNativeThreadID, signalno);
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
thread_recreate_startup(void *arg) {
|
thread_recreate_startup(void *arg) {
|
||||||
/*
|
/*
|
||||||
|
@ -1232,6 +1294,7 @@ thread_recreate_startup(void *arg) {
|
||||||
*/
|
*/
|
||||||
thread_info_t *tinfo = (thread_info_t *)arg;
|
thread_info_t *tinfo = (thread_info_t *)arg;
|
||||||
|
|
||||||
|
prctl(PR_SET_NAME, (unsigned long)&tinfo->nativeThreadName, 0, 0, 0);
|
||||||
RestoreTLSInfo(tinfo);
|
RestoreTLSInfo(tinfo);
|
||||||
|
|
||||||
if (setjmp(tinfo->retEnv) != 0) {
|
if (setjmp(tinfo->retEnv) != 0) {
|
||||||
|
@ -1267,6 +1330,9 @@ RecreateThreads() {
|
||||||
sIsNuwaProcess = false;
|
sIsNuwaProcess = false;
|
||||||
sIsFreezing = false;
|
sIsFreezing = false;
|
||||||
|
|
||||||
|
sMainThread.recreatedThreadID = pthread_self();
|
||||||
|
sMainThread.recreatedNativeThreadID = gettid();
|
||||||
|
|
||||||
// Run registered constructors.
|
// Run registered constructors.
|
||||||
for (std::vector<nuwa_construct_t>::iterator ctr = sConstructors.begin();
|
for (std::vector<nuwa_construct_t>::iterator ctr = sConstructors.begin();
|
||||||
ctr != sConstructors.end();
|
ctr != sConstructors.end();
|
||||||
|
@ -1556,6 +1622,10 @@ PrepareNuwaProcess() {
|
||||||
|
|
||||||
// Make marked threads block in one freeze point.
|
// Make marked threads block in one freeze point.
|
||||||
REAL(pthread_mutex_lock)(&sThreadFreezeLock);
|
REAL(pthread_mutex_lock)(&sThreadFreezeLock);
|
||||||
|
|
||||||
|
// Populate sMainThread for mapping of tgkill.
|
||||||
|
sMainThread.origThreadID = pthread_self();
|
||||||
|
sMainThread.origNativeThreadID = gettid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make current process as a Nuwa process.
|
// Make current process as a Nuwa process.
|
||||||
|
@ -1607,6 +1677,10 @@ NuwaMarkCurrentThread(void (*recreate)(void *), void *arg) {
|
||||||
tinfo->flags |= TINFO_FLAG_NUWA_SUPPORT;
|
tinfo->flags |= TINFO_FLAG_NUWA_SUPPORT;
|
||||||
tinfo->recrFunc = recreate;
|
tinfo->recrFunc = recreate;
|
||||||
tinfo->recrArg = arg;
|
tinfo->recrArg = arg;
|
||||||
|
|
||||||
|
// XXX Thread name might be set later than this call. If this is the case, we
|
||||||
|
// might need to delay getting the thread name.
|
||||||
|
prctl(PR_GET_NAME, (unsigned long)&tinfo->nativeThreadName, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"toolkit/devtools/apps": ""
|
"toolkit/devtools/apps": ""
|
||||||
},
|
},
|
||||||
"excludetests": {
|
"excludetests": {
|
||||||
|
"b2g/chrome/content/test/mochitest": "require OOP support for mochitest-b2g-desktop, Bug 957554",
|
||||||
"content/xul":"tests that use xul",
|
"content/xul":"tests that use xul",
|
||||||
"layout/xul" : "",
|
"layout/xul" : "",
|
||||||
"dom/tests/mochitest/general/test_focusrings.xul":"",
|
"dom/tests/mochitest/general/test_focusrings.xul":"",
|
||||||
|
|
|
@ -83,6 +83,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
#include "ipc/Nuwa.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SIGNAL_SAVE_PROFILE SIGUSR2
|
#define SIGNAL_SAVE_PROFILE SIGUSR2
|
||||||
|
|
||||||
#if defined(__GLIBC__)
|
#if defined(__GLIBC__)
|
||||||
|
@ -229,9 +233,15 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||||
sem_post(&sSignalHandlingDone);
|
sem_post(&sSignalHandlingDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the Nuwa process is enabled, we need to use the wrapper of tgkill() to
|
||||||
|
// perform the mapping of thread ID.
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
extern "C" MFBT_API int tgkill(pid_t tgid, pid_t tid, int signalno);
|
||||||
|
#else
|
||||||
int tgkill(pid_t tgid, pid_t tid, int signalno) {
|
int tgkill(pid_t tgid, pid_t tid, int signalno) {
|
||||||
return syscall(SYS_tgkill, tgid, tid, signalno);
|
return syscall(SYS_tgkill, tgid, tid, signalno);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class PlatformData : public Malloced {
|
class PlatformData : public Malloced {
|
||||||
public:
|
public:
|
||||||
|
@ -263,6 +273,18 @@ static void* SignalSender(void* arg) {
|
||||||
static void* initialize_atfork = setup_atfork();
|
static void* initialize_atfork = setup_atfork();
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
// If the Nuwa process is enabled, we need to mark and freeze the sampler
|
||||||
|
// thread in the Nuwa process and have this thread recreated in the spawned
|
||||||
|
// child.
|
||||||
|
if(IsNuwaProcess()) {
|
||||||
|
NuwaMarkCurrentThread(nullptr, nullptr);
|
||||||
|
// Freeze the thread here so the spawned child will get the correct tgid
|
||||||
|
// from the getpid() call below.
|
||||||
|
NuwaFreezeCurrentThread();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int vm_tgid_ = getpid();
|
int vm_tgid_ = getpid();
|
||||||
|
|
||||||
while (SamplerRegistry::sampler->IsActive()) {
|
while (SamplerRegistry::sampler->IsActive()) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче