Merge birch to m-c.

This commit is contained in:
Ryan VanderMeulen 2013-07-10 09:42:28 -04:00
commit e396d026b5
33 changed files with 670 additions and 99 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "58d73404571f7619b478116dfec8faced97be13d",
"revision": "5e60cb6fc0e09cefe242a6fb0159fbd09360cc1a",
"repo_path": "/integration/gaia-central"
}

View File

@ -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;
}

View File

@ -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.
/**

View File

@ -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.

View File

@ -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)
{

View File

@ -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() {

View File

@ -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

View File

@ -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;

View File

@ -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);
};

View File

@ -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}"),

View File

@ -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);

View File

@ -34,3 +34,4 @@ qemu = true
[test_massive_incoming_delete.js]
[test_getsegmentinfofortext.js]
[test_phone_number_normalization.js]
[test_mmsmessage_attachments.js]

View File

@ -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();

View File

@ -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",

View File

@ -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);

View File

@ -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++

View File

@ -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++

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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.
*

View File

@ -6,3 +6,4 @@ qemu = true
[test_geolocation.js]
disabled = Bug 808783
[test_get_voicemailInfo.js]
[test_fakevolume.js]

View 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();

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;