mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Merge birch to m-c.
This commit is contained in:
commit
e396d026b5
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "58d73404571f7619b478116dfec8faced97be13d",
|
||||
"revision": "5e60cb6fc0e09cefe242a6fb0159fbd09360cc1a",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -2094,36 +2094,6 @@ BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
GetDeviceServiceChannel(const nsAString& aObjectPath,
|
||||
const nsAString& aPattern,
|
||||
int aAttributeId)
|
||||
{
|
||||
// This is a blocking call, should not be run on main thread.
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// GetServiceAttributeValue only exists in android's bluez dbus binding
|
||||
// implementation
|
||||
nsCString tempPattern = NS_ConvertUTF16toUTF8(aPattern);
|
||||
const char* pattern = tempPattern.get();
|
||||
|
||||
DBusMessage *reply =
|
||||
dbus_func_args(gThreadConnection->GetConnection(),
|
||||
NS_ConvertUTF16toUTF8(aObjectPath).get(),
|
||||
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
|
||||
DBUS_TYPE_STRING, &pattern,
|
||||
DBUS_TYPE_UINT16, &aAttributeId,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
return reply ? dbus_returns_int32(reply) : -1;
|
||||
#else
|
||||
// FIXME/Bug 793977 qdot: Just return something for desktop, until we have a
|
||||
// parser for the GetServiceAttributes xml block
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
BluetoothDBusService::RemoveReservedServicesInternal(
|
||||
@ -2589,8 +2559,7 @@ public:
|
||||
mDeviceAddress = GetAddressFromObjectPath(aObjectPath);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Run()
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -2606,55 +2575,92 @@ private:
|
||||
BluetoothProfileManagerBase* mManager;
|
||||
};
|
||||
|
||||
class GetServiceChannelRunnable : public nsRunnable
|
||||
class OnGetServiceChannelReplyHandler : public DBusReplyHandler
|
||||
{
|
||||
public:
|
||||
GetServiceChannelRunnable(const nsAString& aObjectPath,
|
||||
const nsAString& aServiceUuid,
|
||||
BluetoothProfileManagerBase* aManager)
|
||||
: mObjectPath(aObjectPath),
|
||||
mServiceUuid(aServiceUuid),
|
||||
mManager(aManager)
|
||||
OnGetServiceChannelReplyHandler(const nsAString& aObjectPath,
|
||||
const nsAString& aServiceUUID,
|
||||
BluetoothProfileManagerBase* aBluetoothProfileManager)
|
||||
: mObjectPath(aObjectPath),
|
||||
mServiceUUID(aServiceUUID),
|
||||
mBluetoothProfileManager(aBluetoothProfileManager)
|
||||
{
|
||||
MOZ_ASSERT(!aObjectPath.IsEmpty());
|
||||
MOZ_ASSERT(!aServiceUuid.IsEmpty());
|
||||
MOZ_ASSERT(aManager);
|
||||
MOZ_ASSERT(mBluetoothProfileManager);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Run()
|
||||
void Handle(DBusMessage* aReply)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // DBus thread
|
||||
|
||||
int channel = GetDeviceServiceChannel(mObjectPath, mServiceUuid, 0x0004);
|
||||
nsRefPtr<nsRunnable> r(new OnGetServiceChannelRunnable(mObjectPath,
|
||||
mServiceUuid,
|
||||
channel,
|
||||
mManager));
|
||||
NS_DispatchToMainThread(r);
|
||||
return NS_OK;
|
||||
// The default channel is an invalid value of -1. We
|
||||
// update it if we have received a correct reply. Both
|
||||
// cases, valid and invalid channel numbers, are handled
|
||||
// in BluetoothProfileManagerBase::OnGetServiceChannel.
|
||||
|
||||
int channel = -1;
|
||||
|
||||
if (aReply && (dbus_message_get_type(aReply) != DBUS_MESSAGE_TYPE_ERROR)) {
|
||||
channel = dbus_returns_int32(aReply);
|
||||
}
|
||||
|
||||
nsRefPtr<nsRunnable> r = new OnGetServiceChannelRunnable(mObjectPath,
|
||||
mServiceUUID,
|
||||
channel,
|
||||
mBluetoothProfileManager);
|
||||
nsresult rv = NS_DispatchToMainThread(r);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mObjectPath;
|
||||
nsString mServiceUuid;
|
||||
BluetoothProfileManagerBase* mManager;
|
||||
nsString mServiceUUID;
|
||||
BluetoothProfileManagerBase* mBluetoothProfileManager;
|
||||
};
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
const nsAString& aServiceUUID,
|
||||
BluetoothProfileManagerBase* aManager)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBluetoothCommandThread);
|
||||
|
||||
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
|
||||
|
||||
nsRefPtr<nsRunnable> r(new GetServiceChannelRunnable(objectPath,
|
||||
aServiceUuid,
|
||||
aManager));
|
||||
mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
static const int sProtocolDescriptorList = 0x0004;
|
||||
|
||||
// GetServiceAttributeValue only exists in android's bluez dbus binding
|
||||
// implementation
|
||||
nsCString serviceUUID = NS_ConvertUTF16toUTF8(aServiceUUID);
|
||||
const char* cstrServiceUUID = serviceUUID.get();
|
||||
|
||||
nsRefPtr<OnGetServiceChannelReplyHandler> handler =
|
||||
new OnGetServiceChannelReplyHandler(objectPath, aServiceUUID, aManager);
|
||||
|
||||
bool success = dbus_func_args_async(mConnection, -1,
|
||||
OnGetServiceChannelReplyHandler::Callback, handler,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
|
||||
DBUS_TYPE_STRING, &cstrServiceUUID,
|
||||
DBUS_TYPE_UINT16, &sProtocolDescriptorList,
|
||||
DBUS_TYPE_INVALID);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
||||
|
||||
handler.forget();
|
||||
#else
|
||||
// FIXME/Bug 793977 qdot: Just set something for desktop, until we have a
|
||||
// parser for the GetServiceAttributes xml block
|
||||
//
|
||||
// Even though we are on the main thread already, we need to dispatch a
|
||||
// runnable here. OnGetServiceChannel needs mRunnable to be set, which
|
||||
// happens after GetServiceChannel returns.
|
||||
nsRefPtr<nsRunnable> r = new OnGetServiceChannelRunnable(objectPath,
|
||||
aServiceUUID,
|
||||
1,
|
||||
aManager);
|
||||
nsresult rv = NS_DispatchToMainThread(r);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ interface nsIDOMEventListener;
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMContact;
|
||||
|
||||
[scriptable, builtinclass, uuid(d21b7070-c2bc-11e2-8b8b-0800200c9a66)]
|
||||
[scriptable, builtinclass, uuid(5f405112-4da9-4d4d-942c-4da3cb7928e1)]
|
||||
interface nsIDOMMozIccManager : nsIDOMEventTarget
|
||||
{
|
||||
/**
|
||||
@ -432,6 +432,20 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget
|
||||
*/
|
||||
[implicit_jscontext] attribute jsval onicccardlockerror;
|
||||
|
||||
/**
|
||||
* Retrieve the number of remaining tries for unlocking the card.
|
||||
*
|
||||
* @param lockType
|
||||
* Identifies the lock type, e.g. "pin" for the PIN lock, "puk" for
|
||||
* the PUK lock.
|
||||
*
|
||||
* @return a DOM Request.
|
||||
* If the lock type is "pin", or "puk", the request's result will be
|
||||
* an object containing the number of retries for the specified
|
||||
* lock. For any other lock type, the result is undefined.
|
||||
*/
|
||||
nsIDOMDOMRequest getCardLockRetryCount(in DOMString lockType);
|
||||
|
||||
// UICC Phonebook Interfaces.
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ interface nsIIccListener : nsISupports
|
||||
/**
|
||||
* XPCOM component (in the content process) that provides the ICC information.
|
||||
*/
|
||||
[scriptable, uuid(77487bf0-c2be-11e2-8b8b-0800200c9a66)]
|
||||
[scriptable, uuid(7131dfbe-9a2c-434d-b6b8-3eebf491ce1a)]
|
||||
interface nsIIccProvider : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -57,6 +57,7 @@ interface nsIIccProvider : nsISupports
|
||||
nsIDOMDOMRequest getCardLockState(in nsIDOMWindow window, in DOMString lockType);
|
||||
nsIDOMDOMRequest unlockCardLock(in nsIDOMWindow window, in jsval info);
|
||||
nsIDOMDOMRequest setCardLock(in nsIDOMWindow window, in jsval info);
|
||||
nsIDOMDOMRequest getCardLockRetryCount(in nsIDOMWindow window, in DOMString lockType);
|
||||
|
||||
/**
|
||||
* Phonebook interfaces.
|
||||
|
@ -170,6 +170,16 @@ IccManager::UnlockCardLock(const JS::Value& aInfo, nsIDOMDOMRequest** aDomReques
|
||||
return mProvider->UnlockCardLock(GetOwner(), aInfo, aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IccManager::GetCardLockRetryCount(const nsAString& aLockType, nsIDOMDOMRequest** aDomRequest)
|
||||
{
|
||||
if (!mProvider) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetCardLockRetryCount(GetOwner(), aLockType, aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IccManager::IccOpenChannel(const nsAString& aAid, nsIDOMDOMRequest** aRequest)
|
||||
{
|
||||
|
@ -90,10 +90,80 @@ function testPinChangeSuccess() {
|
||||
};
|
||||
}
|
||||
|
||||
/* Read PIN-lock retry count */
|
||||
function testPinCardLockRetryCount() {
|
||||
let request = icc.getCardLockRetryCount('pin');
|
||||
|
||||
ok(request instanceof DOMRequest,
|
||||
'request instanceof ' + request.constructor);
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
is(request.result.lockType, 'pin',
|
||||
'lockType is ' + request.result.lockType);
|
||||
ok(request.result.retryCount >= 0,
|
||||
'retryCount is ' + request.result.retryCount);
|
||||
runNextTest();
|
||||
};
|
||||
request.onerror = function onerror() {
|
||||
// The operation is optional any might not be supported for all
|
||||
// all locks. In this case, we generate 'NotSupportedError' for
|
||||
// the valid lock types.
|
||||
is(request.error.name, 'RequestNotSupported',
|
||||
'error name is ' + request.error.name);
|
||||
runNextTest();
|
||||
};
|
||||
}
|
||||
|
||||
/* Read PUK-lock retry count */
|
||||
function testPukCardLockRetryCount() {
|
||||
let request = icc.getCardLockRetryCount('puk');
|
||||
|
||||
ok(request instanceof DOMRequest,
|
||||
'request instanceof ' + request.constructor);
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
is(request.result.lockType, 'puk',
|
||||
'lockType is ' + request.result.lockType);
|
||||
ok(request.result.retryCount >= 0,
|
||||
'retryCount is ' + request.result.retryCount);
|
||||
runNextTest();
|
||||
};
|
||||
request.onerror = function onerror() {
|
||||
// The operation is optional any might not be supported for all
|
||||
// all locks. In this case, we generate 'NotSupportedError' for
|
||||
// the valid lock types.
|
||||
is(request.error.name, 'RequestNotSupported',
|
||||
'error name is ' + request.error.name);
|
||||
runNextTest();
|
||||
};
|
||||
}
|
||||
|
||||
/* Read lock retry count for an invalid entries */
|
||||
function testInvalidCardLockRetryCount() {
|
||||
let request = icc.getCardLockRetryCount('invalid-lock-type');
|
||||
|
||||
ok(request instanceof DOMRequest,
|
||||
'request instanceof ' + request.constructor);
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
ok(false,
|
||||
'request should never return success for an invalid lock type');
|
||||
runNextTest();
|
||||
};
|
||||
request.onerror = function onerror() {
|
||||
is(request.error.name, 'GenericFailure',
|
||||
'error name is ' + request.error.name);
|
||||
runNextTest();
|
||||
};
|
||||
}
|
||||
|
||||
let tests = [
|
||||
testPinChangeFailed,
|
||||
testPinChangeFailedNotification,
|
||||
testPinChangeSuccess,
|
||||
testPinCardLockRetryCount,
|
||||
testPukCardLockRetryCount,
|
||||
testInvalidCardLockRetryCount
|
||||
];
|
||||
|
||||
function runNextTest() {
|
||||
|
@ -2572,5 +2572,37 @@ ContentParent::RecvSystemMessageHandled()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
|
||||
if (vs) {
|
||||
vs->CreateFakeVolume(fsName, mountPoint);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
NS_WARNING("ContentParent::RecvCreateFakeVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
|
||||
if (vs) {
|
||||
vs->SetFakeVolumeState(fsName, fsState);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
NS_WARNING("ContentParent::RecvSetFakeVolumeState shouldn't be called when MOZ_WIDGET_GONK is not defined");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -416,6 +416,10 @@ private:
|
||||
|
||||
virtual bool RecvSystemMessageHandled() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState) MOZ_OVERRIDE;
|
||||
|
||||
virtual void ProcessingError(Result what) MOZ_OVERRIDE;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
@ -515,6 +515,10 @@ parent:
|
||||
// Notify the parent that the child has finished handling a system message.
|
||||
async SystemMessageHandled();
|
||||
|
||||
// called by the child (test code only) to propagate volume changes to the parent
|
||||
async CreateFakeVolume(nsString fsName, nsString mountPoint);
|
||||
async SetFakeVolumeState(nsString fsName, int32_t fsState);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData);
|
||||
};
|
||||
|
@ -47,6 +47,11 @@ function debug(aMsg) {
|
||||
// dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
|
||||
}
|
||||
|
||||
|
||||
const MSG_SENT_SUCCESS = 0;
|
||||
const MSG_SENT_FAILURE_PERM_DENIED = 1;
|
||||
const MSG_SENT_FAILURE_APP_NOT_RUNNING = 2;
|
||||
|
||||
// Implementation of the component used by internal users.
|
||||
|
||||
function SystemMessageInternal() {
|
||||
@ -158,13 +163,16 @@ SystemMessageInternal.prototype = {
|
||||
debug("Sending " + aType + " " + JSON.stringify(aMessage) +
|
||||
" for " + aPageURI.spec + " @ " + aManifestURI.spec);
|
||||
|
||||
let result = this._sendMessageCommon(aType,
|
||||
aMessage,
|
||||
messageID,
|
||||
aPageURI.spec,
|
||||
aManifestURI.spec);
|
||||
debug("Returned status of sending message: " + result);
|
||||
|
||||
// Don't need to open the pages and queue the system message
|
||||
// which was not allowed to be sent.
|
||||
if (!this._sendMessageCommon(aType,
|
||||
aMessage,
|
||||
messageID,
|
||||
aPageURI.spec,
|
||||
aManifestURI.spec)) {
|
||||
if (result === MSG_SENT_FAILURE_PERM_DENIED) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -173,8 +181,10 @@ SystemMessageInternal.prototype = {
|
||||
// Queue this message in the corresponding pages.
|
||||
this._queueMessage(page, aMessage, messageID);
|
||||
|
||||
// Open app pages to handle their pending messages.
|
||||
this._openAppPage(page, aMessage);
|
||||
if (result === MSG_SENT_FAILURE_APP_NOT_RUNNING) {
|
||||
// Don't open the page again if we already sent the message to it.
|
||||
this._openAppPage(page, aMessage);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -196,21 +206,27 @@ SystemMessageInternal.prototype = {
|
||||
// Find pages that registered an handler for this type.
|
||||
this._pages.forEach(function(aPage) {
|
||||
if (aPage.type == aType) {
|
||||
let result = this._sendMessageCommon(aType,
|
||||
aMessage,
|
||||
messageID,
|
||||
aPage.uri,
|
||||
aPage.manifest);
|
||||
debug("Returned status of sending message: " + result);
|
||||
|
||||
|
||||
// Don't need to open the pages and queue the system message
|
||||
// which was not allowed to be sent.
|
||||
if (!this._sendMessageCommon(aType,
|
||||
aMessage,
|
||||
messageID,
|
||||
aPage.uri,
|
||||
aPage.manifest)) {
|
||||
if (result === MSG_SENT_FAILURE_PERM_DENIED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue this message in the corresponding pages.
|
||||
this._queueMessage(aPage, aMessage, messageID);
|
||||
|
||||
// Open app pages to handle their pending messages.
|
||||
this._openAppPage(aPage, aMessage);
|
||||
if (result === MSG_SENT_FAILURE_APP_NOT_RUNNING) {
|
||||
// Open app pages to handle their pending messages.
|
||||
this._openAppPage(aPage, aMessage);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
@ -525,7 +541,7 @@ SystemMessageInternal.prototype = {
|
||||
.isSystemMessagePermittedToSend(aType,
|
||||
aPageURI,
|
||||
aManifestURI)) {
|
||||
return false;
|
||||
return MSG_SENT_FAILURE_PERM_DENIED;
|
||||
}
|
||||
|
||||
let appPageIsRunning = false;
|
||||
@ -571,9 +587,11 @@ SystemMessageInternal.prototype = {
|
||||
// message when the page finishes handling the system message with other
|
||||
// pending messages. At that point, we'll release the lock we acquired.
|
||||
this._acquireCpuWakeLock(pageKey);
|
||||
return MSG_SENT_FAILURE_APP_NOT_RUNNING;
|
||||
} else {
|
||||
return MSG_SENT_SUCCESS;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
classID: Components.ID("{70589ca5-91ac-4b9e-b839-d6a88167d714}"),
|
||||
|
@ -473,13 +473,7 @@ MmsMessage::GetSmil(nsAString& aSmil)
|
||||
NS_IMETHODIMP
|
||||
MmsMessage::GetAttachments(JSContext* aCx, JS::Value* aAttachments)
|
||||
{
|
||||
// TODO Bug 850529 We should return an empty array (or null)
|
||||
// when it has no attachments? Need to further check this.
|
||||
uint32_t length = mAttachments.Length();
|
||||
if (length == 0) {
|
||||
*aAttachments = JSVAL_NULL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> attachments(aCx, JS_NewArrayObject(aCx, length, nullptr));
|
||||
NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -34,3 +34,4 @@ qemu = true
|
||||
[test_massive_incoming_delete.js]
|
||||
[test_getsegmentinfofortext.js]
|
||||
[test_phone_number_normalization.js]
|
||||
[test_mmsmessage_attachments.js]
|
||||
|
@ -0,0 +1,121 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
|
||||
const MMS_MAX_LENGTH_SUBJECT = 40;
|
||||
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
SpecialPowers.setBoolPref("dom.sms.enabled", true);
|
||||
|
||||
let tasks = {
|
||||
// List of test fuctions. Each of them should call |tasks.next()| when
|
||||
// completed or |tasks.finish()| to jump to the last one.
|
||||
_tasks: [],
|
||||
_nextTaskIndex: 0,
|
||||
|
||||
push: function push(func) {
|
||||
this._tasks.push(func);
|
||||
},
|
||||
|
||||
next: function next() {
|
||||
let index = this._nextTaskIndex++;
|
||||
let task = this._tasks[index];
|
||||
try {
|
||||
task();
|
||||
} catch (ex) {
|
||||
ok(false, "test task[" + index + "] throws: " + ex);
|
||||
// Run last task as clean up if possible.
|
||||
if (index != this._tasks.length - 1) {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
finish: function finish() {
|
||||
this._tasks[this._tasks.length - 1]();
|
||||
},
|
||||
|
||||
run: function run() {
|
||||
this.next();
|
||||
}
|
||||
};
|
||||
|
||||
let mozMobileMessage;
|
||||
|
||||
function getAllMessages(callback, filter, reverse) {
|
||||
if (!filter) {
|
||||
filter = new MozSmsFilter;
|
||||
}
|
||||
let messages = [];
|
||||
let request = mozMobileMessage.getMessages(filter, reverse || false);
|
||||
request.onsuccess = function(event) {
|
||||
if (request.result) {
|
||||
messages.push(request.result);
|
||||
request.continue();
|
||||
return;
|
||||
}
|
||||
|
||||
window.setTimeout(callback.bind(null, messages), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteAllMessages() {
|
||||
getAllMessages(function deleteAll(messages) {
|
||||
let message = messages.shift();
|
||||
if (!message) {
|
||||
ok(true, "all messages deleted");
|
||||
tasks.next();
|
||||
return;
|
||||
}
|
||||
|
||||
let request = mozMobileMessage.delete(message.id);
|
||||
request.onsuccess = deleteAll.bind(null, messages);
|
||||
request.onerror = function (event) {
|
||||
ok(false, "failed to delete all messages");
|
||||
tasks.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(function () {
|
||||
log("Verifying initial state.");
|
||||
|
||||
mozMobileMessage = window.navigator.mozMobileMessage;
|
||||
ok(mozMobileMessage instanceof MozMobileMessageManager);
|
||||
|
||||
tasks.next();
|
||||
});
|
||||
|
||||
tasks.push(function () {
|
||||
log("MmsMessage.attachments should be an empty array.");
|
||||
|
||||
mozMobileMessage.onfailed = function (event) {
|
||||
mozMobileMessage.onfailed = null;
|
||||
|
||||
let message = event.message;
|
||||
ok(Array.isArray(message.attachments) && message.attachments.length === 0,
|
||||
"message.attachments should be an empty array.");
|
||||
|
||||
tasks.next();
|
||||
};
|
||||
|
||||
// Have a long long subject causes the send fails, so we don't need
|
||||
// networking here.
|
||||
mozMobileMessage.sendMMS({
|
||||
subject: new Array(MMS_MAX_LENGTH_SUBJECT + 2).join("a"),
|
||||
receivers: ["1", "2"],
|
||||
attachments: [],
|
||||
});
|
||||
});
|
||||
|
||||
tasks.push(deleteAllMessages);
|
||||
|
||||
// WARNING: All tasks should be pushed before this!!!
|
||||
tasks.push(function cleanUp() {
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
SpecialPowers.clearUserPref("dom.sms.enabled");
|
||||
finish();
|
||||
});
|
||||
|
||||
tasks.run();
|
@ -79,6 +79,7 @@ const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:VoicemailInfoChanged",
|
||||
"RIL:CallError",
|
||||
"RIL:CardLockResult",
|
||||
"RIL:CardLockRetryCount",
|
||||
"RIL:USSDReceived",
|
||||
"RIL:SendMMI:Return:OK",
|
||||
"RIL:SendMMI:Return:KO",
|
||||
@ -123,6 +124,17 @@ MobileIccCardLockResult.prototype = {
|
||||
success: 'r'}
|
||||
};
|
||||
|
||||
function MobileIccCardLockRetryCount(options) {
|
||||
this.lockType = options.lockType;
|
||||
this.retryCount = options.retryCount;
|
||||
this.success = options.success;
|
||||
}
|
||||
MobileIccCardLockRetryCount.prototype = {
|
||||
__exposedProps__ : {lockType: 'r',
|
||||
retryCount: 'r',
|
||||
success: 'r'}
|
||||
};
|
||||
|
||||
function MobileICCInfo() {}
|
||||
MobileICCInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileICCInfo]),
|
||||
@ -650,6 +662,23 @@ RILContentHelper.prototype = {
|
||||
return request;
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function getCardLockRetryCount(window, lockType) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
|
||||
clientId: 0,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
sendMMI: function sendMMI(window, mmi) {
|
||||
// We need to save the global window to get the proper MMIError
|
||||
// constructor once we get the reply from the parent process.
|
||||
@ -1378,6 +1407,14 @@ RILContentHelper.prototype = {
|
||||
this.fireRequestError(msg.json.requestId, msg.json.errorMsg);
|
||||
}
|
||||
break;
|
||||
case "RIL:CardLockRetryCount":
|
||||
if (msg.json.success) {
|
||||
let result = new MobileIccCardLockRetryCount(msg.json);
|
||||
this.fireRequestSuccess(msg.json.requestId, result);
|
||||
} else {
|
||||
this.fireRequestError(msg.json.requestId, msg.json.errorMsg);
|
||||
}
|
||||
break;
|
||||
case "RIL:USSDReceived": {
|
||||
let data = msg.json.data;
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
|
@ -115,6 +115,7 @@ const RIL_IPC_ICCMANAGER_MSG_NAMES = [
|
||||
"RIL:GetCardLockState",
|
||||
"RIL:UnlockCardLock",
|
||||
"RIL:SetCardLock",
|
||||
"RIL:GetCardLockRetryCount",
|
||||
"RIL:IccOpenChannel",
|
||||
"RIL:IccExchangeAPDU",
|
||||
"RIL:IccCloseChannel",
|
||||
@ -826,6 +827,10 @@ RadioInterface.prototype = {
|
||||
gMessageManager.saveRequestTarget(msg);
|
||||
this.setCardLock(msg.json.data);
|
||||
break;
|
||||
case "RIL:GetCardLockRetryCount":
|
||||
gMessageManager.saveRequestTarget(msg);
|
||||
this.getCardLockRetryCount(msg.json.data);
|
||||
break;
|
||||
case "RIL:SendMMI":
|
||||
gMessageManager.saveRequestTarget(msg);
|
||||
this.sendMMI(msg.json.data);
|
||||
@ -1025,6 +1030,9 @@ RadioInterface.prototype = {
|
||||
case "iccUnlockCardLock":
|
||||
this.handleIccCardLockResult(message);
|
||||
break;
|
||||
case "iccGetCardLockRetryCount":
|
||||
this.handleIccCardLockRetryCount(message);
|
||||
break;
|
||||
case "icccontacts":
|
||||
this.handleReadIccContacts(message);
|
||||
break;
|
||||
@ -2107,6 +2115,10 @@ RadioInterface.prototype = {
|
||||
gMessageManager.sendRequestResults("RIL:CardLockResult", message);
|
||||
},
|
||||
|
||||
handleIccCardLockRetryCount: function handleIccCardLockRetryCount(message) {
|
||||
gMessageManager.sendRequestResults("RIL:CardLockRetryCount", message);
|
||||
},
|
||||
|
||||
handleUSSDReceived: function handleUSSDReceived(ussd) {
|
||||
if (DEBUG) this.debug("handleUSSDReceived " + JSON.stringify(ussd));
|
||||
gSystemMessenger.broadcastMessage("ussd-received", ussd);
|
||||
@ -3333,6 +3345,11 @@ RadioInterface.prototype = {
|
||||
this.worker.postMessage(message);
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function getCardLockRetryCount(message) {
|
||||
message.rilMessageType = "iccGetCardLockRetryCount";
|
||||
this.worker.postMessage(message);
|
||||
},
|
||||
|
||||
readIccContacts: function readIccContacts(message) {
|
||||
message.rilMessageType = "readICCContacts";
|
||||
this.worker.postMessage(message);
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVolumeStat.idl"
|
||||
|
||||
[scriptable, uuid(1134f267-7b81-42f2-b64a-6edb91286576)]
|
||||
[scriptable, uuid(4b5bd562-bd05-4658-ab0f-f668a9e25fb5)]
|
||||
interface nsIVolume : nsISupports
|
||||
{
|
||||
// These MUST match the states from android's system/vold/Volume.h header
|
||||
@ -49,6 +49,9 @@ interface nsIVolume : nsISupports
|
||||
readonly attribute boolean isMountLocked;
|
||||
|
||||
nsIVolumeStat getStats();
|
||||
|
||||
// Whether this is a fake volume.
|
||||
readonly attribute boolean isFake;
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -12,7 +12,7 @@
|
||||
%}
|
||||
[ref] native nsStringTArrayRef(nsTArray<nsString>);
|
||||
|
||||
[scriptable, uuid(7c179fb7-67a0-43a3-9337-294e0360b858)]
|
||||
[scriptable, uuid(a3b110cd-74f2-43cb-84c6-2a87713f2774)]
|
||||
interface nsIVolumeService : nsISupports
|
||||
{
|
||||
nsIVolume getVolumeByName(in DOMString volName);
|
||||
@ -24,6 +24,10 @@ interface nsIVolumeService : nsISupports
|
||||
nsIVolumeMountLock createMountLock(in DOMString volName);
|
||||
|
||||
[noscript] void getVolumeNames(in nsStringTArrayRef aVolNames);
|
||||
|
||||
/* for test case only to simulate sdcard insertion/removal */
|
||||
void createFakeVolume(in DOMString name, in DOMString path);
|
||||
void SetFakeVolumeState(in DOMString name, in long state);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -50,7 +50,8 @@ nsVolume::nsVolume(const Volume* aVolume)
|
||||
mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
|
||||
mState(aVolume->State()),
|
||||
mMountGeneration(aVolume->MountGeneration()),
|
||||
mMountLocked(aVolume->IsMountLocked())
|
||||
mMountLocked(aVolume->IsMountLocked()),
|
||||
mIsFake(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,6 +86,13 @@ bool nsVolume::Equals(nsIVolume* aVolume)
|
||||
if (mMountLocked != volIsMountLocked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isFake;
|
||||
aVolume->GetIsFake(&isFake);
|
||||
if (mIsFake != isFake) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -136,6 +144,12 @@ NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
|
||||
{
|
||||
*aIsFake = mIsFake;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::LogState() const
|
||||
{
|
||||
@ -156,6 +170,7 @@ void nsVolume::Set(nsIVolume* aVolume)
|
||||
aVolume->GetName(mName);
|
||||
aVolume->GetMountPoint(mMountPoint);
|
||||
aVolume->GetState(&mState);
|
||||
aVolume->GetIsFake(&mIsFake);
|
||||
|
||||
int32_t volMountGeneration;
|
||||
aVolume->GetMountGeneration(&volMountGeneration);
|
||||
@ -222,5 +237,25 @@ nsVolume::UpdateMountLock(bool aMountLocked)
|
||||
MountGeneration(), aMountLocked));
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::SetState(int32_t aState)
|
||||
{
|
||||
static int32_t sMountGeneration = 0;
|
||||
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsFake());
|
||||
|
||||
if (aState == mState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aState == nsIVolume::STATE_MOUNTED) {
|
||||
mMountGeneration = ++sMountGeneration;
|
||||
}
|
||||
|
||||
mState = aState;
|
||||
}
|
||||
|
||||
} // system
|
||||
} // mozilla
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
mMountPoint(aMountPoint),
|
||||
mState(aState),
|
||||
mMountGeneration(aMountGeneration),
|
||||
mMountLocked(false)
|
||||
mMountLocked(false),
|
||||
mIsFake(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -42,7 +43,8 @@ public:
|
||||
: mName(aName),
|
||||
mState(STATE_INIT),
|
||||
mMountGeneration(-1),
|
||||
mMountLocked(true) // Needs to agree with Volume::Volume
|
||||
mMountLocked(true), // Needs to agree with Volume::Volume
|
||||
mIsFake(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -72,11 +74,16 @@ private:
|
||||
void UpdateMountLock(const nsAString& aMountLockState);
|
||||
void UpdateMountLock(bool aMountLocked);
|
||||
|
||||
bool IsFake() const { return mIsFake; }
|
||||
void SetIsFake(bool aIsFake) { mIsFake = aIsFake; }
|
||||
void SetState(int32_t aState);
|
||||
|
||||
nsString mName;
|
||||
nsString mMountPoint;
|
||||
int32_t mState;
|
||||
int32_t mMountGeneration;
|
||||
bool mMountLocked;
|
||||
bool mIsFake;
|
||||
};
|
||||
|
||||
} // system
|
||||
|
@ -326,7 +326,7 @@ nsVolumeService::FindVolumeByName(const nsAString& aName)
|
||||
|
||||
//static
|
||||
already_AddRefed<nsVolume>
|
||||
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName)
|
||||
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/)
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
|
||||
@ -337,6 +337,7 @@ nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName)
|
||||
}
|
||||
// Volume not found - add a new one
|
||||
vol = new nsVolume(aName);
|
||||
vol->SetIsFake(aIsFake);
|
||||
mVolumeArray.AppendElement(vol);
|
||||
return vol.forget();
|
||||
}
|
||||
@ -348,11 +349,19 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume)
|
||||
|
||||
nsString volName;
|
||||
aVolume->GetName(volName);
|
||||
nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName);
|
||||
bool aIsFake;
|
||||
aVolume->GetIsFake(&aIsFake);
|
||||
nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
|
||||
if (vol->Equals(aVolume)) {
|
||||
// Nothing has really changed. Don't bother telling anybody.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vol->IsFake() && aIsFake) {
|
||||
// Prevent an incoming fake volume from overriding an existing real volume.
|
||||
return;
|
||||
}
|
||||
|
||||
vol->Set(aVolume);
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
if (!obs) {
|
||||
@ -362,6 +371,41 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume)
|
||||
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsRefPtr<nsVolume> vol = new nsVolume(name, path, nsIVolume::STATE_INIT, -1);
|
||||
vol->SetIsFake(true);
|
||||
UpdateVolume(vol.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ContentChild::GetSingleton()->SendCreateFakeVolume(nsString(name), nsString(path));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsRefPtr<nsVolume> vol;
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
vol = FindVolumeByName(name);
|
||||
}
|
||||
if (!vol || !vol->IsFake()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
vol->SetState(state);
|
||||
UpdateVolume(vol.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ContentChild::GetSingleton()->SendSetFakeVolumeState(nsString(name), state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* The UpdateVolumeRunnable creates an nsVolume and updates the main thread
|
||||
* data structure while running on the main thread.
|
||||
|
@ -50,7 +50,7 @@ private:
|
||||
const nsAString& aMountLockState);
|
||||
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
|
||||
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName);
|
||||
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
|
||||
|
||||
Monitor mArrayMonitor;
|
||||
nsVolume::Array mVolumeArray;
|
||||
|
@ -1196,6 +1196,36 @@ let RIL = {
|
||||
this.queryICCFacilityLock(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function for fetching the number of unlock retries of ICC locks.
|
||||
*/
|
||||
iccGetCardLockRetryCount: function iccGetCardLockRetryCount(options) {
|
||||
switch (options.lockType) {
|
||||
case "pin":
|
||||
case "puk":
|
||||
case "pin2":
|
||||
case "puk2":
|
||||
case "nck":
|
||||
case "cck":
|
||||
case "spck":
|
||||
options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
|
||||
options.success = false;
|
||||
this.sendDOMMessage(options);
|
||||
return;
|
||||
default:
|
||||
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
|
||||
options.success = false;
|
||||
this.sendDOMMessage(options);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: We currently don't have a way for
|
||||
// reading the retry count. See bug 868896.
|
||||
options.retryCount = 0;
|
||||
options.success = true;
|
||||
this.sendDOMMessage(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Query ICC facility lock.
|
||||
*
|
||||
|
@ -6,3 +6,4 @@ qemu = true
|
||||
[test_geolocation.js]
|
||||
disabled = Bug 808783
|
||||
[test_get_voicemailInfo.js]
|
||||
[test_fakevolume.js]
|
||||
|
29
dom/system/gonk/tests/marionette/test_fakevolume.js
Normal file
29
dom/system/gonk/tests/marionette/test_fakevolume.js
Normal file
@ -0,0 +1,29 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
let Cc = SpecialPowers.Cc;
|
||||
let Ci = SpecialPowers.Ci;
|
||||
|
||||
let volumeService = Cc["@mozilla.org/telephony/volume-service;1"].getService(Ci.nsIVolumeService);
|
||||
ok(volumeService, "Should have volume service");
|
||||
|
||||
let volName = "fake";
|
||||
let mountPoint = "/data/fake/storage";
|
||||
volumeService.createFakeVolume(volName, mountPoint);
|
||||
|
||||
let vol = volumeService.getVolumeByName(volName);
|
||||
ok(vol, "volume shouldn't be null");
|
||||
|
||||
is(volName, vol.name, "name");
|
||||
is(mountPoint, vol.mountPoint, "moutnPoint");
|
||||
is(Ci.nsIVolume.STATE_INIT, vol.state, "state");
|
||||
|
||||
|
||||
let oldMountGen = vol.mountGeneration;
|
||||
volumeService.SetFakeVolumeState(volName, Ci.nsIVolume.STATE_MOUNTED);
|
||||
is(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state");
|
||||
ok(vol.mountGeneration > oldMountGen, "mount generation should be incremented");
|
||||
|
||||
finish();
|
@ -507,10 +507,14 @@ var WifiManager = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function setPowerModeCommand(mode, callback) {
|
||||
function setPowerModeCommandICS(mode, callback) {
|
||||
doBooleanCommand("DRIVER POWERMODE " + (mode === "AUTO" ? 0 : 1), "OK", callback);
|
||||
}
|
||||
|
||||
function setPowerModeCommandJB(mode, callback) {
|
||||
doBooleanCommand("SET ps " + (mode === "AUTO" ? 1 : 0), "OK", callback);
|
||||
}
|
||||
|
||||
function getPowerModeCommand(callback) {
|
||||
doStringCommand("DRIVER GETPOWER", function(reply) {
|
||||
if (reply)
|
||||
@ -1508,7 +1512,9 @@ var WifiManager = (function() {
|
||||
manager.wpsPbc = wpsPbcCommand;
|
||||
manager.wpsPin = wpsPinCommand;
|
||||
manager.wpsCancel = wpsCancelCommand;
|
||||
manager.setPowerMode = setPowerModeCommand;
|
||||
manager.setPowerMode = (sdkVersion >= 16)
|
||||
? setPowerModeCommandJB
|
||||
: setPowerModeCommandICS;
|
||||
manager.setSuspendOptimizations = setSuspendOptimizationsCommand;
|
||||
manager.setStaticIpMode = setStaticIpMode;
|
||||
manager.getRssiApprox = getRssiApproxCommand;
|
||||
|
@ -113,6 +113,10 @@ class Channel : public Message::Sender {
|
||||
|
||||
// Return the server side of the socketpair.
|
||||
int GetServerFileDescriptor() const;
|
||||
|
||||
// Close the client side of the socketpair.
|
||||
void CloseClientFileDescriptor();
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
// Return the server pipe handle.
|
||||
void* GetServerPipeHandle() const;
|
||||
|
@ -779,6 +779,14 @@ void Channel::ChannelImpl::GetClientFileDescriptorMapping(int *src_fd,
|
||||
*dest_fd = kClientChannelFd;
|
||||
}
|
||||
|
||||
void Channel::ChannelImpl::CloseClientFileDescriptor() {
|
||||
if (client_pipe_ != -1) {
|
||||
Singleton<PipeMap>()->Remove(pipe_name_);
|
||||
HANDLE_EINTR(close(client_pipe_));
|
||||
client_pipe_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Called by libevent when we can read from th pipe without blocking.
|
||||
void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
|
||||
bool send_server_hello_msg = false;
|
||||
@ -944,4 +952,8 @@ int Channel::GetServerFileDescriptor() const {
|
||||
return channel_impl_->GetServerFileDescriptor();
|
||||
}
|
||||
|
||||
void Channel::CloseClientFileDescriptor() {
|
||||
channel_impl_->CloseClientFileDescriptor();
|
||||
}
|
||||
|
||||
} // namespace IPC
|
||||
|
@ -40,6 +40,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
|
||||
DCHECK(mode_ == MODE_SERVER);
|
||||
return pipe_;
|
||||
}
|
||||
void CloseClientFileDescriptor();
|
||||
|
||||
private:
|
||||
void Init(Mode mode, Listener* listener);
|
||||
|
@ -627,7 +627,6 @@ int dbus_returns_int32(DBusMessage *reply)
|
||||
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
|
||||
}
|
||||
|
||||
dbus_message_unref(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -647,5 +646,15 @@ int dbus_returns_uint32(DBusMessage *reply)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBusReplyHandler::Callback(DBusMessage* aReply, void* aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
|
||||
nsRefPtr<DBusReplyHandler> handler =
|
||||
already_AddRefed<DBusReplyHandler>(static_cast<DBusReplyHandler*>(aData));
|
||||
|
||||
handler->Handle(aReply);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define mozilla_ipc_dbus_dbusutils_h__
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
|
||||
// LOGE and free a D-Bus error
|
||||
@ -50,8 +51,45 @@ private:
|
||||
DBusMessage* mMsg;
|
||||
};
|
||||
|
||||
typedef void (*DBusCallback)(DBusMessage *, void *);
|
||||
/**
|
||||
* DBusReplyHandler represents a handler for DBus reply messages. Inherit
|
||||
* from this class and implement the Handle method. The method Callback
|
||||
* should be passed to the DBus send function, with the class instance as
|
||||
* user-data argument.
|
||||
*/
|
||||
class DBusReplyHandler : public mozilla::RefCounted<DBusReplyHandler>
|
||||
{
|
||||
public:
|
||||
virtual ~DBusReplyHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a call-back function for DBus. The supplied value for
|
||||
* aData must be a pointer to an instance of DBusReplyHandler.
|
||||
*/
|
||||
static void Callback(DBusMessage* aReply, void* aData);
|
||||
|
||||
/**
|
||||
* Call-back method for handling the reply message from DBus.
|
||||
*/
|
||||
virtual void Handle(DBusMessage* aReply) = 0;
|
||||
|
||||
protected:
|
||||
DBusReplyHandler()
|
||||
{
|
||||
}
|
||||
|
||||
DBusReplyHandler(const DBusReplyHandler& aHandler)
|
||||
{
|
||||
}
|
||||
|
||||
DBusReplyHandler& operator = (const DBusReplyHandler& aRhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef void (*DBusCallback)(DBusMessage *, void *);
|
||||
|
||||
void log_and_free_dbus_error(DBusError* err,
|
||||
const char* function,
|
||||
|
@ -656,6 +656,11 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
||||
#endif
|
||||
false, &process, arch);
|
||||
|
||||
// We're in the parent and the child was launched. Close the child FD in the
|
||||
// parent as soon as possible, which will allow the parent to detect when the
|
||||
// child closes its FD (either due to normal exit or due to crash).
|
||||
GetChannel()->CloseClientFileDescriptor();
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
// Wait for the child process to send us its 'task_t' data.
|
||||
const int kTimeoutMs = 10000;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwcomposer.h>
|
||||
#include <hardware/power.h>
|
||||
#include <suspend/autosuspend.h>
|
||||
|
||||
#include "GraphicBufferAlloc.h"
|
||||
@ -36,6 +37,7 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
, mHwc(nullptr)
|
||||
, mFBDevice(nullptr)
|
||||
, mEnabledCallback(nullptr)
|
||||
, mPowerModule(nullptr)
|
||||
{
|
||||
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mFBModule);
|
||||
ALOGW_IF(err, "%s module not found", GRALLOC_HARDWARE_MODULE_ID);
|
||||
@ -82,6 +84,12 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
}
|
||||
|
||||
err = hw_get_module(POWER_HARDWARE_MODULE_ID,
|
||||
(hw_module_t const**)&mPowerModule);
|
||||
if (!err)
|
||||
mPowerModule->init(mPowerModule);
|
||||
ALOGW_IF(err, "Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
|
||||
|
||||
mAlloc = new GraphicBufferAlloc();
|
||||
mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, mAlloc);
|
||||
|
||||
@ -115,8 +123,10 @@ GonkDisplayJB::GetNativeWindow()
|
||||
void
|
||||
GonkDisplayJB::SetEnabled(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
autosuspend_disable();
|
||||
mPowerModule->setInteractive(mPowerModule, true);
|
||||
}
|
||||
|
||||
if (mHwc)
|
||||
mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, !enabled);
|
||||
@ -126,8 +136,10 @@ GonkDisplayJB::SetEnabled(bool enabled)
|
||||
if (mEnabledCallback)
|
||||
mEnabledCallback(enabled);
|
||||
|
||||
if (!enabled)
|
||||
if (!enabled) {
|
||||
autosuspend_enable();
|
||||
mPowerModule->setInteractive(mPowerModule, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "GonkDisplay.h"
|
||||
#include "FramebufferSurface.h"
|
||||
#include "hardware/hwcomposer.h"
|
||||
#include "hardware/power.h"
|
||||
#include "utils/RefBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -49,6 +50,7 @@ private:
|
||||
hw_module_t const* mFBModule;
|
||||
hwc_composer_device_1_t* mHwc;
|
||||
framebuffer_device_t* mFBDevice;
|
||||
power_module_t* mPowerModule;
|
||||
android::sp<android::FramebufferSurface> mFBSurface;
|
||||
android::sp<ANativeWindow> mSTClient;
|
||||
android::sp<android::IGraphicBufferAlloc> mAlloc;
|
||||
|
Loading…
Reference in New Issue
Block a user