From 38681ff9e3ea520c54314e34d635e09ae67e6f84 Mon Sep 17 00:00:00 2001 From: roytam1 Date: Tue, 7 Sep 2021 15:52:27 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1146248 - Stop previous DHCP request when requesting a new one. r=vchang (1aae6f57d) - Bug 1167466 - Prevent from previous failed DHCP callback interferring ongoing DHCP request. r=vchang. (35fc7df93) - Bug 1167132 - Part 3: [NetworkManager] Move network information into a separate interface (Wifi). r=hchang (f44dc346d) - Bug 1167132 - Part 4: [NetworkManager] Move network information into a separate interface (DataCall). r=echen (175ff98a6) - Bug 1167132 - Part 5: [NetworkManager] Move network information into a separate interface (Tethering). r=echen (5bca84f68) - Bug 1114938 - Part 1: Refactor StkProactiveCmdFactory.jsm into a XPCOM Service. r=echen (1701a4ac8) - Bug 1114938 - Part 2.1: (Gonk) Refactor Stk Proactive Commands from IccProvider to IccService. r=echen (a541d04d6) - Bug 1114938 - Part 2.2: (Gonk) Refactor Stk Request APIs from IccProvider to IccService. r=echen (6b72b6fd9) - Bug 1114938 - Part 2.3: (Gonk) Remove Implementation from IccProvider. r=echen (5ef470e1a) - Bug 1114938 - Part 3.1: (IPC) IPDL Declaration. r=echen (56dbb4563) - Bug 1114938 - Part 3.2: (IPC) Add Helper to deflate/inflate XPCOM object to/from JSON for IPC. r=echen (fe30d9af9) - Bug 1114938 - Part 4: (WebIDL) Type of MNC/MCC shall be the same to the one defined in MozMobileNetworkInfo. r=echen, r=htsai (62e7c23f2) - Bug 1114937 - Part 1: Define new IDL for IccContacts. r=echen (04150be4c) - Bug 1114937 - Part 2: IDL implementation in Gonk. r=echen (40c79e34a) - Bug 1114937 - Part 3: Web API change to adopt IccService for IccContacts. r=echen, r=hsinyi (e55efbe8f) - Bug 1114938 - Part 3.3: (IPC) IPDL Implementation. r=echen (2e695628e) - Bug 1114937 - Part 4: IPDL Implementation. r=echen (a93612284) - Bug 1114937 - Part 6: Deprecate RILContentHelper. r=echen (474dee728) - Bug 1167132 - Part 6: [NetworkManager] Move network information into a separate interface (RadioInterface). r=echen (948f8674b) - Bug 1167132 - Part 7: [NetworkManager] Move network information into a separate interface (MobileConnection). r=echen (ef6f47b08) - missing bit of Bug 992772 (dcb2b8c2f) - Bug 1182770 - Catch Rejected Promise Properly when Failed to ensure routing. r=echen (c1ec16c4d) - Bug 1167132 - Part 8: [NetworkManager] Move network information into a separate interface (Mms). r=btseng (e6320c600) - Bug 1167132 - Part 9: [NetworkManager] Move network information into a separate interface (shell). r=fabrice (f532dde13) - Bug 1167132 - Part 10: [NetworkManager] Move network information into a separate interface (PushService). r=nsm (acb180630) - Bug 1167132 - Part 11: [NetworkManager] Move network information into a separate interface (Gps). r=kanru (9debb66e7) - Bug 1167132 - Part 12: [NetworkManager] Move network information into a separate interface (discovery). r=jryans (04249762c) --- b2g/chrome/content/shell.js | 6 +- b2g/installer/package-manifest.in | 4 +- dom/bluetooth/BluetoothRilListener.cpp | 2 +- .../bluetooth2/BluetoothRilListener.cpp | 2 +- dom/icc/Icc.cpp | 160 ++- dom/icc/Icc.h | 16 +- dom/icc/IccCallback.cpp | 151 +++ dom/icc/IccContact.cpp | 145 +++ dom/icc/IccContact.h | 50 + dom/icc/IccListener.cpp | 29 +- dom/icc/IccListener.h | 4 - dom/icc/gonk/IccService.js | 201 +++- ...oactiveCmdFactory.jsm => StkCmdFactory.js} | 600 +++++++++- dom/icc/gonk/StkCmdFactory.manifest | 6 + dom/icc/interfaces/moz.build | 4 +- dom/icc/interfaces/nsIGonkIccService.idl | 7 +- dom/icc/interfaces/nsIIccContact.idl | 60 + dom/icc/interfaces/nsIIccMessenger.idl | 640 +---------- dom/icc/interfaces/nsIIccProvider.idl | 55 - dom/icc/interfaces/nsIIccService.idl | 119 +- dom/icc/interfaces/nsIStkCmdFactory.idl | 140 +++ dom/icc/interfaces/nsIStkProactiveCmd.idl | 1017 +++++++++++++++++ dom/icc/ipc/IccChild.cpp | 160 ++- dom/icc/ipc/IccChild.h | 6 + dom/icc/ipc/IccIPCUtils.cpp | 86 ++ dom/icc/ipc/IccIPCUtils.h | 35 + dom/icc/ipc/IccParent.cpp | 184 ++- dom/icc/ipc/IccParent.h | 20 + dom/icc/ipc/PIcc.ipdl | 55 + dom/icc/ipc/PIccRequest.ipdl | 12 + dom/icc/ipc/PIccTypes.ipdlh | 8 + dom/icc/moz.build | 10 +- dom/mobileconnection/MobileConnection.cpp | 3 +- .../gonk/MobileConnectionService.js | 11 +- dom/mobilemessage/gonk/MmsService.js | 58 +- dom/push/PushServiceWebSocket.jsm | 6 +- dom/simplepush/PushService.jsm | 5 +- dom/system/gonk/DataCallManager.js | 210 ++-- .../gonk/GonkGPSGeolocationProvider.cpp | 42 +- dom/system/gonk/RILContentHelper.js | 474 -------- dom/system/gonk/RILContentHelper.manifest | 20 - dom/system/gonk/RILSystemMessenger.jsm | 20 +- dom/system/gonk/RILSystemMessengerHelper.js | 8 + dom/system/gonk/RadioInterfaceLayer.js | 331 +----- dom/system/gonk/SystemWorkerManager.cpp | 1 - dom/system/gonk/TetheringService.js | 79 +- dom/system/gonk/moz.build | 2 - dom/system/gonk/nsIRadioInterfaceLayer.idl | 7 + dom/system/gonk/nsITetheringService.idl | 8 +- dom/system/gonk/nsRadioInterfaceLayer.h | 16 - .../tests/marionette/test_ril_code_quality.py | 6 - .../gonk/tests/test_ril_system_messenger.js | 18 +- dom/webidl/MozIcc.webidl | 2 +- dom/webidl/MozStkCommandEvent.webidl | 4 +- dom/wifi/WifiNetUtil.jsm | 21 +- dom/wifi/WifiP2pManager.jsm | 95 +- dom/wifi/WifiWorker.js | 145 +-- toolkit/devtools/discovery/discovery.js | 12 +- 58 files changed, 3565 insertions(+), 2033 deletions(-) create mode 100644 dom/icc/IccContact.cpp create mode 100644 dom/icc/IccContact.h rename dom/icc/gonk/{StkProactiveCmdFactory.jsm => StkCmdFactory.js} (59%) create mode 100644 dom/icc/gonk/StkCmdFactory.manifest create mode 100644 dom/icc/interfaces/nsIIccContact.idl delete mode 100644 dom/icc/interfaces/nsIIccProvider.idl create mode 100644 dom/icc/interfaces/nsIStkCmdFactory.idl create mode 100644 dom/icc/interfaces/nsIStkProactiveCmd.idl create mode 100644 dom/icc/ipc/IccIPCUtils.cpp create mode 100644 dom/icc/ipc/IccIPCUtils.h delete mode 100644 dom/system/gonk/RILContentHelper.js delete mode 100644 dom/system/gonk/RILContentHelper.manifest delete mode 100644 dom/system/gonk/nsRadioInterfaceLayer.h diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 49f7ab5527..42eb4f4954 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -183,9 +183,9 @@ var shell = { debugCrashReport('Not online, postponing.'); Services.obs.addObserver(function observer(subject, topic, state) { - let network = subject.QueryInterface(Ci.nsINetworkInterface); - if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED - && network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) { + let network = subject.QueryInterface(Ci.nsINetworkInfo); + if (network.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED + && network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) { shell.submitQueuedCrashes(); Services.obs.removeObserver(observer, topic); diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 8fd5fc9699..6cfc24637c 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -504,8 +504,8 @@ @RESPATH@/components/SmsService.js @RESPATH@/components/SmsService.manifest #endif -@RESPATH@/components/RILContentHelper.js -@RESPATH@/components/RILContentHelper.manifest +@RESPATH@/components/StkCmdFactory.js +@RESPATH@/components/StkCmdFactory.manifest @RESPATH@/components/RILSystemMessengerHelper.js @RESPATH@/components/RILSystemMessengerHelper.manifest @RESPATH@/components/TelephonyAudioService.js diff --git a/dom/bluetooth/BluetoothRilListener.cpp b/dom/bluetooth/BluetoothRilListener.cpp index a8fbd4b0af..d1ceaa3577 100644 --- a/dom/bluetooth/BluetoothRilListener.cpp +++ b/dom/bluetooth/BluetoothRilListener.cpp @@ -38,7 +38,7 @@ IccListener::NotifyIccInfoChanged() } NS_IMETHODIMP -IccListener::NotifyStkCommand(const nsAString & aMessage) +IccListener::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd) { return NS_OK; } diff --git a/dom/bluetooth/bluetooth2/BluetoothRilListener.cpp b/dom/bluetooth/bluetooth2/BluetoothRilListener.cpp index 79adcb053e..ac3c78b8e9 100644 --- a/dom/bluetooth/bluetooth2/BluetoothRilListener.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothRilListener.cpp @@ -37,7 +37,7 @@ IccListener::NotifyIccInfoChanged() } NS_IMETHODIMP -IccListener::NotifyStkCommand(const nsAString & aMessage) +IccListener::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd) { return NS_OK; } diff --git a/dom/icc/Icc.cpp b/dom/icc/Icc.cpp index 3f482ceb40..e1deecfe65 100644 --- a/dom/icc/Icc.cpp +++ b/dom/icc/Icc.cpp @@ -7,19 +7,21 @@ #include "mozilla/dom/Icc.h" #include "IccCallback.h" +#include "IccContact.h" +#include "mozilla/dom/ContactsBinding.h" #include "mozilla/dom/DOMRequest.h" #include "mozilla/dom/IccInfo.h" #include "mozilla/dom/MozStkCommandEvent.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "nsIIccInfo.h" -#include "nsIIccProvider.h" #include "nsIIccService.h" -#include "nsJSON.h" -#include "nsRadioInterfaceLayer.h" +#include "nsIStkCmdFactory.h" +#include "nsIStkProactiveCmd.h" #include "nsServiceManagerUtils.h" using mozilla::dom::icc::IccCallback; +using mozilla::dom::icc::IccContact; namespace mozilla { namespace dom { @@ -56,25 +58,16 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(Icc, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(Icc, DOMEventTargetHelper) -Icc::Icc(nsPIDOMWindow* aWindow, long aClientId, nsIIcc* aHandler, nsIIccInfo* aIccInfo) +Icc::Icc(nsPIDOMWindow* aWindow, nsIIcc* aHandler, nsIIccInfo* aIccInfo) : mLive(true) - , mClientId(aClientId) , mHandler(aHandler) { BindToOwner(aWindow); - mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID); - if (aIccInfo) { aIccInfo->GetIccid(mIccId); UpdateIccInfo(aIccInfo); } - - // Not being able to acquire the provider isn't fatal since we check - // for it explicitly below. - if (!mProvider) { - NS_WARNING("Could not acquire nsIIccProvider!"); - } } Icc::~Icc() @@ -85,7 +78,6 @@ void Icc::Shutdown() { mIccInfo.SetNull(); - mProvider = nullptr; mHandler = nullptr; mLive = false; } @@ -97,7 +89,7 @@ Icc::NotifyEvent(const nsAString& aName) } nsresult -Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage) +Icc::NotifyStkEvent(const nsAString& aName, nsIStkProactiveCmd* aStkProactiveCmd) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetOwner()))) { @@ -106,13 +98,12 @@ Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage) JSContext* cx = jsapi.cx(); JS::Rooted value(cx); - if (!aMessage.IsEmpty()) { - nsCOMPtr json(new nsJSON()); - nsresult rv = json->DecodeToJSVal(aMessage, cx, &value); - NS_ENSURE_SUCCESS(rv, rv); - } else { - value = JS::NullValue(); - } + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, NS_ERROR_UNEXPECTED); + + cmdFactory->CreateCommandMessage(aStkProactiveCmd, &value); + NS_ENSURE_TRUE(value.isObject(), NS_ERROR_UNEXPECTED); MozStkCommandEventInit init; init.mBubbles = false; @@ -193,13 +184,33 @@ void Icc::SendStkResponse(const JSContext* aCx, JS::Handle aCommand, JS::Handle aResponse, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return; } - nsresult rv = mProvider->SendStkResponse(mClientId, GetOwner(), aCommand, - aResponse); + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + if (!cmdFactory) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsCOMPtr command; + cmdFactory->CreateCommand(aCommand, getter_AddRefs(command)); + if (!command) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsCOMPtr response; + cmdFactory->CreateResponse(aResponse, getter_AddRefs(response)); + if (!response) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsresult rv = mHandler->SendStkResponse(command, response); if (NS_FAILED(rv)) { aRv.Throw(rv); } @@ -209,15 +220,12 @@ void Icc::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return; } - nsresult rv = mProvider->SendStkMenuSelection(mClientId, - GetOwner(), - aItemIdentifier, - aHelpRequested); + nsresult rv = mHandler->SendStkMenuSelection(aItemIdentifier, aHelpRequested); if (NS_FAILED(rv)) { aRv.Throw(rv); } @@ -227,13 +235,38 @@ void Icc::SendStkTimerExpiration(const JSContext* aCx, JS::Handle aTimer, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return; } - nsresult rv = mProvider->SendStkTimerExpiration(mClientId, GetOwner(), - aTimer); + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + if (!cmdFactory) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsCOMPtr timer; + cmdFactory->CreateTimer(aTimer, getter_AddRefs(timer)); + if (!timer) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + uint16_t timerId; + nsresult rv = timer->GetTimerId(&timerId); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + } + + uint32_t timerValue; + rv = timer->GetTimerValue(&timerValue); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + } + + rv = mHandler->SendStkTimerExpiration(timerId, timerValue); if (NS_FAILED(rv)) { aRv.Throw(rv); } @@ -243,12 +276,26 @@ void Icc::SendStkEventDownload(const JSContext* aCx, JS::Handle aEvent, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return; } - nsresult rv = mProvider->SendStkEventDownload(mClientId, GetOwner(), aEvent); + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + if (!cmdFactory) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsCOMPtr event; + cmdFactory->CreateEvent(aEvent, getter_AddRefs(event)); + if (!event) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsresult rv = mHandler->SendStkEventDownload(event); if (NS_FAILED(rv)) { aRv.Throw(rv); } @@ -363,44 +410,55 @@ Icc::GetCardLockRetryCount(IccLockType aLockType, ErrorResult& aRv) already_AddRefed Icc::ReadContacts(IccContactType aContactType, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } - nsRefPtr request; - nsresult rv = mProvider->ReadContacts(mClientId, GetOwner(), - static_cast(aContactType), - getter_AddRefs(request)); + nsRefPtr request = new DOMRequest(GetOwner()); + nsRefPtr requestCallback = + new IccCallback(GetOwner(), request); + + nsresult rv = mHandler->ReadContacts(static_cast(aContactType), + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } - return request.forget().downcast(); + return request.forget(); } already_AddRefed -Icc::UpdateContact(const JSContext* aCx, IccContactType aContactType, - JS::Handle aContact, const nsAString& aPin2, - ErrorResult& aRv) +Icc::UpdateContact(IccContactType aContactType, mozContact& aContact, + const nsAString& aPin2, ErrorResult& aRv) { - if (!mProvider) { + if (!mHandler) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } - nsRefPtr request; - nsresult rv = mProvider->UpdateContact(mClientId, GetOwner(), - static_cast(aContactType), - aContact, aPin2, - getter_AddRefs(request)); + nsRefPtr request = new DOMRequest(GetOwner()); + nsRefPtr requestCallback = + new IccCallback(GetOwner(), request); + + nsCOMPtr iccContact; + nsresult rv = IccContact::Create(aContact, getter_AddRefs(iccContact)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } - return request.forget().downcast(); + rv = mHandler->UpdateContact(static_cast(aContactType), + iccContact, + aPin2, + requestCallback); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + + return request.forget(); } already_AddRefed diff --git a/dom/icc/Icc.h b/dom/icc/Icc.h index 6c2698f8e7..1a0a452e65 100644 --- a/dom/icc/Icc.h +++ b/dom/icc/Icc.h @@ -13,12 +13,14 @@ class nsIIcc; class nsIIccInfo; class nsIIccProvider; +class nsIStkProactiveCmd; namespace mozilla { namespace dom { class DOMRequest; class OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo; +class mozContact; class Promise; class Icc final : public DOMEventTargetHelper @@ -28,8 +30,7 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Icc, DOMEventTargetHelper) NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper) - Icc(nsPIDOMWindow* aWindow, long aClientId, - nsIIcc* aHandler, nsIIccInfo* aIccInfo); + Icc(nsPIDOMWindow* aWindow, nsIIcc* aHandler, nsIIccInfo* aIccInfo); void Shutdown(); @@ -38,7 +39,7 @@ public: NotifyEvent(const nsAString& aName); nsresult - NotifyStkEvent(const nsAString& aName, const nsAString& aMessage); + NotifyStkEvent(const nsAString& aName, nsIStkProactiveCmd* aStkProactiveCmd); nsString GetIccId() @@ -98,9 +99,8 @@ public: ReadContacts(IccContactType aContactType, ErrorResult& aRv); already_AddRefed - UpdateContact(const JSContext* aCx, IccContactType aContactType, - JS::Handle aContact, const nsAString& aPin2, - ErrorResult& aRv); + UpdateContact(IccContactType aContactType, mozContact& aContact, + const nsAString& aPin2, ErrorResult& aRv); already_AddRefed MatchMvno(IccMvnoType aMvnoType, const nsAString& aMatchData, @@ -121,11 +121,7 @@ private: ~Icc(); bool mLive; - uint32_t mClientId; nsString mIccId; - // mProvider is a xpcom service and will be released at Shutdown(), so it - // doesn't need to be cycle collected. - nsCOMPtr mProvider; // mHandler will be released at Shutdown(), so there is no need to join cycle // collection. nsCOMPtr mHandler; diff --git a/dom/icc/IccCallback.cpp b/dom/icc/IccCallback.cpp index 4bfcb67843..d4abcba459 100644 --- a/dom/icc/IccCallback.cpp +++ b/dom/icc/IccCallback.cpp @@ -6,10 +6,12 @@ #include "IccCallback.h" +#include "mozilla/dom/ContactsBinding.h" #include "mozilla/dom/IccCardLockError.h" #include "mozilla/dom/MozIccBinding.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ToJSValue.h" +#include "nsIIccContact.h" #include "nsJSUtils.h" #include "nsServiceManagerUtils.h" @@ -17,6 +19,97 @@ namespace mozilla { namespace dom { namespace icc { +namespace { + +static nsresult +IccContactToMozContact(JSContext* aCx, GlobalObject& aGlobal, + nsIIccContact* aIccContact, + mozContact** aMozContact) +{ + *aMozContact = nullptr; + + ContactProperties properties; + + // Names + char16_t** rawStringArray = nullptr; + uint32_t count = 0; + nsresult rv = aIccContact->GetNames(&count, &rawStringArray); + NS_ENSURE_SUCCESS(rv, rv); + if (count > 0) { + Sequence& nameSeq = properties.mName.Construct().SetValue(); + for (uint32_t i = 0; i < count; i++) { + nameSeq.AppendElement(nsDependentString(rawStringArray[i]), fallible); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } + + // Numbers + rawStringArray = nullptr; + count = 0; + rv = aIccContact->GetNumbers(&count, &rawStringArray); + NS_ENSURE_SUCCESS(rv, rv); + if (count > 0) { + Sequence& numberSeq = properties.mTel.Construct().SetValue(); + for (uint32_t i = 0; i < count; i++) { + ContactTelField number; + number.mValue.Construct() = nsDependentString(rawStringArray[i]); + numberSeq.AppendElement(number, fallible); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } + + // Emails + rawStringArray = nullptr; + count = 0; + rv = aIccContact->GetEmails(&count, &rawStringArray); + NS_ENSURE_SUCCESS(rv, rv); + if (count > 0) { + Sequence& emailSeq = properties.mEmail.Construct().SetValue(); + for (uint32_t i = 0; i < count; i++) { + ContactField email; + email.mValue.Construct() = nsDependentString(rawStringArray[i]); + emailSeq.AppendElement(email, fallible); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } + + ErrorResult er; + nsRefPtr contact + = mozContact::Constructor(aGlobal, aCx, properties, er); + NS_ENSURE_FALSE(er.Failed(), er.StealNSResult()); + + nsAutoString contactId; + rv = aIccContact->GetId(contactId); + NS_ENSURE_SUCCESS(rv, rv); + + contact->SetId(contactId, er); + NS_ENSURE_FALSE(er.Failed(), er.StealNSResult()); + + contact.forget(aMozContact); + + return NS_OK; +} + +static NS_IMETHODIMP +IccContactListToMozContactList(JSContext* aCx, GlobalObject& aGlobal, + nsIIccContact** aContacts, uint32_t aCount, + nsTArray>& aContactList) +{ + aContactList.SetCapacity(aCount); + for (uint32_t i = 0; i < aCount ; i++) { + nsRefPtr contact; + nsresult rv = + IccContactToMozContact(aCx, aGlobal, aContacts[i], getter_AddRefs(contact)); + NS_ENSURE_SUCCESS(rv, rv); + + aContactList.AppendElement(contact); + } + + return NS_OK; +} + +} // anonymous namespace + NS_IMPL_ISUPPORTS(IccCallback, nsIIccCallback) IccCallback::IccCallback(nsPIDOMWindow* aWindow, DOMRequest* aRequest, @@ -132,6 +225,64 @@ IccCallback::NotifyCardLockError(const nsAString & aErrorMsg, return NS_OK; } +NS_IMETHODIMP +IccCallback::NotifyRetrievedIccContacts(nsIIccContact** aContacts, + uint32_t aCount) +{ + MOZ_ASSERT(aContacts); + + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mWindow))) { + return NS_ERROR_FAILURE; + } + + JSContext* cx = jsapi.cx(); + nsCOMPtr go = do_QueryInterface(mWindow); + GlobalObject global(cx, go->GetGlobalJSObject()); + + nsTArray> contactList; + + nsresult rv = + IccContactListToMozContactList(cx, global, aContacts, aCount, contactList); + NS_ENSURE_SUCCESS(rv, rv); + + JS::Rooted jsResult(cx); + + if (!ToJSValue(cx, contactList, &jsResult)) { + return NS_ERROR_FAILURE; + } + + return NotifySuccess(jsResult); +} + +NS_IMETHODIMP +IccCallback::NotifyUpdatedIccContact(nsIIccContact* aContact) +{ + MOZ_ASSERT(aContact); + + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mWindow))) { + return NS_ERROR_FAILURE; + } + + JSContext* cx = jsapi.cx(); + nsCOMPtr go = do_QueryInterface(mWindow); + GlobalObject global(cx, go->GetGlobalJSObject()); + + nsRefPtr mozContact; + nsresult rv = + IccContactToMozContact(cx, global, aContact, getter_AddRefs(mozContact)); + NS_ENSURE_SUCCESS(rv, rv); + + JS::Rooted jsResult(cx); + + if (!ToJSValue(cx, mozContact, &jsResult)) { + return NS_ERROR_FAILURE; + } + + return NotifySuccess(jsResult); +} + } // namespace icc } // namespace dom } // namespace mozilla \ No newline at end of file diff --git a/dom/icc/IccContact.cpp b/dom/icc/IccContact.cpp new file mode 100644 index 0000000000..da5ec6d38c --- /dev/null +++ b/dom/icc/IccContact.cpp @@ -0,0 +1,145 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "IccContact.h" +#include "mozilla/dom/ContactsBinding.h" +#include "nsReadableUtils.h" + +using namespace mozilla::dom::icc; + +using mozilla::dom::mozContact; + +NS_IMPL_ISUPPORTS(IccContact, nsIIccContact) + +/* static */ nsresult +IccContact::Create(mozContact& aMozContact, nsIIccContact** aIccContact) +{ + *aIccContact = nullptr; + ErrorResult er; + + // Id + nsAutoString id; + aMozContact.GetId(id, er); + NS_ENSURE_SUCCESS(er.StealNSResult(), NS_ERROR_FAILURE); + + // Names + Nullable> names; + aMozContact.GetName(names, er); + NS_ENSURE_SUCCESS(er.StealNSResult(), NS_ERROR_FAILURE); + if (names.IsNull()) { + // Set as Empty nsTarray for IccContact constructor. + names.SetValue(); + } + + // Numbers + Nullable> nullableNumberList; + aMozContact.GetTel(nullableNumberList, er); + NS_ENSURE_SUCCESS(er.StealNSResult(), NS_ERROR_FAILURE); + nsTArray numbers; + if (!nullableNumberList.IsNull()) { + const nsTArray& numberList = nullableNumberList.Value(); + for (uint32_t i = 0; i < numberList.Length(); i++) { + if (numberList[i].mValue.WasPassed()) { + numbers.AppendElement(numberList[i].mValue.Value()); + } + } + } + + // Emails + Nullable> nullableEmailList; + aMozContact.GetEmail(nullableEmailList, er); + NS_ENSURE_SUCCESS(er.StealNSResult(), NS_ERROR_FAILURE); + nsTArray emails; + if (!nullableEmailList.IsNull()) { + const nsTArray& emailList = nullableEmailList.Value(); + for (uint32_t i = 0; i < emailList.Length(); i++) { + if (emailList[i].mValue.WasPassed()) { + emails.AppendElement(emailList[i].mValue.Value()); + } + } + } + + nsCOMPtr iccContact = new IccContact(id, + names.Value(), + numbers, + emails); + iccContact.forget(aIccContact); + + return NS_OK; +} + +/*static*/ nsresult +IccContact::Create(const nsAString& aId, + const nsTArray& aNames, + const nsTArray& aNumbers, + const nsTArray& aEmails, + nsIIccContact** aIccContact) +{ + *aIccContact = nullptr; + + nsCOMPtr iccContact = new IccContact(aId, + aNames, + aNumbers, + aEmails); + iccContact.forget(aIccContact); + + return NS_OK; +} + +IccContact::IccContact(const nsAString& aId, + const nsTArray& aNames, + const nsTArray& aNumbers, + const nsTArray& aEmails) + : mId(aId), + mNames(aNames), + mNumbers(aNumbers), + mEmails(aEmails) +{ +} + +// nsIIccInfo implementation. + +NS_IMETHODIMP IccContact::GetId(nsAString & aId) +{ + aId = mId; + return NS_OK; +} + +#define ICCCONTACT_IMPL_GET_CONTACT_FIELD(_field) \ +NS_IMETHODIMP IccContact::Get##_field(uint32_t* aCount, char16_t*** a##_field) \ +{ \ + NS_ENSURE_ARG_POINTER(aCount); \ + NS_ENSURE_ARG_POINTER(a##_field); \ + \ + *aCount = 0; \ + *a##_field = nullptr; \ + \ + uint32_t count = m##_field.Length(); \ + if (count == 0) { \ + return NS_OK; \ + } \ + char16_t** temp = \ + static_cast(moz_xmalloc(sizeof(char16_t*) * (count))); \ + if (temp == nullptr) { \ + return NS_ERROR_OUT_OF_MEMORY; \ + } \ + for (uint32_t i = 0; i < count; i++) { \ + (temp)[i] = ToNewUnicode(m##_field[i]); \ + if (!(temp)[i]) { \ + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, temp); \ + return NS_ERROR_OUT_OF_MEMORY; \ + } \ + } \ + \ + *aCount = count; \ + *a##_field = temp; \ + \ + return NS_OK; \ +} + +ICCCONTACT_IMPL_GET_CONTACT_FIELD(Names) +ICCCONTACT_IMPL_GET_CONTACT_FIELD(Numbers) +ICCCONTACT_IMPL_GET_CONTACT_FIELD(Emails) + +#undef ICCCONTACT_GET_CONTACT_FIELD diff --git a/dom/icc/IccContact.h b/dom/icc/IccContact.h new file mode 100644 index 0000000000..4234a18610 --- /dev/null +++ b/dom/icc/IccContact.h @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_icc_IccContact_h +#define mozilla_dom_icc_IccContact_h + +#include "nsIIccContact.h" + +namespace mozilla { +namespace dom { +class mozContact; +namespace icc { + +class IccContact : public nsIIccContact +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIICCCONTACT + + static nsresult + Create(mozContact& aMozContact, + nsIIccContact** aIccContact); + + static nsresult + Create(const nsAString& aId, + const nsTArray& aNames, + const nsTArray& aNumbers, + const nsTArray& aEmails, + nsIIccContact** aIccContact); + +private: + IccContact(const nsAString& aId, + const nsTArray& aNames, + const nsTArray& aNumbers, + const nsTArray& aEmails); + virtual ~IccContact() {} + + nsString mId; + nsTArray mNames; + nsTArray mNumbers; + nsTArray mEmails; +}; + +} // namespace icc +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_icc_IccContact_h + diff --git a/dom/icc/IccListener.cpp b/dom/icc/IccListener.cpp index 06321dc15a..977538c2ca 100644 --- a/dom/icc/IccListener.cpp +++ b/dom/icc/IccListener.cpp @@ -10,7 +10,6 @@ #include "IccManager.h" #include "nsIDOMClassInfo.h" #include "nsIIccInfo.h" -#include "nsRadioInterfaceLayer.h" using namespace mozilla::dom; @@ -22,15 +21,6 @@ IccListener::IccListener(IccManager* aIccManager, uint32_t aClientId) { MOZ_ASSERT(mIccManager); - // TODO: Bug 1114938, Refactor STK in MozIcc.webidl with IPDL. - // Remove the registration to IccProvider. - mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID); - - if (!mProvider) { - NS_WARNING("Could not acquire nsIIccProvider!"); - return; - } - nsCOMPtr iccService = do_GetService(ICC_SERVICE_CONTRACTID); if (!iccService) { @@ -50,17 +40,13 @@ IccListener::IccListener(IccManager* aIccManager, uint32_t aClientId) nsString iccId; iccInfo->GetIccid(iccId); if (!iccId.IsEmpty()) { - mIcc = new Icc(mIccManager->GetOwner(), mClientId, mHandler, iccInfo); + mIcc = new Icc(mIccManager->GetOwner(), mHandler, iccInfo); } } DebugOnly rv = mHandler->RegisterListener(this); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed registering icc listener with Icc Handler"); - - rv = mProvider->RegisterIccMsg(mClientId, this); - NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), - "Failed registering icc messages with provider"); } IccListener::~IccListener() @@ -71,13 +57,6 @@ IccListener::~IccListener() void IccListener::Shutdown() { - // TODO: Bug 1114938, Refactor STK in MozIcc.webidl with IPDL. - // Remove the unregistration to IccProvider. - if (mProvider) { - mProvider->UnregisterIccMsg(mClientId, this); - mProvider = nullptr; - } - if (mHandler) { mHandler->UnregisterListener(this); mHandler = nullptr; @@ -94,13 +73,13 @@ IccListener::Shutdown() // nsIIccListener NS_IMETHODIMP -IccListener::NotifyStkCommand(const nsAString& aMessage) +IccListener::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd) { if (!mIcc) { return NS_OK; } - return mIcc->NotifyStkEvent(NS_LITERAL_STRING("stkcommand"), aMessage); + return mIcc->NotifyStkEvent(NS_LITERAL_STRING("stkcommand"), aStkProactiveCmd); } NS_IMETHODIMP @@ -143,7 +122,7 @@ IccListener::NotifyIccInfoChanged() nsString iccId; iccInfo->GetIccid(iccId); if (!iccId.IsEmpty()) { - mIcc = new Icc(mIccManager->GetOwner(), mClientId, mHandler, iccInfo); + mIcc = new Icc(mIccManager->GetOwner(), mHandler, iccInfo); mIccManager->NotifyIccAdd(iccId); mIcc->NotifyEvent(NS_LITERAL_STRING("iccinfochange")); } diff --git a/dom/icc/IccListener.h b/dom/icc/IccListener.h index 0798282431..94e7801ca7 100644 --- a/dom/icc/IccListener.h +++ b/dom/icc/IccListener.h @@ -8,7 +8,6 @@ #define mozilla_dom_IccListener_h #include "nsAutoPtr.h" -#include "nsIIccProvider.h" #include "nsIIccService.h" namespace mozilla { @@ -45,9 +44,6 @@ private: // IccListener, this will release the reference and break the cycle. nsRefPtr mIcc; nsRefPtr mIccManager; - // mProvider is a xpcom service and will be released at Shutdown(), so it - // doesn't need to be cycle collected. - nsCOMPtr mProvider; // mHandler will be released at Shutdown(), there is no need to join cycle // collection. nsCOMPtr mHandler; diff --git a/dom/icc/gonk/IccService.js b/dom/icc/gonk/IccService.js index ffd581bba1..3be5b7471f 100644 --- a/dom/icc/gonk/IccService.js +++ b/dom/icc/gonk/IccService.js @@ -29,6 +29,14 @@ XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService", "@mozilla.org/mobileconnection/mobileconnectionservice;1", "nsIGonkMobileConnectionService"); +XPCOMUtils.defineLazyServiceGetter(this, "gIccMessenger", + "@mozilla.org/ril/system-messenger-helper;1", + "nsIIccMessenger"); + +XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory", + "@mozilla.org/icc/stkcmdfactory;1", + "nsIStkCmdFactory"); + let DEBUG = RIL.DEBUG_RIL; function debug(s) { dump("IccService: " + s); @@ -72,6 +80,86 @@ CdmaIccInfo.prototype = { prlVersion: 0 }; +function IccContact(aContact) { + this.id = aContact.contactId || null; + this._names = []; + this._numbers = []; + this._emails = []; + + if (aContact.alphaId) { + this._names.push(aContact.alphaId); + } + + if (aContact.number) { + this._numbers.push(aContact.number); + } + + let anrLen = aContact.anr ? aContact.anr.length : 0; + for (let i = 0; i < anrLen; i++) { + this._numbers.push(anr[i]); + } + + if (aContact.email) { + this._emails.push(aContact.email); + } +} +IccContact.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccContact]), + + _names: null, + _numbers: null, + _emails: null, + + // nsIIccContact + + id: null, + + getNames: function(aCount) { + if (!this._names) { + if (aCount) { + aCount.value = 0; + } + return null; + } + + if (aCount) { + aCount.value = this._names.length; + } + + return this._names.slice(); + }, + + getNumbers: function(aCount) { + if (!this._numbers) { + if (aCount) { + aCount.value = 0; + } + return null; + } + + if (aCount) { + aCount.value = this._numbers.length; + } + + return this._numbers.slice(); + }, + + getEmails: function(aCount) { + if (!this._emails) { + if (aCount) { + aCount.value = 0; + } + return null; + } + + if (aCount) { + aCount.value = this._emails.length; + } + + return this._emails.slice(); + }, +}; + function IccService() { this._iccs = []; @@ -124,6 +212,27 @@ IccService.prototype = { /** * nsIGonkIccService interface. */ + notifyStkCommand: function(aServiceId, aStkcommand) { + if (DEBUG) { + debug("notifyStkCommand for service Id: " + aServiceId); + } + + let icc = this.getIccByServiceId(aServiceId); + + gIccMessenger.notifyStkProactiveCommand(icc.iccInfo.iccid, aStkcommand); + + icc._deliverListenerEvent("notifyStkCommand", [aStkcommand]); + }, + + notifyStkSessionEnd: function(aServiceId) { + if (DEBUG) { + debug("notifyStkSessionEnd for service Id: " + aServiceId); + } + + this.getIccByServiceId(aServiceId) + ._deliverListenerEvent("notifyStkSessionEnd"); + }, + notifyCardStateChanged: function(aServiceId, aCardState) { if (DEBUG) { debug("notifyCardStateChanged for service Id: " + aServiceId + @@ -536,7 +645,97 @@ Icc.prototype = { aCallback.notifyCloseChannelSuccess(); }); - } + }, + + sendStkResponse: function(aCommand, aResponse) { + let response = gStkCmdFactory.createResponseMessage(aResponse); + response.command = gStkCmdFactory.createCommandMessage(aCommand); + this._radioInterface.sendWorkerMessage("sendStkTerminalResponse", response); + }, + + sendStkMenuSelection: function(aItemIdentifier, aHelpRequested) { + this._radioInterface + .sendWorkerMessage("sendStkMenuSelection", { + itemIdentifier: aItemIdentifier, + helpRequested: aHelpRequested + }); + }, + + sendStkTimerExpiration: function(aTimerId, aTimerValue) { + this._radioInterface + .sendWorkerMessage("sendStkTimerExpiration",{ + timer: { + timerId: aTimerId, + timerValue: aTimerValue + } + }); + }, + + sendStkEventDownload: function(aEvent) { + this._radioInterface + .sendWorkerMessage("sendStkEventDownload", + { event: gStkCmdFactory.createEventMessage(aEvent) }); + }, + + readContacts: function(aContactType, aCallback) { + this._radioInterface + .sendWorkerMessage("readICCContacts", + { contactType: aContactType }, + (aResponse) => { + if (aResponse.errorMsg) { + aCallback.notifyError(aResponse.errorMsg); + return; + } + + let iccContacts = []; + + aResponse.contacts.forEach(c => iccContacts.push(new IccContact(c))); + + aCallback.notifyRetrievedIccContacts(iccContacts, iccContacts.length); + }); + }, + + updateContact: function(aContactType, aContact, aPin2, aCallback) { + let iccContact = { contactId: aContact.id }; + let count = { value: 0 }; + let names = aContact.getNames(count); + if (count.value > 0) { + iccContact.alphaId = names[0]; + } + + let numbers = aContact.getNumbers(count); + if (count.value > 0) { + iccContact.number = numbers[0]; + + let anrArray = numbers.slice(1); + let length = anrArray.length; + if (length > 0) { + iccContact.anr = []; + for (let i = 0; i < length; i++) { + iccContact.anr.push(anrArray[i].value); + } + } + } + + let emails = aContact.getEmails(count); + if (count.value > 0) { + iccContact.email = emails[0]; + } + + this._radioInterface + .sendWorkerMessage("updateICCContact", + { contactType: aContactType, + contact: iccContact, + pin2: aPin2 }, + (aResponse) => { + if (aResponse.errorMsg) { + aCallback.notifyError(aResponse.errorMsg); + return; + } + + aCallback.notifyUpdatedIccContact(new IccContact(aResponse.contact)); + }); + }, }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([IccService]); diff --git a/dom/icc/gonk/StkProactiveCmdFactory.jsm b/dom/icc/gonk/StkCmdFactory.js similarity index 59% rename from dom/icc/gonk/StkProactiveCmdFactory.jsm rename to dom/icc/gonk/StkCmdFactory.js index ef16cffa9f..defca445ac 100644 --- a/dom/icc/gonk/StkProactiveCmdFactory.jsm +++ b/dom/icc/gonk/StkCmdFactory.js @@ -11,6 +11,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); let RIL = {}; Cu.import("resource://gre/modules/ril_consts.js", RIL); +const GONK_STKCMDFACTORY_CONTRACTID = "@mozilla.org/icc/stkcmdfactory;1"; +const GONK_STKCMDFACTORY_CID = Components.ID("{7a663440-e336-11e4-8fd5-c3140a7ff307}"); + /** * Helper Utilities to convert JS Objects to IDL Objects. */ @@ -64,7 +67,7 @@ function appendIconInfo(aTarget, aStkIconInfo) { /** * The implementation of the data types used in variant types of - * StkProactiveCommand. + * StkProactiveCommand, StkTerminalResponse, StkDownloadEvent. */ function StkDuration(aTimeUnit, aTimeInterval) { @@ -177,11 +180,27 @@ StkTimer.prototype = { // nsIStkTimer timerId: 0, timerValue: Ci.nsIStkTimer.TIMER_VALUE_INVALID, - timerAction: 0 + timerAction: Ci.nsIStkTimer.TIMER_ACTION_INVALID +}; + +function StkLocationInfo(aMcc, aMnc, aGsmLocationAreaCode, aGsmCellId) { + this.mcc = aMcc; + this.mnc = aMnc; + this.gsmLocationAreaCode = aGsmLocationAreaCode; + this.gsmCellId = aGsmCellId; +} +StkLocationInfo.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkLocationInfo]), + + // nsIStkLocationInfo + mcc: null, + mnc: null, + gsmLocationAreaCode: -1, + gsmCellId: -1 }; /** - * The implementation of nsIStkProactiveCommand Set and STK System Message Set. + * The implementation of nsIStkProactiveCommand set and paired JS object set. */ function StkProactiveCommand(aCommandDetails) { this.commandNumber = aCommandDetails.commandNumber; @@ -995,14 +1014,444 @@ QueriedIFs[RIL.STK_CMD_CLOSE_CHANNEL] = Ci.nsIStkTextMessageCmd; QueriedIFs[RIL.STK_CMD_SEND_DATA] = Ci.nsIStkTextMessageCmd; QueriedIFs[RIL.STK_CMD_RECEIVE_DATA] = Ci.nsIStkTextMessageCmd; +/** + * The implementation of nsIStkTerminalResponse set and paired JS object set. + */ +function StkTerminalResponse(aResponseMessage) { + this.resultCode = aResponseMessage.resultCode; + if (aResponseMessage.additionalInformation != undefined) { + this.additionalInformation = aResponseMessage.additionalInformation; + } +} +StkTerminalResponse.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse]), + + // nsIStkTerminalResponse + resultCode: 0, + additionalInformation: Ci.nsIStkTerminalResponse.ADDITIONAL_INFO_INVALID +}; + +function StkResponseMessage(aStkTerminalResponse) { + this.resultCode = aStkTerminalResponse.resultCode; + if (aStkTerminalResponse.additionalInformation + !== Ci.nsIStkTerminalResponse.ADDITIONAL_INFO_INVALID) { + this.additionalInformation = aStkTerminalResponse.additionalInformation; + } +} +StkResponseMessage.prototype = { + resultCode: Ci.nsIStkTerminalResponse.RESULT_OK +}; + +function StkSelectItemResponse(aStkSelectItemResponseMessage) { + // Call |StkTerminalResponse| constructor. + StkTerminalResponse.call(this, aStkSelectItemResponseMessage); + this.itemIdentifier = aStkSelectItemResponseMessage.itemIdentifier; +} +StkSelectItemResponse.prototype = Object.create(StkTerminalResponse.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse, + Ci.nsIStkSelectItemResponse]) + }, + + // nsIStkSelectItemResponse + itemIdentifier: { value: 0, writable: true } +}); + +function StkSelectItemResponseMessage(aStkSelectItemResponse) { + // Call |StkResponseMessage| constructor. + StkResponseMessage.call(this, aStkSelectItemResponse); + + this.itemIdentifier = aStkSelectItemResponse.itemIdentifier; +} +StkSelectItemResponseMessage.prototype = Object.create(StkResponseMessage.prototype); + +function StkGetInputResponse(aStkGetInputResponseMessage) { + // Call |StkTerminalResponse| constructor. + StkTerminalResponse.call(this, aStkGetInputResponseMessage); + if (aStkGetInputResponseMessage.isYesNo !== undefined) { + this.isYesNo = (aStkGetInputResponseMessage.isYesNo) + ? Ci.nsIStkGetInputResponse.YES + : Ci.nsIStkGetInputResponse.NO; + } + + if (aStkGetInputResponseMessage.input !== undefined) { + // We expect input to be "" if user confirmed the input with nothing, + // and we use null to present 'undefined' internally for the conversion + // between nsIStkTerminalResponse and JS objects. + this.input = aStkGetInputResponseMessage.input || ""; + } + +} +StkGetInputResponse.prototype = Object.create(StkTerminalResponse.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse, + Ci.nsIStkGetInputResponse]) + }, + + // nsIStkGetInputResponse + isYesNo: { value: Ci.nsIStkGetInputResponse.YES_NO_INVALID, writable: true }, + input: { value: null, writable: true } +}); + +function StkGetInputResponseMessage(aStkGetInputResponse) { + // Call |StkResponseMessage| constructor. + StkResponseMessage.call(this, aStkGetInputResponse); + + if (aStkGetInputResponse.isYesNo !== Ci.nsIStkGetInputResponse.YES_NO_INVALID) { + this.isYesNo = !!aStkGetInputResponse.isYesNo; + } + + if (aStkGetInputResponse.input !== null) { + this.input = aStkGetInputResponse.input; + } +} +StkGetInputResponseMessage.prototype = Object.create(StkResponseMessage.prototype); + +function StkCallSetupResponse(aStkCallSetupResponseMessage) { + // Call |StkTerminalResponse| constructor. + StkTerminalResponse.call(this, aStkCallSetupResponseMessage); + this.hasConfirmed = !! aStkCallSetupResponseMessage.hasConfirmed; +} +StkCallSetupResponse.prototype = Object.create(StkTerminalResponse.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse, + Ci.nsIStkCallSetupResponse]) + }, + + // nsIStkCallSetupResponse + hasConfirmed: { value: false, writable: true } +}); + +function StkCallSetupResponseMessage(aStkCallSetupResponse) { + // Call |StkResponseMessage| constructor. + StkResponseMessage.call(this, aStkCallSetupResponse); + + this.hasConfirmed = aStkCallSetupResponse.hasConfirmed; +} +StkCallSetupResponseMessage.prototype = Object.create(StkResponseMessage.prototype); + +function StkLocalInfoResponse(aStkLocalInfoResponseMessage) { + // Call |StkTerminalResponse| constructor. + StkTerminalResponse.call(this, aStkLocalInfoResponseMessage); + + let localInfo = aStkLocalInfoResponseMessage.localInfo; + + if (localInfo.imei) { + this.imei = localInfo.imei; + return; + } + + if (localInfo.locationInfo) { + let info = localInfo.locationInfo; + + this.locationInfo = new StkLocationInfo(info.mcc, + info.mnc, + info.gsmLocationAreaCode, + info.gsmCellId); + return; + } + + if (localInfo.date) { + if (localInfo.date instanceof Date) { + this.date = localInfo.date.getTime(); + } else { + // JSON is adopted as our IPDL protocol, so Date object will be presented as + // a String in ISO8601 format by JSON. + // For the conversion between Date and JSON, please see: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON#Example:_Using_toJSON + this.date = new Date(localInfo.date).getTime(); + } + + return; + } + + if (localInfo.language) { + this.language = localInfo.language; + return; + } +} +StkLocalInfoResponse.prototype = Object.create(StkTerminalResponse.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse, + Ci.nsIStkLocalInfoResponse]) + }, + + // nsIStkLocalInfoResponse + imei: { value: null, writable: true }, + locationInfo: { value: null, writable: true }, + date: { value: Ci.nsIStkLocalInfoResponse.DATE_INVALID, writable: true }, + language: { value: null, writable: true }, +}); + +function StkLocalInfoResponseMessage(aStkLocalInfoResponse) { + // Call |StkResponseMessage| constructor. + StkResponseMessage.call(this, aStkLocalInfoResponse); + + let localInfo = this.localInfo = {}; + + if (aStkLocalInfoResponse.imei) { + localInfo.imei = aStkLocalInfoResponse.imei; + return; + } + + if (aStkLocalInfoResponse.locationInfo) { + let srcInfo = aStkLocalInfoResponse.locationInfo; + let destInfo = localInfo.locationInfo = {}; + + destInfo.mcc = srcInfo.mcc; + destInfo.mnc = srcInfo.mnc; + destInfo.gsmLocationAreaCode = srcInfo.gsmLocationAreaCode; + destInfo.gsmCellId = srcInfo.gsmCellId; + + return; + } + + if (aStkLocalInfoResponse.date !== Ci.nsIStkLocalInfoResponse.DATE_INVALID) { + localInfo.date = new Date(aStkLocalInfoResponse.date); + return; + } + + if (aStkLocalInfoResponse.language) { + localInfo.language = aStkLocalInfoResponse.language; + return; + } +} +StkLocalInfoResponseMessage.prototype = Object.create(StkResponseMessage.prototype); + +function StkTimerResponse(aStkTimerResponseMessage) { + // Call |StkTerminalResponse| constructor. + StkTerminalResponse.call(this, aStkTimerResponseMessage); + let timer = aStkTimerResponseMessage.timer; + // timerAction is useless in Terminal Response, + // so we always set it to TIMER_ACTION_INVALID. + this.timer = new StkTimer(timer.timerId, + Math.floor(timer.timerValue), + Ci.nsIStkTimer.TIMER_ACTION_INVALID); +} +StkTimerResponse.prototype = Object.create(StkTerminalResponse.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkTerminalResponse, + Ci.nsIStkTimerResponse]) + }, + + // nsIStkTimerResponse + timer: { value: null, writable: true } +}); + +function StkTimerResponseMessage(aStkTimerResponse) { + // Call |StkResponseMessage| constructor. + StkResponseMessage.call(this, aStkTimerResponse); + + let timer = this.timer = {}; + // timerAction is meaningless for terminal response. + timer.timerId = aStkTimerResponse.timer.timerId; + timer.timerValue = aStkTimerResponse.timer.timerValue; +} +StkTimerResponseMessage.prototype = Object.create(StkResponseMessage.prototype); + +/** + * The implementation of nsIStkDownloadEvent set and paired JS object set. + */ +function StkDownloadEvent(aEventMessage) { + this.eventType = aEventMessage.eventType; +} +StkDownloadEvent.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkDownloadEvent]), + + // nsIStkDownloadEvent + eventType: 0 +}; + +function StkEventMessage(aStkDownloadEvent) { + this.eventType = aStkDownloadEvent.eventType; +} +StkEventMessage.prototype = { + eventType: 0 +}; + +function StkLocationEvent(aStkLocationEventMessage) { + // Call |StkDownloadEvent| constructor. + StkDownloadEvent.call(this, aStkLocationEventMessage); + this.locationStatus = aStkLocationEventMessage.locationStatus; + + if (this.locationStatus == Ci.nsIStkLocationEvent.SERVICE_STATE_NORMAL && + aStkLocationEventMessage.locationInfo) { + let info = aStkLocationEventMessage.locationInfo; + + this.locationInfo = new StkLocationInfo(info.mcc, + info.mnc, + info.gsmLocationAreaCode, + info.gsmCellId); + } +} +StkLocationEvent.prototype = Object.create(StkDownloadEvent.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkDownloadEvent, + Ci.nsIStkLocationEvent]) + }, + + // nsIStkLocationEvent + locationStatus: { value: Ci.nsIStkLocationEvent.SERVICE_STATE_UNAVAILABLE, writable: true }, + locationInfo: { value: null, writable: true } +}); + +function StkLocationEventMessage(aStkLocationEvent) { + // Call |StkEventMessage| constructor. + StkEventMessage.call(this, aStkLocationEvent); + this.locationStatus = aStkLocationEvent.locationStatus; + if (aStkLocationEvent.locationInfo) { + let info = aStkLocationEvent.locationInfo; + + this.locationInfo = new StkLocationInfo(info.mcc, + info.mnc, + info.gsmLocationAreaCode, + info.gsmCellId); + } +} +StkLocationEventMessage.prototype = Object.create(StkEventMessage.prototype); + +function StkCallEvent(aStkCallEventMessage) { + // Call |StkDownloadEvent| constructor. + StkDownloadEvent.call(this, aStkCallEventMessage); + + if (aStkCallEventMessage.number) { + this.number = aStkCallEventMessage.number; + } + + this.isIssuedByRemote = !!aStkCallEventMessage.isIssuedByRemote; + + if (aStkCallEventMessage.error) { + this.error = aStkCallEventMessage.error; + } +} +StkCallEvent.prototype = Object.create(StkDownloadEvent.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkDownloadEvent, + Ci.nsIStkCallEvent]) + }, + + // nsIStkCallEvent + number: { value: null, writable: true }, + isIssuedByRemote: { value: false, writable: true }, + error: { value: null, writable: true } +}); + +function StkCallEventMessage(aStkCallEvent) { + // Call |StkEventMessage| constructor. + StkEventMessage.call(this, aStkCallEvent); + this.number = aStkCallEvent.number; + this.isIssuedByRemote = aStkCallEvent.isIssuedByRemote; + this.error = aStkCallEvent.error; +} +StkCallEventMessage.prototype = Object.create(StkEventMessage.prototype); + +function StkLanguageSelectionEvent(aStkLanguageSelectionEventMessage) { + // Call |StkDownloadEvent| constructor. + StkDownloadEvent.call(this, aStkLanguageSelectionEventMessage); + + if (aStkLanguageSelectionEventMessage.language) { + this.language = aStkLanguageSelectionEventMessage.language; + } +} +StkLanguageSelectionEvent.prototype = Object.create(StkDownloadEvent.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkDownloadEvent, + Ci.nsIStkLanguageSelectionEvent]) + }, + + // nsIStkLanguageSelectionEvent + language: { value: null, writable: true } +}); + +function StkLanguageSelectionEventMessage(aStkLanguageSelectionEvent) { + // Call |StkEventMessage| constructor. + StkEventMessage.call(this, aStkLanguageSelectionEvent); + this.language = aStkLanguageSelectionEvent.language; +} +StkLanguageSelectionEventMessage.prototype = Object.create(StkEventMessage.prototype); + +function StkBrowserTerminationEvent(aStkBrowserTerminationEventMessage) { + // Call |StkDownloadEvent| constructor. + StkDownloadEvent.call(this, aStkBrowserTerminationEventMessage); + + if (aStkBrowserTerminationEventMessage.terminationCause) { + this.terminationCause = aStkBrowserTerminationEventMessage.terminationCause; + } +} +StkBrowserTerminationEvent.prototype = Object.create(StkDownloadEvent.prototype, { + QueryInterface: { + value: XPCOMUtils.generateQI([Ci.nsIStkDownloadEvent, + Ci.nsIStkBrowserTerminationEvent]) + }, + + // nsIStkBrowserTerminationEvent + terminationCause: { value: Ci.nsIStkBrowserTerminationEvent.BROWSER_TERMINATION_CAUSE_USER, writable: true } +}); + +function StkBrowserTerminationEventMessage(aStkBrowserTerminationEvent) { + // Call |StkEventMessage| constructor. + StkEventMessage.call(this, aStkBrowserTerminationEvent); + this.terminationCause = aStkBrowserTerminationEvent.terminationCause; +} +StkBrowserTerminationEventMessage.prototype = Object.create(StkEventMessage.prototype); + +/** + * Event Prototype Mappings. + */ +let EventPrototypes = {}; +EventPrototypes[RIL.STK_EVENT_TYPE_USER_ACTIVITY] = StkDownloadEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE] = StkDownloadEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_MT_CALL] = StkCallEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_CALL_CONNECTED] = StkCallEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_CALL_DISCONNECTED] = StkCallEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_LOCATION_STATUS] = StkLocationEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_LANGUAGE_SELECTION] = StkLanguageSelectionEvent; +EventPrototypes[RIL.STK_EVENT_TYPE_BROWSER_TERMINATION] = StkBrowserTerminationEvent; + +/** + * Event Message Prototype Mappings. + */ +let EventMsgPrototypes = {}; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_USER_ACTIVITY] = StkEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE] = StkEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_MT_CALL] = StkCallEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_CALL_CONNECTED] = StkCallEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_CALL_DISCONNECTED] = StkCallEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_LOCATION_STATUS] = StkLocationEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_LANGUAGE_SELECTION] = StkLanguageSelectionEventMessage; +EventMsgPrototypes[RIL.STK_EVENT_TYPE_BROWSER_TERMINATION] = StkBrowserTerminationEventMessage; + +/** + * Event QueryInterface Mappings. + */ +let QueriedEventIFs = {}; +QueriedEventIFs[RIL.STK_EVENT_TYPE_USER_ACTIVITY] = Ci.nsIStkDownloadEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE] = Ci.nsIStkDownloadEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_MT_CALL] = Ci.nsIStkCallEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_CALL_CONNECTED] = Ci.nsIStkCallEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_CALL_DISCONNECTED] = Ci.nsIStkCallEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_LOCATION_STATUS] = Ci.nsIStkLocationEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_LANGUAGE_SELECTION] = Ci.nsIStkLanguageSelectionEvent; +QueriedEventIFs[RIL.STK_EVENT_TYPE_BROWSER_TERMINATION] = Ci.nsIStkBrowserTerminationEvent; + /** * StkProactiveCmdFactory */ -this.StkProactiveCmdFactory = { +function StkProactiveCmdFactory() { +} +StkProactiveCmdFactory.prototype = { + classID: GONK_STKCMDFACTORY_CID, + + classInfo: XPCOMUtils.generateCI({classID: GONK_STKCMDFACTORY_CID, + contractID: GONK_STKCMDFACTORY_CONTRACTID, + classDescription: "StkProactiveCmdFactory", + interfaces: [Ci.nsIStkCmdFactory], + flags: Ci.nsIClassInfo.SINGLETON}), + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkCmdFactory]), + /** - * @param aCommandDetails - * The CommandDetails decoded from ril_worker.js. - * @return a nsIStkProactiveCmd instance. + * nsIStkCmdFactory interface. */ createCommand: function(aCommandDetails) { let cmdType = CmdPrototypes[aCommandDetails.typeOfCommand]; @@ -1014,10 +1463,6 @@ this.StkProactiveCmdFactory = { return new cmdType(aCommandDetails); }, - /** - * @param nsIStkProactiveCmd instance. - * @return a Javascript object with the same structure to MozStkCommandEvent. - */ createCommandMessage: function(aStkProactiveCmd) { let cmd = null; @@ -1037,8 +1482,135 @@ this.StkProactiveCmdFactory = { return new msgType(cmd); }, + + deflateCommand: function(aStkProactiveCmd) { + return JSON.stringify(this.createCommandMessage(aStkProactiveCmd)); + }, + + inflateCommand: function(aJSON) { + return this.createCommand(JSON.parse(aJSON)); + }, + + createResponse: function(aResponseMessage) { + if (!aResponseMessage || aResponseMessage.resultCode === undefined) { + throw new Error("Invalid response message: " + JSON.stringify(aResponseMessage)); + } + + if (aResponseMessage.itemIdentifier !== undefined) { + return new StkSelectItemResponse(aResponseMessage); + } + + if (aResponseMessage.input !== undefined || + aResponseMessage.isYesNo !== undefined) { + return new StkGetInputResponse(aResponseMessage); + } + + if (aResponseMessage.hasConfirmed !== undefined) { + return new StkCallSetupResponse(aResponseMessage); + } + + if (aResponseMessage.localInfo !== undefined) { + return new StkLocalInfoResponse(aResponseMessage); + } + + if (aResponseMessage.timer !== undefined) { + return new StkTimerResponse(aResponseMessage); + } + + return new StkTerminalResponse(aResponseMessage); + }, + + createResponseMessage: function(aStkTerminalResponse) { + if (!aStkTerminalResponse) { + throw new Error("Invalid terminal response: " + JSON.stringify(aStkTerminalResponse)); + } + + let response; + if (aStkTerminalResponse instanceof Ci.nsIStkSelectItemResponse) { + response = aStkTerminalResponse.QueryInterface(Ci.nsIStkSelectItemResponse); + return new StkSelectItemResponseMessage(response); + } + + if (aStkTerminalResponse instanceof Ci.nsIStkGetInputResponse) { + response = aStkTerminalResponse.QueryInterface(Ci.nsIStkGetInputResponse); + return new StkGetInputResponseMessage(response); + } + + if (aStkTerminalResponse instanceof Ci.nsIStkCallSetupResponse) { + response = aStkTerminalResponse.QueryInterface(Ci.nsIStkCallSetupResponse); + return new StkCallSetupResponseMessage(response); + } + + if (aStkTerminalResponse instanceof Ci.nsIStkLocalInfoResponse) { + response = aStkTerminalResponse.QueryInterface(Ci.nsIStkLocalInfoResponse); + return new StkLocalInfoResponseMessage(response); + } + + if (aStkTerminalResponse instanceof Ci.nsIStkTimerResponse) { + response = aStkTerminalResponse.QueryInterface(Ci.nsIStkTimerResponse); + return new StkTimerResponseMessage(response); + } + + return new StkResponseMessage(aStkTerminalResponse); + }, + + deflateResponse: function(aStkTerminalResponse) { + return JSON.stringify(this.createResponseMessage(aStkTerminalResponse)); + }, + + inflateResponse: function(aJSON) { + return this.createResponse(JSON.parse(aJSON)); + }, + + createEvent: function(aEventMessage) { + let eventType = EventPrototypes[aEventMessage.eventType]; + + if (typeof eventType != "function") { + throw new Error("Unknown Event Type: " + aEventMessage.eventType); + } + + return new eventType(aEventMessage); + }, + + createEventMessage: function(aStkDownloadEvent) { + let event = null; + + let eventType = EventMsgPrototypes[aStkDownloadEvent.eventType]; + + if (typeof eventType != "function") { + throw new Error("Unknown Event Type: " + aStkDownloadEvent.eventType); + } + + // convert aStkDownloadEvent to it's concrete interface before creating message. + try { + event = aStkDownloadEvent.QueryInterface(QueriedEventIFs[aStkDownloadEvent.eventType]); + } catch (e) { + throw new Error("Failed to convert event into concrete class: " + e); + } + + return new eventType(event); + }, + + deflateDownloadEvent: function(aStkDownloadEvent) { + return JSON.stringify(this.createEventMessage(aStkDownloadEvent)); + }, + + inflateDownloadEvent: function(aJSON) { + return this.createEvent(JSON.parse(aJSON)); + }, + + createTimer: function(aStkTimerMessage) { + if (!aStkTimerMessage || + aStkTimerMessage.timerId === undefined) { + throw new Error("Invalid timer object: " + JSON.stringify(aStkTimerMessage)); + } + + // timerAction is useless in TIMER EXPIRATION envelope, + // so we always set it to TIMER_ACTION_INVALID. + return new StkTimer(aStkTimerMessage.timerId, + Math.floor(aStkTimerMessage.timerValue), + Ci.nsIStkTimer.TIMER_ACTION_INVALID); + } }; -this.EXPORTED_SYMBOLS = [ - 'StkProactiveCmdFactory' -]; +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([StkProactiveCmdFactory]); diff --git a/dom/icc/gonk/StkCmdFactory.manifest b/dom/icc/gonk/StkCmdFactory.manifest new file mode 100644 index 0000000000..6f0060bff0 --- /dev/null +++ b/dom/icc/gonk/StkCmdFactory.manifest @@ -0,0 +1,6 @@ +# 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/. + +component {7a663440-e336-11e4-8fd5-c3140a7ff307} StkCmdFactory.js +contract @mozilla.org/icc/stkcmdfactory;1 {7a663440-e336-11e4-8fd5-c3140a7ff307} \ No newline at end of file diff --git a/dom/icc/interfaces/moz.build b/dom/icc/interfaces/moz.build index 9c5a1fa643..a0f10e035c 100644 --- a/dom/icc/interfaces/moz.build +++ b/dom/icc/interfaces/moz.build @@ -5,9 +5,11 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPIDL_SOURCES += [ + 'nsIIccContact.idl', 'nsIIccInfo.idl', - 'nsIIccProvider.idl', # TODO: Bug 815526, deprecate RILContentHelper. 'nsIIccService.idl', + 'nsIStkCmdFactory.idl', + 'nsIStkProactiveCmd.idl', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: diff --git a/dom/icc/interfaces/nsIGonkIccService.idl b/dom/icc/interfaces/nsIGonkIccService.idl index 890b1c9855..7266cdac6a 100644 --- a/dom/icc/interfaces/nsIGonkIccService.idl +++ b/dom/icc/interfaces/nsIGonkIccService.idl @@ -9,12 +9,11 @@ "@mozilla.org/icc/gonkiccservice;1" %} -[scriptable, uuid(a037b8a2-b027-11e4-9496-c3b7af59a512)] +[scriptable, uuid(cdcdd800-ef24-11e4-99e7-1f0f5f2576c5)] interface nsIGonkIccService : nsIIccService { - // TODO: Bug 1114938 - Refactor STK in MozIcc.webidl with IPDL: - // void notifyStkCommand(in unsigned long aServiceId, in jsval aStkcommand); - // void notifyStkSessionEnd(in unsigned long aServiceId); + void notifyStkCommand(in unsigned long aServiceId, in nsIStkProactiveCmd aStkcommand); + void notifyStkSessionEnd(in unsigned long aServiceId); void notifyCardStateChanged(in unsigned long aServiceId, in unsigned long aCardState); void notifyIccInfoChanged(in unsigned long aServiceId, in jsval aIccInfo); void notifyImsiChanged(in unsigned long aServiceId, in DOMString aImsi); diff --git a/dom/icc/interfaces/nsIIccContact.idl b/dom/icc/interfaces/nsIIccContact.idl new file mode 100644 index 0000000000..9bc4bee258 --- /dev/null +++ b/dom/icc/interfaces/nsIIccContact.idl @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +[scriptable, uuid(0f3dbcd1-9f7b-40a8-aa3c-b5701978ec53)] +interface nsIIccContact : nsISupports +{ + /** + * The unique identifier of this ICC Contact. + * + * Note: This id is composed of the iccid and its record index of EF_ADN. + */ + readonly attribute DOMString id; + + /** + * Name list. + * + * The container of Alpha-Id in EF_ADN and Second Name in EF_SNE of this contact, + * where EF_SNE provides the possibility to store a name in different language. + * + * @see 10.2.1 Support of two name fields per entry, 3GPP TS 21.111. + * + * @param aCount + * The number of names. + * + * @returns the array of names. + */ + void getNames([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out wstring aNames); + + /** + * Phone number list. + * + * The container of the dialing numbers of this contact in EF_ADN and EF_ANR. + * + * @see 10.2.2 Support of multiple phone numbers per entry, 3GPP TS 21.111. + * + * @param aCount + * The number of phone numbers. + * + * @returns the array of phone numbers. + */ + void getNumbers([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out wstring aNumbers); + + /** + * Email list. + * + * The container of the emails of this contact in EF_EMAIL. + * + * @param aCount + * The number of emails. + * + * @returns the array of emails. + */ + void getEmails([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out wstring aEmails); +}; \ No newline at end of file diff --git a/dom/icc/interfaces/nsIIccMessenger.idl b/dom/icc/interfaces/nsIIccMessenger.idl index 93c30c04c6..230da0e52d 100644 --- a/dom/icc/interfaces/nsIIccMessenger.idl +++ b/dom/icc/interfaces/nsIIccMessenger.idl @@ -4,645 +4,7 @@ #include "nsISupports.idl" -[scriptable, uuid(1510cf0c-5db6-11e4-9869-6bf419e26642)] -interface nsIStkDuration : nsISupports -{ - /** - * The value of Time units defined in 12.8 Duration of TS 11.14. - */ - readonly attribute unsigned short timeUnit; - - /** - * The length of time required, expressed in timeUnit. - * - * Note: the range is from 1 unit to 255 units. - */ - readonly attribute unsigned short timeInterval; -}; - -[scriptable, uuid(c7b6e57a-696d-11e4-bcaa-bfe8386e75a9)] -interface nsIStkIcon : nsISupports -{ - /** - * The color coding schemes defined in 4.6.1.1 of TS 31.102. - */ - const unsigned short CODING_SCHEME_BASIC = 0x11; - const unsigned short CODING_SCHEME_COLOR = 0x21; - const unsigned short CODING_SCHEME_COLOR_TRANSPARENCY = 0x22; - - /** - * Width of the icon. - */ - readonly attribute unsigned long width; - - /** - * Height of the icon. - */ - readonly attribute unsigned long height; - - /** - * Image coding scheme of the icon. - * One of CODING_SCHEME_*. - */ - readonly attribute unsigned short codingScheme; - - /** - * Array of pixels. Each pixel represents a color in the RGBA format made up - * of four bytes, that is, the Red sample in the highest 8 bits, followed by - * the Green sample, Blue sample and the Alpha sample in the lowest 8 bits. - * - * @param aCount - * The number of pixels. - * - * @returns a copy of the array of pixels. - */ - void getPixels([optional] out unsigned long aCount, - [array, size_is(aCount), retval] out unsigned long aPixels); -}; - -[scriptable, uuid(4a6d173e-5e8b-11e4-9d78-071bb3d6ba8f)] -interface nsIStkIconInfo : nsISupports -{ - /** - * Indicates how the icon is to be used. - * - * @see TS 11.14, clause 12.31, Icon Identifier. - * - * true: icon replaces the text string. - * false: icon shall be displayed together with the text string. - */ - readonly attribute boolean iconSelfExplanatory; - - /** - * Icon(s) that replaces or accompanies the text string. - * - * @see TS 11.14, clause 12.31, Icon Identifier. - * - * Array of icons, basically of a same image, that may differ in size, - * resolution or coding scheme. The first icon should be the default one. - * - * @param aCount - * The number of icons. - * - * @returns a copy of the list of icons. - */ - void getIcons([optional] out unsigned long aCount, - [array, size_is(aCount), retval] out nsIStkIcon aIcons); -}; - -[scriptable, uuid(ea95d25c-5e84-11e4-bd96-07285c50c1f2)] -interface nsIStkItem : nsISupports -{ - /** - * Identifier of item. - * - * The identifier is a single byte between '01' and 'FF'. Each item shall - * have a unique identifier within an Item list. - */ - readonly attribute unsigned short identifier; - - /** - * Text string of item. - */ - readonly attribute DOMString text; - - /** - * (Optional) - * Icon info of item. - */ - readonly attribute nsIStkIconInfo iconInfo; -}; - -[scriptable, uuid(222651f0-6976-11e4-accf-736a9c6e7d19)] -interface nsIStkTimer : nsISupports -{ - /** - * Identifier of a timer. - */ - readonly attribute unsigned short timerId; - - const unsigned long TIMER_VALUE_INVALID = 0xFFFFFFFF; - - /** - * Length of time during which the timer has to run. - * - * The possible duration of a timer is between 1 s and 24 h. - * The resolution of a timer is 1 second. - * - * Note: In TS 11.14, clause 6.6.21 TIMER MANAGEMENT, - * " - * The SIM shall supply this data object only when a timer has to - * be started. - * " - * Hence, set to TIMER_VALUE_INVALID when |timerAction| is not equal to - * TIMER_ACTION_START. - */ - readonly attribute unsigned long timerValue; - - /* - * Times actions defined in TS 11.14, clause 12.6, - * Command Qualifier, TIMER MANAGEMENT - */ - const unsigned short TIMER_ACTION_START = 0x00; - const unsigned short TIMER_ACTION_DEACTIVATE = 0x01; - const unsigned short TIMER_ACTION_GET_CURRENT_VALUE = 0x02; - - /** - * The action requested from UICC. - * It shall be one of TIMER_ACTION_*. - */ - readonly attribute unsigned short timerAction; -}; - -/** - * The base class of all STK Proactive Commands. - * - * This interface is to be applied by the commands that provide info no more than: - * |commandNumber|, |typeOfCommand|, |commandQualifier|. - * - * The commands in this category are: - * - STK_CMD_REFRESH - * - STK_CMD_POLL_OFF - */ -[scriptable, uuid(f47f25b2-5d84-11e4-8637-7f59ea6da82f)] -interface nsIStkProactiveCmd : nsISupports -{ - /** - * The number of command issued by ICC. And it is assigned - * by ICC may take any hexadecimal value betweean '01' and 'FE'. - * - * @see TS 11.14, clause 6.5.1 - */ - readonly attribute unsigned short commandNumber; - - /** - * The value of |Type of Command| defined in TS 11.14, clause 13.4 - */ - readonly attribute unsigned short typeOfCommand; - - /** - * Qualifiers specific to the command. - */ - readonly attribute unsigned short commandQualifier; -}; - -/** - * This interface is to be applied by STK_CMD_POLL_INTERVAL. - */ -[scriptable, uuid(0a27c090-5dbc-11e4-92eb-ebc26db3db29)] -interface nsIStkPollIntervalCmd : nsIStkProactiveCmd -{ - /** - * The maximum interval between two STATUS commands related to - * Proactive Polling. - * - * Note: Mandatory for STK_CMD_POLL_INTERVAL. - * - * @See TS 11.14, clause 6.6.6 POLL INTERVAL - */ - readonly attribute nsIStkDuration duration; -}; - -/** - * This interface is to be applied by STK_CMD_PROVIDE_LOCAL_INFO. - */ -[scriptable, uuid(89a304ce-5dc6-11e4-8dce-23723fb242b4)] -interface nsIStkProvideLocalInfoCmd : nsIStkProactiveCmd -{ - /** - * Values defined in TS 11.14, clause 12.6, Command Qualifier, - * PROVIDE LOCAL INFORMATION - */ - readonly attribute unsigned short localInfoType; -}; - -/** - * This interface is to be applied by STK_CMD_SET_UP_EVENT_LIST. - */ -[scriptable, uuid(5f796dec-5e6a-11e4-aaf3-bb675cb36df5)] -interface nsIStkSetupEventListCmd : nsIStkProactiveCmd -{ - /** - * (Optional) - * Get the list of events. - * Each event could be one of values defined in TS 11.14, clause 8.25, Event list. - * - * Note: It could be null as an indication to the terminal to remove the - * existing list of events in the terminal. - * - * @param aCount - * The number of events. - * - * @returns a copy of the list of events. - */ - void getEventList([optional] out unsigned long aCount, - [array, size_is(aCount), retval] out unsigned short aEventList); -}; - -/** - * This interface is to be applied by STK_CMD_SET_UP_MENU. - */ -[scriptable, uuid(d7a66664-a602-11e4-9cc7-c7ce5fdade7d)] -interface nsIStkSetUpMenuCmd : nsIStkProactiveCmd -{ - /** - * (Optional for STK_CMD_SELECT_ITEM) - * Title of the menu. - */ - readonly attribute DOMString title; - - /** - * Get the list of menu items. - * - * Note: The minimal number of items is 1. - * See TS 11.14, clause 6.6.7 SET-UP MENU and 6.6.8 SELECT ITEM. - * - * @param aCount - * The number of items. - * - * @returns a copy of the list of menu items. - * For |SET-UP MENU|, the 1st item in |aItems| could be null as an - * indication to the ME to remove the existing menu from the menu - * system in the ME. - */ - void getItems([optional] out unsigned long aCount, - [array, size_is(aCount), retval] out nsIStkItem aItems); - - /** - * (Optional) - * Get the list of Next Action Indicators. - * - * Each element should be the value of |Next Action Indicator| in TS 11.14, - * clause 13.4. - * - * @see TS 11.14, clause 12.24, Items Next Action Indicator. - * - * @param aCount - * The number of indicators. - * - * @returns a copy of the list of Next Action Indicators. - */ - void getNextActionList([optional] out unsigned long aCount, - [array, size_is(aCount), retval] out unsigned short aActions); - - /** - * (Optional) - * Icon info of the menu. - */ - readonly attribute nsIStkIconInfo iconInfo; - - /** - * Help information available or not. - * - * @see TS 11.14, clause 12.6, Command Qualifier, SET UP MENU, bit 8. - * - * true: help information available. - * false: no help information available. - * - */ - readonly attribute boolean isHelpAvailable; -}; - -/** - * This interface is to be applied by STK_CMD_SELECT_ITEM. - */ -[scriptable, uuid(eb71f0fa-a602-11e4-926f-a3814461d218)] -interface nsIStkSelectItemCmd : nsIStkSetUpMenuCmd -{ - /** - * Presentation type, one of PRESENTATION_TYPE_*. - * - * @See TS 11.14, clause 12.6, Command Qualifier: Select Item - */ - const unsigned short PRESENTATION_TYPE_NOT_SPECIFIED = 0x00; - const unsigned short PRESENTATION_TYPE_DATA_VALUES = 0x01; - const unsigned short PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03; - - readonly attribute unsigned short presentationType; - - const unsigned short DEFAULT_ITEM_INVALID = 0xFFFF; - - /** - * (Optional) - * Default item identifier of the menu. - * - * Set to DEFAULT_ITEM_INVALID if null. - */ - readonly attribute unsigned short defaultItem; -}; - -/** - * This interface is to be applied by - * - STK_CMD_SET_UP_IDLE_MODE_TEXT - * - STK_CMD_SEND_{SS|USSD|SMS|DTMF} - * - STK_CMD_OPEN_CHANNEL - * - STK_CMD_CLOSE_CHANNEL - * - STK_CMD_SEND_DATA - * - STK_CMD_RECEIVE_DATA - */ -[scriptable, uuid(61c42b3c-6324-11e4-959e-7fb2dc9a3f0d)] -interface nsIStkTextMessageCmd : nsIStkProactiveCmd -{ - /** - * Text String. - */ - readonly attribute DOMString text; - - /** - * (Optional) - * Icon to be displayed. - */ - readonly attribute nsIStkIconInfo iconInfo; -}; - -/** - * This interface is to be applied by STK_CMD_DISPLAY_TEXT. - */ -[scriptable, uuid(66a83f0a-6322-11e4-a773-9382de87a74a)] -interface nsIStkDisplayTextCmd : nsIStkTextMessageCmd -{ - /** - * (Optional) - * The length of time for which the ME shall display the dialog. - */ - readonly attribute nsIStkDuration duration; - - /** - * Indicate this text message is high priority or normal priority. - * - * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 1. - * - * true: high priority - * false: normal priority - */ - readonly attribute boolean isHighPriority; - - /** - * Need to wait for user to clear message or not. - * - * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 8. - * - * true: Wait for user to clear message. - * false: clear message after a delay. - */ - readonly attribute boolean userClear; - - /** - * Need to response immediately or not. - * - * @see TS 11.14, clause 12.43, Immediate response. - * - * true: The terminal shall send response immediately. - * false: otherwise. - */ - readonly attribute boolean responseNeeded; -}; - -/** - * The base interface of nsIStkInputKeyCmd, nsIStkInputTextCmd. - */ -[scriptable, uuid(ed16a67e-6022-11e4-a8fd-c34fe6e6bb11)] -interface nsIStkInputCmd : nsIStkProactiveCmd -{ - /** - * Text for the ME to display in conjunction with asking the user to respond. - */ - readonly attribute DOMString text; - - /** - * (Optional) - * The length of time for which the ME shall display the dialog. - */ - readonly attribute nsIStkDuration duration; - - /** - * Minimum length of response. - * Set to 1 for STK_CMD_GET_INKEY. - */ - readonly attribute unsigned short minLength; - - /** - * Maximum length of response. - * Set to 1 for STK_CMD_GET_INKEY. - */ - readonly attribute unsigned short maxLength; - - /** - * (Optional) - * Text for the ME to display, corresponds to a default text string offered - * by the ICC. - */ - readonly attribute DOMString defaultText; - - /** - * Input format. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 1. - * - * true: Alphabet set. - * false: Digits only. - */ - readonly attribute boolean isAlphabet; - - /** - * Alphabet encoding. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 2. - * - * true: UCS2 alphabet. - * false: default SMS alphabet. - */ - readonly attribute boolean isUCS2; - - /** - * Help information available or not. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 8. - * - * true: help information available. - * false: no help information available. - */ - readonly attribute boolean isHelpAvailable; - - /** - * (Optional) - * Icon to be displayed. - */ - readonly attribute nsIStkIconInfo iconInfo; -}; - -/** - * This interface is to be applied by STK_CMD_GET_INKEY. - */ -[scriptable, uuid(27a4078a-6025-11e4-a9ab-bf39252bfaf1)] -interface nsIStkInputKeyCmd : nsIStkInputCmd -{ - /** - * Yes/No response is requested. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INKEY, bit 3. - * - * true: Yes/No response is requested, and character sets - * (Alphabet set and UCS2) are disabled. - * false: Character sets (Alphabet set and UCS2) are enabled. - */ - readonly attribute boolean isYesNoRequested; -}; - -/** - * This interface is to be applied by STK_CMD_GET_INPUT. - */ -[scriptable, uuid(f3c33ae8-60d4-11e4-9da8-4ff4cb8566c3)] -interface nsIStkInputTextCmd : nsIStkInputCmd -{ - /** - * Visibility of input. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 3. - * - * true: User input shall not be revealed in any way. - * false: ME may echo user input on the display. - */ - readonly attribute boolean hideInput; - - /** - * User input in packed or unpacked format. - * - * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 4. - * - * true: User input to be in SMS packed format. - * false: User input to be in unpacked format. - */ - readonly attribute boolean isPacked; -}; - -/** - * This interface is to be applied by STK_CMD_SET_UP_CALL. - */ -[scriptable, uuid(6abbf688-6956-11e4-a9d3-4b07f063ef21)] -interface nsIStkSetUpCallCmd : nsIStkProactiveCmd -{ - /** - * The Dialling number. - */ - readonly attribute DOMString address; - - /** - * (Optional) - * The text message used in user confirmation phase. - */ - readonly attribute DOMString confirmText; - - /** - * (Optional) - * Icon to be displayed in user confirmation phase. - */ - readonly attribute nsIStkIconInfo confirmIconInfo; - - /** - * (Optional) - * The text message used in call set up phase. - */ - readonly attribute DOMString callText; - - /** - * (Optional) - * Icon to be displayed in call set up phase. - */ - readonly attribute nsIStkIconInfo callIconInfo; - - /** - * (Optional) - * The maximum duration for the redial mechanism. - * The time elapsed since the first call set-up attempt has exceeded the duration - * requested by the UICC, the redial mechanism is terminated. - */ - readonly attribute nsIStkDuration duration; -}; - -/** - * This interface is to be applied by STK_CMD_LAUNCH_BROWSER. - */ -[scriptable, uuid(b9bca548-695b-11e4-8c1f-cfb850f421ab)] -interface nsIStkBrowserSettingCmd : nsIStkProactiveCmd -{ - /** - * The URL to be opened by browser. - */ - readonly attribute DOMString url; - - /** - * Browser launch mode. - * @See TS 11.14, clause 12.6, Command Qualifier, LAUNCH BROWSER. - */ - readonly attribute unsigned short mode; - - /** - * (Optional) - * Confirm message to launch browser. - */ - readonly attribute DOMString confirmText; - - /** - * (Optional) - * Icon to be displayed in user confirmation phase. - */ - readonly attribute nsIStkIconInfo confirmIconInfo; -}; - -/** - * This interface is to be applied by STK_CMD_PLAY_TONE. - */ -[scriptable, uuid(f49dd148-60ee-11e4-af46-6b938538de51)] -interface nsIStkPlayToneCmd : nsIStkProactiveCmd -{ - const unsigned short TONE_TYPE_INVALID = 0xFFFF; - - /** - * (Optional) - * Text String. - */ - readonly attribute DOMString text; - - /** - * (Optional) - * One of the tone value coded in TS 11.14, clause 12.16, Tone. - * - * Set to TONE_TYPE_INVALID if null. - */ - readonly attribute unsigned short tone; - - /** - * (Optional) - * The length of time for which the ME shall generate the tone. - */ - readonly attribute nsIStkDuration duration; - - /** - * Need to vibrate or not. - * true: vibrate alert, if available, with the tone. - * false: use of vibrate alert is up to the ME. - */ - readonly attribute boolean isVibrate; - - /** - * (Optional) - * Icon to be displayed. - */ - readonly attribute nsIStkIconInfo iconInfo; -}; - -/** - * This interface is to be applied by STK_CMD_TIMER_MANAGEMENT. - */ -[scriptable, uuid(e421b122-60f3-11e4-b8d7-bfe75825a796)] -interface nsIStkTimerManagementCmd : nsIStkProactiveCmd -{ - /** - * Timer Information. - */ - readonly attribute nsIStkTimer timerInfo; -}; +interface nsIStkProactiveCmd; [scriptable, uuid(000696fe-5d85-11e4-8da2-2fdf3880276b)] interface nsIIccMessenger : nsISupports diff --git a/dom/icc/interfaces/nsIIccProvider.idl b/dom/icc/interfaces/nsIIccProvider.idl deleted file mode 100644 index d3c68b5826..0000000000 --- a/dom/icc/interfaces/nsIIccProvider.idl +++ /dev/null @@ -1,55 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIDOMDOMRequest; -interface nsIDOMWindow; -interface nsIIccListener; - -/** - * XPCOM component (in the content process) that provides the ICC information. - */ -[scriptable, uuid(2fbacfc4-f52d-11e4-9667-33b72f279d14)] -interface nsIIccProvider : nsISupports -{ - /** - * Called when a content process registers receiving unsolicited messages from - * RadioInterfaceLayer in the chrome process. Only a content process that has - * the 'mobileconnection' permission is allowed to register. - */ - void registerIccMsg(in unsigned long clientId, in nsIIccListener listener); - void unregisterIccMsg(in unsigned long clientId, in nsIIccListener listener); - - /** - * STK interfaces. - */ - void sendStkResponse(in unsigned long clientId, - in nsIDOMWindow window, - in jsval command, - in jsval response); - void sendStkMenuSelection(in unsigned long clientId, - in nsIDOMWindow window, - in unsigned short itemIdentifier, - in boolean helpRequested); - void sendStkTimerExpiration(in unsigned long clientId, - in nsIDOMWindow window, - in jsval timer); - void sendStkEventDownload(in unsigned long clientId, - in nsIDOMWindow window, - in jsval event); - - /** - * Phonebook interfaces. - */ - nsIDOMDOMRequest readContacts(in unsigned long clientId, - in nsIDOMWindow window, - in unsigned long contactType); - - nsIDOMDOMRequest updateContact(in unsigned long clientId, - in nsIDOMWindow window, - in unsigned long contactType, - in jsval contact, - in DOMString pin2); -}; diff --git a/dom/icc/interfaces/nsIIccService.idl b/dom/icc/interfaces/nsIIccService.idl index 57b5cb1e0a..b3ca9cac81 100644 --- a/dom/icc/interfaces/nsIIccService.idl +++ b/dom/icc/interfaces/nsIIccService.idl @@ -5,12 +5,16 @@ #include "nsISupports.idl" interface nsIIcc; +interface nsIIccContact; interface nsIIccInfo; +interface nsIStkDownloadEvent; +interface nsIStkProactiveCmd; +interface nsIStkTerminalResponse; -[scriptable, uuid(7c0ada3d-d8d4-493e-9243-fa3df39855e4)] +[scriptable, uuid(71b33012-eca2-11e4-a40d-9ff040a6fe2a)] interface nsIIccListener : nsISupports { - void notifyStkCommand(in DOMString aMessage); + void notifyStkCommand(in nsIStkProactiveCmd aStkProactiveCmd); void notifyStkSessionEnd(); void notifyCardStateChanged(); void notifyIccInfoChanged(); @@ -19,7 +23,7 @@ interface nsIIccListener : nsISupports /** * A callback interface for handling asynchronous response. */ -[scriptable, uuid(b0e2899a-adc3-11e4-89cf-1b60eaa35b06)] +[scriptable, uuid(b7b0623f-fb2c-4cec-b0dc-00ac2fe7b296)] interface nsIIccCallback : nsISupports { /** @@ -42,9 +46,28 @@ interface nsIIccCallback : nsISupports */ void notifyGetCardLockRetryCount(in long aCount); + /** + * The success callback of |readContacts|. + * + * @param aContacts + * The list of contacts retrieved from ICC. + * @param aCount + * The number of contacts retrieved from ICC. + */ + void notifyRetrievedIccContacts([array, size_is(aCount)] in nsIIccContact aContacts, + in uint32_t aCount); + + /** + * The success callback of |updateContact|. + * + * @param aContact + * The contact with the updated result. + */ + void notifyUpdatedIccContact(in nsIIccContact aContact); + /** * The error callback of |getCardLockEnabled|, |getCardLockRetryCount|, - * |matchMvno|, and |getServiceStateEnabled|. + * |matchMvno|, |getServiceStateEnabled|, |readContacts| and |updateContact|. * * @param aErrorMsg * The error message. @@ -135,7 +158,7 @@ NS_CreateIccService(); /** * XPCOM component that provides the access to the selected ICC. */ -[scriptable, uuid(6ad6b686-f52d-11e4-942d-db2884bd9242)] +[scriptable, uuid(1791f102-b081-4435-8555-37eb035fa4e2)] interface nsIIcc : nsISupports { /** @@ -232,6 +255,15 @@ interface nsIIcc : nsISupports */ const unsigned long CARD_SERVICE_FDN = 0; + /** + * Icc Contact Type Constants + * + * Note: MUST be matched with enum IccContactType in MozIcc.webidl! + */ + const unsigned long CONTACT_TYPE_ADN = 0; + const unsigned long CONTACT_TYPE_FDN = 1; + const unsigned long CONTACT_TYPE_SDN = 2; + /** * Called to register icc-related changes. * @@ -426,4 +458,81 @@ interface nsIIcc : nsISupports */ void iccCloseChannel(in long aChannel, in nsIIccChannelCallback aCallback); + + /** + * Send STK terminal response to the received proactive command. + * + * @param aCommand + * The received proactive command. + * @param aResponse + * The response to be reply to the card application that issues + * this proactive command. + */ + void sendStkResponse(in nsIStkProactiveCmd aCommand, + in nsIStkTerminalResponse aResponse); + + /** + * Send envelope to notify the selected item of the main STK menu. + * + * @param aItemIdentifier + * The identifier of the menu item. + * @param aHelpRequested + * True if help information of the selected item is requested by + * the user. + */ + void sendStkMenuSelection(in unsigned short aItemIdentifier, + in boolean aHelpRequested); + + /** + * Send envelope to notify the expiration of a requested timer. + * + * @param aTimerId + * The TimerId provided from previous proactive command. + * @param aTimerValue + * The real used seconds when expired. + */ + void sendStkTimerExpiration(in unsigned short aTimerId, + in unsigned long aTimerValue); + + /** + * Send "Event Download" envelope to the ICC. + * + * @param aEvent + * The event that ICC listening to in STK_CMD_SET_UP_EVENT_LIST. + */ + void sendStkEventDownload(in nsIStkDownloadEvent aEvent); + + /** + * Read Specified type of Contact from ICC. + * + * @param aContactType + * One of CONTACT_TYPE_*. + * + * @param aCallback + * An instance of nsIIccCallback: + * nsIIccCallback::notifyRetrievedIccContacts() if success. + * nsIIccCallback::notifyError(), otherwise. + */ + void readContacts(in unsigned long aContactType, + in nsIIccCallback aCallback); + + /** + * Update Specified type of Contact in ICC. + * + * @param aContactType + * One of CONTACT_TYPE_*. + * @param aContact + * an nsIIccContact instance with information to be updated. + * @param aPin2 (Optional) + * The PIN2 required to update FDN contact. + * + * @param aCallback + * An instance of nsIIccCallback: + * nsIIccCallback::notifyUpdatedIccContact() if success. + * nsIIccCallback::notifyError(), otherwise. + */ + void updateContact(in unsigned long aContactType, + in nsIIccContact aContact, + in DOMString aPin2, + in nsIIccCallback aCallback); }; diff --git a/dom/icc/interfaces/nsIStkCmdFactory.idl b/dom/icc/interfaces/nsIStkCmdFactory.idl new file mode 100644 index 0000000000..ff827240a5 --- /dev/null +++ b/dom/icc/interfaces/nsIStkCmdFactory.idl @@ -0,0 +1,140 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +%{C++ +#define ICC_STK_CMD_FACTORY_CONTRACTID \ + "@mozilla.org/icc/stkcmdfactory;1" +%} + +interface nsIStkProactiveCmd; +interface nsIStkTerminalResponse; +interface nsIStkDownloadEvent; +interface nsIStkTimer; + +/** + * This StkCmdFactory provides series factory methods to create objects defined + * in nsIStkProactiveCmd.idl and MozStkCommandEvent.webidl. + */ +[scriptable, uuid(743536c4-006f-11e5-a3f7-bf7a7fd59b9b)] +interface nsIStkCmdFactory : nsISupports +{ + /** + * @param aCommandDetails + * A JS object which complies with 'dictionary MozStkCommand' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkProactiveCmd instance. + */ + nsIStkProactiveCmd createCommand(in jsval aCommandDetails); + + /** + * @param aStkProactiveCmd + * a nsIStkProactiveCmd instance. + * + * @return a JS object which complies with 'dictionary MozStkCommand' + * in MozStkCommandEvent.webidl + */ + jsval createCommandMessage(in nsIStkProactiveCmd aStkProactiveCmd); + + /** + * @param aStkProactiveCmd + * a nsIStkProactiveCmd instance. + * + * @return a JSON string which complies with 'dictionary MozStkCommand' + * in MozStkCommandEvent.webidl + */ + AString deflateCommand(in nsIStkProactiveCmd aStkProactiveCmd); + + /** + * @param a JSON string which complies with 'dictionary MozStkCommand' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkProactiveCmd instance. + */ + nsIStkProactiveCmd inflateCommand(in AString aJSON); + + /** + * @param aResponseMessage + * A JS object which complies with 'dictionary MozStkResponse' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkTerminalResponse instance. + */ + nsIStkTerminalResponse createResponse(in jsval aResponseMessage); + + /** + * @param aStkTerminalResponse + * a nsIStkTerminalResponse instance. + * + * @return a JS object which complies with 'dictionary MozStkResponse' + * in MozStkCommandEvent.webidl + */ + jsval createResponseMessage(in nsIStkTerminalResponse aStkTerminalResponse); + + /** + * @param aStkTerminalResponse + * a nsIStkTerminalResponse instance. + * + * @return a JSON string which complies with 'dictionary MozStkResponse' + * in MozStkCommandEvent.webidl + */ + AString deflateResponse(in nsIStkTerminalResponse aStkTerminalResponse); + + /** + * @param a JSON string which complies with 'dictionary MozStkResponse' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkTerminalResponse instance. + */ + nsIStkTerminalResponse inflateResponse(in AString aJSON); + + /** + * @param aEventMessage + * A JS object which complies with 'dictionary MozStkXxxEvent' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkDownloadEvent instance. + */ + nsIStkDownloadEvent createEvent(in jsval aEventMessage); + + /** + * @param aStkDownloadEvent + * a nsIStkDownloadEvent instance. + * + * @return a JS object which complies with 'dictionary MozStkXxxEvent' + * in MozStkCommandEvent.webidl + */ + jsval createEventMessage(in nsIStkDownloadEvent aStkDownloadEvent); + + /** + * @param aStkDownloadEvent + * a nsIStkDownloadEvent instance. + * + * @return a JSON string which complies with 'dictionary MozStkXxxEvent' + * in MozStkCommandEvent.webidl + */ + AString deflateDownloadEvent(in nsIStkDownloadEvent aStkDownloadEvent); + + /** + * @param a JSON string which complies with 'dictionary MozStkXxxEvent' + * in MozStkCommandEvent.webidl + * + * @return a nsIStkDownloadEvent instance. + */ + nsIStkDownloadEvent inflateDownloadEvent(in AString aJSON); + + /** + * @param aStkTimerMessage + * a JS object which complies with 'dictionary MozStkTimer' + * in MozStkCommandEvent.webidl + * + * @return an instance of nsIStkTimer with the same timerId and timerValue + * from aStkTimerMessage. + * + * Note: This API is specific to nsIIcc::sendStkTimerExpiration(). + */ + nsIStkTimer createTimer(in jsval aStkTimerMessage); +}; diff --git a/dom/icc/interfaces/nsIStkProactiveCmd.idl b/dom/icc/interfaces/nsIStkProactiveCmd.idl new file mode 100644 index 0000000000..77446e9888 --- /dev/null +++ b/dom/icc/interfaces/nsIStkProactiveCmd.idl @@ -0,0 +1,1017 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "domstubs.idl" + +[scriptable, uuid(1510cf0c-5db6-11e4-9869-6bf419e26642)] +interface nsIStkDuration : nsISupports +{ + /** + * The value of Time units defined in 12.8 Duration of TS 11.14. + */ + readonly attribute unsigned short timeUnit; + + /** + * The length of time required, expressed in timeUnit. + * + * Note: the range is from 1 unit to 255 units. + */ + readonly attribute unsigned short timeInterval; +}; + +[scriptable, uuid(c7b6e57a-696d-11e4-bcaa-bfe8386e75a9)] +interface nsIStkIcon : nsISupports +{ + /** + * The color coding schemes defined in 4.6.1.1 of TS 31.102. + */ + const unsigned short CODING_SCHEME_BASIC = 0x11; + const unsigned short CODING_SCHEME_COLOR = 0x21; + const unsigned short CODING_SCHEME_COLOR_TRANSPARENCY = 0x22; + + /** + * Width of the icon. + */ + readonly attribute unsigned long width; + + /** + * Height of the icon. + */ + readonly attribute unsigned long height; + + /** + * Image coding scheme of the icon. + * One of CODING_SCHEME_*. + */ + readonly attribute unsigned short codingScheme; + + /** + * Array of pixels. Each pixel represents a color in the RGBA format made up + * of four bytes, that is, the Red sample in the highest 8 bits, followed by + * the Green sample, Blue sample and the Alpha sample in the lowest 8 bits. + * + * @param aCount + * The number of pixels. + * + * @returns a copy of the array of pixels. + */ + void getPixels([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out unsigned long aPixels); +}; + +[scriptable, uuid(4a6d173e-5e8b-11e4-9d78-071bb3d6ba8f)] +interface nsIStkIconInfo : nsISupports +{ + /** + * Indicates how the icon is to be used. + * + * @see TS 11.14, clause 12.31, Icon Identifier. + * + * true: icon replaces the text string. + * false: icon shall be displayed together with the text string. + */ + readonly attribute boolean iconSelfExplanatory; + + /** + * Icon(s) that replaces or accompanies the text string. + * + * @see TS 11.14, clause 12.31, Icon Identifier. + * + * Array of icons, basically of a same image, that may differ in size, + * resolution or coding scheme. The first icon should be the default one. + * + * @param aCount + * The number of icons. + * + * @returns a copy of the list of icons. + */ + void getIcons([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out nsIStkIcon aIcons); +}; + +[scriptable, uuid(ea95d25c-5e84-11e4-bd96-07285c50c1f2)] +interface nsIStkItem : nsISupports +{ + /** + * Identifier of item. + * + * The identifier is a single byte between '01' and 'FF'. Each item shall + * have a unique identifier within an Item list. + */ + readonly attribute unsigned short identifier; + + /** + * Text string of item. + */ + readonly attribute DOMString text; + + /** + * (Optional) + * Icon info of item. + */ + readonly attribute nsIStkIconInfo iconInfo; +}; + +[scriptable, uuid(1ec0d430-eeec-11e4-8566-df81b6d562c8)] +interface nsIStkTimer : nsISupports +{ + /** + * Identifier of a timer. + */ + readonly attribute unsigned short timerId; + + const unsigned long TIMER_VALUE_INVALID = 0xFFFFFFFF; + + /** + * Length of time during which the timer has to run. + * + * The possible duration of a timer is between 1 s and 24 h. + * The resolution of a timer is 1 second. + * + * Note: In TS 11.14, clause 6.6.21 TIMER MANAGEMENT, + * " + * The SIM shall supply this data object only when a timer has to + * be started. + * " + * Hence, set to TIMER_VALUE_INVALID when |timerAction| is not equal to + * TIMER_ACTION_START. + */ + readonly attribute unsigned long timerValue; + + /* + * Times actions defined in TS 11.14, clause 12.6, + * Command Qualifier, TIMER MANAGEMENT + */ + const unsigned short TIMER_ACTION_START = 0x00; + const unsigned short TIMER_ACTION_DEACTIVATE = 0x01; + const unsigned short TIMER_ACTION_GET_CURRENT_VALUE = 0x02; + const unsigned short TIMER_ACTION_INVALID = 0xFF; + + /** + * The action requested from UICC. + * It shall be one of TIMER_ACTION_*. + */ + readonly attribute unsigned short timerAction; +}; + +[scriptable, uuid(09903cfe-f3bf-11e4-a029-23d988cd1a82)] +interface nsIStkLocationInfo : nsISupports +{ + /** + * Mobile Country Code (MCC) of the current serving operator. + */ + readonly attribute DOMString mcc; + + /** + * Mobile Network Code (MNC) of the current serving operator. + */ + readonly attribute DOMString mnc; + + /** + * Mobile Location Area Code (LAC) for the current serving operator. + */ + readonly attribute unsigned short gsmLocationAreaCode; + + /** + * Mobile Cell ID for the current serving operator. + */ + readonly attribute unsigned long gsmCellId; +}; + +/** + * The base class of all STK Proactive Commands. + * + * This interface is to be applied by the commands that provide info no more than: + * |commandNumber|, |typeOfCommand|, |commandQualifier|. + * + * The commands in this category are: + * - STK_CMD_REFRESH + * - STK_CMD_POLL_OFF + */ +[scriptable, uuid(f47f25b2-5d84-11e4-8637-7f59ea6da82f)] +interface nsIStkProactiveCmd : nsISupports +{ + /** + * The number of command issued by ICC. And it is assigned + * by ICC may take any hexadecimal value betweean '01' and 'FE'. + * + * @see TS 11.14, clause 6.5.1 + */ + readonly attribute unsigned short commandNumber; + + /** + * The value of |Type of Command| defined in TS 11.14, clause 13.4 + */ + readonly attribute unsigned short typeOfCommand; + + /** + * Qualifiers specific to the command. + */ + readonly attribute unsigned short commandQualifier; +}; + +/** + * This interface is to be applied by STK_CMD_POLL_INTERVAL. + */ +[scriptable, uuid(0a27c090-5dbc-11e4-92eb-ebc26db3db29)] +interface nsIStkPollIntervalCmd : nsIStkProactiveCmd +{ + /** + * The maximum interval between two STATUS commands related to + * Proactive Polling. + * + * Note: Mandatory for STK_CMD_POLL_INTERVAL. + * + * @See TS 11.14, clause 6.6.6 POLL INTERVAL + */ + readonly attribute nsIStkDuration duration; +}; + +/** + * This interface is to be applied by STK_CMD_PROVIDE_LOCAL_INFO. + */ +[scriptable, uuid(89a304ce-5dc6-11e4-8dce-23723fb242b4)] +interface nsIStkProvideLocalInfoCmd : nsIStkProactiveCmd +{ + /** + * Values defined in TS 11.14, clause 12.6, Command Qualifier, + * PROVIDE LOCAL INFORMATION + */ + readonly attribute unsigned short localInfoType; +}; + +/** + * This interface is to be applied by STK_CMD_SET_UP_EVENT_LIST. + */ +[scriptable, uuid(5f796dec-5e6a-11e4-aaf3-bb675cb36df5)] +interface nsIStkSetupEventListCmd : nsIStkProactiveCmd +{ + /** + * (Optional) + * Get the list of events. + * Each event could be one of values defined in TS 11.14, clause 8.25, Event list. + * + * Note: It could be null as an indication to the terminal to remove the + * existing list of events in the terminal. + * + * @param aCount + * The number of events. + * + * @returns a copy of the list of events. + */ + void getEventList([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out unsigned short aEventList); +}; + +/** + * This interface is to be applied by STK_CMD_SET_UP_MENU. + */ +[scriptable, uuid(d7a66664-a602-11e4-9cc7-c7ce5fdade7d)] +interface nsIStkSetUpMenuCmd : nsIStkProactiveCmd +{ + /** + * (Optional for STK_CMD_SELECT_ITEM) + * Title of the menu. + */ + readonly attribute DOMString title; + + /** + * Get the list of menu items. + * + * Note: The minimal number of items is 1. + * See TS 11.14, clause 6.6.7 SET-UP MENU and 6.6.8 SELECT ITEM. + * + * @param aCount + * The number of items. + * + * @returns a copy of the list of menu items. + * For |SET-UP MENU|, the 1st item in |aItems| could be null as an + * indication to the ME to remove the existing menu from the menu + * system in the ME. + */ + void getItems([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out nsIStkItem aItems); + + /** + * (Optional) + * Get the list of Next Action Indicators. + * + * Each element should be the value of |Next Action Indicator| in TS 11.14, + * clause 13.4. + * + * @see TS 11.14, clause 12.24, Items Next Action Indicator. + * + * @param aCount + * The number of indicators. + * + * @returns a copy of the list of Next Action Indicators. + */ + void getNextActionList([optional] out unsigned long aCount, + [array, size_is(aCount), retval] out unsigned short aActions); + + /** + * (Optional) + * Icon info of the menu. + */ + readonly attribute nsIStkIconInfo iconInfo; + + /** + * Help information available or not. + * + * @see TS 11.14, clause 12.6, Command Qualifier, SET UP MENU, bit 8. + * + * true: help information available. + * false: no help information available. + * + */ + readonly attribute boolean isHelpAvailable; +}; + +/** + * This interface is to be applied by STK_CMD_SELECT_ITEM. + */ +[scriptable, uuid(eb71f0fa-a602-11e4-926f-a3814461d218)] +interface nsIStkSelectItemCmd : nsIStkSetUpMenuCmd +{ + /** + * Presentation type, one of PRESENTATION_TYPE_*. + * + * @See TS 11.14, clause 12.6, Command Qualifier: Select Item + */ + const unsigned short PRESENTATION_TYPE_NOT_SPECIFIED = 0x00; + const unsigned short PRESENTATION_TYPE_DATA_VALUES = 0x01; + const unsigned short PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03; + + readonly attribute unsigned short presentationType; + + const unsigned short DEFAULT_ITEM_INVALID = 0xFFFF; + + /** + * (Optional) + * Default item identifier of the menu. + * + * Set to DEFAULT_ITEM_INVALID if null. + */ + readonly attribute unsigned short defaultItem; +}; + +/** + * This interface is to be applied by + * - STK_CMD_SET_UP_IDLE_MODE_TEXT + * - STK_CMD_SEND_{SS|USSD|SMS|DTMF} + * - STK_CMD_OPEN_CHANNEL + * - STK_CMD_CLOSE_CHANNEL + * - STK_CMD_SEND_DATA + * - STK_CMD_RECEIVE_DATA + */ +[scriptable, uuid(61c42b3c-6324-11e4-959e-7fb2dc9a3f0d)] +interface nsIStkTextMessageCmd : nsIStkProactiveCmd +{ + /** + * Text String. + */ + readonly attribute DOMString text; + + /** + * (Optional) + * Icon to be displayed. + */ + readonly attribute nsIStkIconInfo iconInfo; +}; + +/** + * This interface is to be applied by STK_CMD_DISPLAY_TEXT. + */ +[scriptable, uuid(66a83f0a-6322-11e4-a773-9382de87a74a)] +interface nsIStkDisplayTextCmd : nsIStkTextMessageCmd +{ + /** + * (Optional) + * The length of time for which the ME shall display the dialog. + */ + readonly attribute nsIStkDuration duration; + + /** + * Indicate this text message is high priority or normal priority. + * + * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 1. + * + * true: high priority + * false: normal priority + */ + readonly attribute boolean isHighPriority; + + /** + * Need to wait for user to clear message or not. + * + * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 8. + * + * true: Wait for user to clear message. + * false: clear message after a delay. + */ + readonly attribute boolean userClear; + + /** + * Need to response immediately or not. + * + * @see TS 11.14, clause 12.43, Immediate response. + * + * true: The terminal shall send response immediately. + * false: otherwise. + */ + readonly attribute boolean responseNeeded; +}; + +/** + * The base interface of nsIStkInputKeyCmd, nsIStkInputTextCmd. + */ +[scriptable, uuid(ed16a67e-6022-11e4-a8fd-c34fe6e6bb11)] +interface nsIStkInputCmd : nsIStkProactiveCmd +{ + /** + * Text for the ME to display in conjunction with asking the user to respond. + */ + readonly attribute DOMString text; + + /** + * (Optional) + * The length of time for which the ME shall display the dialog. + */ + readonly attribute nsIStkDuration duration; + + /** + * Minimum length of response. + * Set to 1 for STK_CMD_GET_INKEY. + */ + readonly attribute unsigned short minLength; + + /** + * Maximum length of response. + * Set to 1 for STK_CMD_GET_INKEY. + */ + readonly attribute unsigned short maxLength; + + /** + * (Optional) + * Text for the ME to display, corresponds to a default text string offered + * by the ICC. + */ + readonly attribute DOMString defaultText; + + /** + * Input format. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 1. + * + * true: Alphabet set. + * false: Digits only. + */ + readonly attribute boolean isAlphabet; + + /** + * Alphabet encoding. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 2. + * + * true: UCS2 alphabet. + * false: default SMS alphabet. + */ + readonly attribute boolean isUCS2; + + /** + * Help information available or not. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 8. + * + * true: help information available. + * false: no help information available. + */ + readonly attribute boolean isHelpAvailable; + + /** + * (Optional) + * Icon to be displayed. + */ + readonly attribute nsIStkIconInfo iconInfo; +}; + +/** + * This interface is to be applied by STK_CMD_GET_INKEY. + */ +[scriptable, uuid(27a4078a-6025-11e4-a9ab-bf39252bfaf1)] +interface nsIStkInputKeyCmd : nsIStkInputCmd +{ + /** + * Yes/No response is requested. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INKEY, bit 3. + * + * true: Yes/No response is requested, and character sets + * (Alphabet set and UCS2) are disabled. + * false: Character sets (Alphabet set and UCS2) are enabled. + */ + readonly attribute boolean isYesNoRequested; +}; + +/** + * This interface is to be applied by STK_CMD_GET_INPUT. + */ +[scriptable, uuid(f3c33ae8-60d4-11e4-9da8-4ff4cb8566c3)] +interface nsIStkInputTextCmd : nsIStkInputCmd +{ + /** + * Visibility of input. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 3. + * + * true: User input shall not be revealed in any way. + * false: ME may echo user input on the display. + */ + readonly attribute boolean hideInput; + + /** + * User input in packed or unpacked format. + * + * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 4. + * + * true: User input to be in SMS packed format. + * false: User input to be in unpacked format. + */ + readonly attribute boolean isPacked; +}; + +/** + * This interface is to be applied by STK_CMD_SET_UP_CALL. + */ +[scriptable, uuid(6abbf688-6956-11e4-a9d3-4b07f063ef21)] +interface nsIStkSetUpCallCmd : nsIStkProactiveCmd +{ + /** + * The Dialling number. + */ + readonly attribute DOMString address; + + /** + * (Optional) + * The text message used in user confirmation phase. + */ + readonly attribute DOMString confirmText; + + /** + * (Optional) + * Icon to be displayed in user confirmation phase. + */ + readonly attribute nsIStkIconInfo confirmIconInfo; + + /** + * (Optional) + * The text message used in call set up phase. + */ + readonly attribute DOMString callText; + + /** + * (Optional) + * Icon to be displayed in call set up phase. + */ + readonly attribute nsIStkIconInfo callIconInfo; + + /** + * (Optional) + * The maximum duration for the redial mechanism. + * The time elapsed since the first call set-up attempt has exceeded the duration + * requested by the UICC, the redial mechanism is terminated. + */ + readonly attribute nsIStkDuration duration; +}; + +/** + * This interface is to be applied by STK_CMD_LAUNCH_BROWSER. + */ +[scriptable, uuid(b9bca548-695b-11e4-8c1f-cfb850f421ab)] +interface nsIStkBrowserSettingCmd : nsIStkProactiveCmd +{ + /** + * The URL to be opened by browser. + */ + readonly attribute DOMString url; + + /** + * Browser launch mode. + * @See TS 11.14, clause 12.6, Command Qualifier, LAUNCH BROWSER. + */ + readonly attribute unsigned short mode; + + /** + * (Optional) + * Confirm message to launch browser. + */ + readonly attribute DOMString confirmText; + + /** + * (Optional) + * Icon to be displayed in user confirmation phase. + */ + readonly attribute nsIStkIconInfo confirmIconInfo; +}; + +/** + * This interface is to be applied by STK_CMD_PLAY_TONE. + */ +[scriptable, uuid(f49dd148-60ee-11e4-af46-6b938538de51)] +interface nsIStkPlayToneCmd : nsIStkProactiveCmd +{ + const unsigned short TONE_TYPE_INVALID = 0xFFFF; + + /** + * (Optional) + * Text String. + */ + readonly attribute DOMString text; + + /** + * (Optional) + * One of the tone value coded in TS 11.14, clause 12.16, Tone. + * + * Set to TONE_TYPE_INVALID if null. + */ + readonly attribute unsigned short tone; + + /** + * (Optional) + * The length of time for which the ME shall generate the tone. + */ + readonly attribute nsIStkDuration duration; + + /** + * Need to vibrate or not. + * true: vibrate alert, if available, with the tone. + * false: use of vibrate alert is up to the ME. + */ + readonly attribute boolean isVibrate; + + /** + * (Optional) + * Icon to be displayed. + */ + readonly attribute nsIStkIconInfo iconInfo; +}; + +/** + * This interface is to be applied by STK_CMD_TIMER_MANAGEMENT. + */ +[scriptable, uuid(e421b122-60f3-11e4-b8d7-bfe75825a796)] +interface nsIStkTimerManagementCmd : nsIStkProactiveCmd +{ + /** + * Timer Information. + */ + readonly attribute nsIStkTimer timerInfo; +}; + +/** + * The base class of all STK Terminal Respones. + * + * This interface is to be applied by the responses that provide info no more + * than |resultCode| and |additionalInformation|. + * + * @see |6.8 Structure of Terminal Response| and |12.12 Result| in TS 11.14 for + * for the common structure of the response. + */ +[scriptable, uuid(8e9f94de-0059-11e5-8608-67b08648d3d9)] +interface nsIStkTerminalResponse : nsISupports +{ + /** + * STK result code. + * + * @see TS 11.14, clause 12.12 + * + * Results '0X' and '1X' indicate that the command has been performed. + */ + /** Command performed successfully */ + const unsigned short RESULT_OK = 0x00; + + /** Command performed with partial comprehension */ + const unsigned short RESULT_PRFRMD_WITH_PARTIAL_COMPREHENSION = 0x01; + + /** Command performed, with missing information */ + const unsigned short RESULT_PRFRMD_WITH_MISSING_INFO = 0x02; + + /** REFRESH performed with additional EFs read */ + const unsigned short RESULT_PRFRMD_WITH_ADDITIONAL_EFS_READ = 0x03; + + /** Command performed successfully, but icon could not be displayed */ + const unsigned short RESULT_PRFRMD_ICON_NOT_DISPLAYED = 0x04; + + /** Command performed successfully, limited service */ + const unsigned short RESULT_PRFRMD_LIMITED_SERVICE = 0x06; + + /** Proactive UICC session terminated by the user */ + const unsigned short RESULT_UICC_SESSION_TERM_BY_USER = 0x10; + + /** Backward move in the proactive UICC session requested by the user */ + const unsigned short RESULT_BACKWARD_MOVE_BY_USER = 0x11; + + /** No response from user */ + const unsigned short RESULT_NO_RESPONSE_FROM_USER = 0x12; + + /** Help information required by the user */ + const unsigned short RESULT_HELP_INFO_REQUIRED = 0x13; + + /** USSD or SS transaction terminated by the user */ + const unsigned short RESULT_USSD_SS_SESSION_TERM_BY_USER = 0x14; + + /** + * Results '2X' indicate to the UICC that it may be worth re-trying the + * command at a later opportunity. + */ + /** Terminal currently unable to process command */ + const unsigned short RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS = 0x20; + + /** Network currently unable to process command */ + const unsigned short RESULT_NETWORK_CRNTLY_UNABLE_TO_PROCESS = 0x21; + + /** User did not accept the proactive command */ + const unsigned short RESULT_USER_NOT_ACCEPT = 0x22; + + /** User cleared down call before connection or network release */ + const unsigned short RESULT_USER_CLEAR_DOWN_CALL = 0x23; + + /** Action in contradiction with the current timer state */ + const unsigned short RESULT_ACTION_CONTRADICTION_TIMER_STATE = 0x24; + + /** Launch browser generic error code */ + const unsigned short RESULT_LAUNCH_BROWSER_ERROR = 0x26; + + /** + * Results '3X' indicate that it is not worth the UICC re-trying with an + * identical command, as it will only get the same response. However, the + * decision to retry lies with the application. + */ + /** Command beyond terminal's capabilities */ + const unsigned short RESULT_BEYOND_TERMINAL_CAPABILITY = 0x30; + + /** Command type not understood by terminal */ + const unsigned short RESULT_CMD_TYPE_NOT_UNDERSTOOD = 0x31; + + /** Command data not understood by terminal */ + const unsigned short RESULT_CMD_DATA_NOT_UNDERSTOOD = 0x32; + + /** Command number not known by terminal */ + const unsigned short RESULT_CMD_NUM_NOT_KNOWN = 0x33; + + /** SS return error */ + const unsigned short RESULT_SS_RETURN_ERROR = 0x34; + + /** SMS RP-ERROR */ + const unsigned short RESULT_SMS_RP_ERROR = 0x35; + + /** Error, required values are missing */ + const unsigned short RESULT_REQUIRED_VALUES_MISSING = 0x36; + + /** USSD return error */ + const unsigned short RESULT_USSD_RETURN_ERROR = 0x37; + + /** MultipleCard commands error */ + const unsigned short RESULT_MULTI_CARDS_CMD_ERROR = 0x38; + + /** + * Interaction with call control by USIM or MO short message control by + * USIM, permanent problem. + */ + const unsigned short RESULT_USIM_CALL_CONTROL_PERMANENT = 0x39; + + /** Bearer independent protocol error */ + const unsigned short RESULT_BIP_ERROR = 0x3a; + + /** + * 12.12.2 Additional information for ME problem: + */ + const unsigned short ADDITIONAL_INFO_ME_PROBLEM_SCREEN_IS_BUSY = 0x01; + + const unsigned short ADDITIONAL_INFO_INVALID = 0xFFFF; + + /** + * The general result of the response. + * One of RESULT_*. + */ + readonly attribute unsigned short resultCode; + + /** + * (Optional) + * The additional info of the response. + * + * One of ADDITIONAL_INFO_*. + * Set to ADDITIONAL_INFO_INVALID if not available. + */ + readonly attribute unsigned short additionalInformation; +}; + +/** + * This interface is to be applied by the response of STK_CMD_SELECT_ITEM. + */ +[scriptable, uuid(8eaa2496-ed7e-11e4-9aff-bfcf22a78770)] +interface nsIStkSelectItemResponse : nsIStkTerminalResponse +{ + /** + * The selected menu item. + */ + readonly attribute unsigned short itemIdentifier; +}; + +/** + * This interface is to be applied by the response of STK_CMD_GET_INKEY and + * STK_CMD_GET_INPUT. + * + * Note: Either |isYesNo| or |input| shall be valid. + */ +[scriptable, uuid(f39d9cd8-ee33-11e4-a55b-ef2489a0707d)] +interface nsIStkGetInputResponse : nsIStkTerminalResponse +{ + const unsigned short YES_NO_INVALID = 0xFFFF; + const unsigned short YES = 1; + const unsigned short NO = 0; + + /** + * (Optional) + * The response if Yes/No response is requested. + * Set to YES_NO_INVALID if not available. + */ + readonly attribute unsigned short isYesNo; + + /** + * (Optional) + * The response of user input. + */ + readonly attribute DOMString input; +}; + +/** + * This interface is to be applied for the response of STK_CMD_CALL_SET_UP. + */ +[scriptable, uuid(dbf61506-ed7f-11e4-93ea-233485a1bac9)] +interface nsIStkCallSetupResponse : nsIStkTerminalResponse +{ + /** + * True if user confirm to set up call. + */ + readonly attribute boolean hasConfirmed; +}; + +/** + * This interface is to be applied by the response of STK_CMD_PROVIDE_LOCAL_INFO. + */ +[scriptable, uuid(24fd4ece-ee37-11e4-8ac4-af876b1ce771)] +interface nsIStkLocalInfoResponse : nsIStkTerminalResponse +{ + const unsigned short DATE_INVALID = 0; + + /** + * (Optional) + * IMEI information + */ + readonly attribute DOMString imei; + + /** + * (Optional) + * Location Information + */ + readonly attribute nsIStkLocationInfo locationInfo; + + /** + * (Optional) + * Date information + */ + readonly attribute DOMTimeStamp date; + + /** + * (Optional) + * Language Information + * + * @see ISO 639-1, Alpha-2 code + */ + readonly attribute DOMString language; +}; + +/** + * This interface is to be applied by the response of STK_CMD_TIMER_MANAGEMENT. + */ +[scriptable, uuid(19f37a02-ed84-11e4-8316-0fde52ecfba6)] +interface nsIStkTimerResponse : nsIStkTerminalResponse +{ + /** + * Timer Info. + * + * Note: Only timer.timerId and timer.timerValue will be used in response. + */ + readonly attribute nsIStkTimer timer; +}; + +/** + * The base class of events used by Event Download. + * + * This interface is to be applied by the event that provide info no more + * than |eventType|. e.g. STK_EVENT_TYPE_USER_ACTIVITY, + * STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE. + * + * @see TS 102 223, clause 8.25 Event List, caluse 7.5 Event download + * for all structures of the event download. + */ +[scriptable, uuid(0215d918-ee4a-11e4-9dcf-ab2c197c9211)] +interface nsIStkDownloadEvent : nsISupports +{ + /** + * The event type of this download event. + * + * @see TS 102 223, clause 8.25 Event List. + */ + readonly attribute unsigned short eventType; +}; + +/** + * This interface is to be applied by STK_EVENT_TYPE_LOCATION_STATUS. + */ +[scriptable, uuid(807b14f0-0059-11e5-aff7-1f8b4e659dbc)] +interface nsIStkLocationEvent : nsIStkDownloadEvent +{ + const unsigned short SERVICE_STATE_NORMAL = 0x00; + const unsigned short SERVICE_STATE_LIMITED = 0x01; + const unsigned short SERVICE_STATE_UNAVAILABLE = 0x02; + + /** + * Indicate current service state of the MS with one of the values listed + * One of SERVICE_STATE_*. + */ + readonly attribute unsigned short locationStatus; + + /** + * (Optional) + * Location Information + * + * Note: This object shall be included only if locationStatus is equal to + * SERVICE_STATE_NORMAL. + * + * @See TS 102 223, clause 7.5.4 Location status event. + */ + readonly attribute nsIStkLocationInfo locationInfo; +}; + +/** + * This interface is to be applied by STK_EVENT_TYPE_MT_CALL, + * STK_EVENT_TYPE_CALL_CONNECTED and STK_EVENT_TYPE_CALL_DISCONNECTED. + */ +[scriptable, uuid(e47dfc98-ee51-11e4-a672-43216a0b375a)] +interface nsIStkCallEvent : nsIStkDownloadEvent +{ + /** + * Remote party number. + */ + readonly attribute DOMString number; + + /** + * For the STK_EVENT_TYPE_CALL_CONNECTED event, setting this to true means + * the connection is answered by remote end, that is, this is an outgoing call. + * For the STK_EVENT_TYPE_CALL_DISCONNECTED event, setting this to true + * indicates the connection is hung up by remote. + * For the STK_EVENT_TYPE_MT_CALL event, this flag is ignored. + */ + readonly attribute boolean isIssuedByRemote; + + /** + * Indicate the cause of disconnection. + * The cause string is the one passed to gaia through the error listener of + * CallEvent. + * Set to null if there's no error. + */ + readonly attribute DOMString error; +}; + +/** + * This interface is to be applied by STK_EVENT_TYPE_LANGUAGE_SELECTION. + */ +[scriptable, uuid(d185f0dc-ee51-11e4-912a-933874ee6cec)] +interface nsIStkLanguageSelectionEvent : nsIStkDownloadEvent +{ + /** + * Language Information + * + * @see ISO 639-1, Alpha-2 code + * "de" for German, "en" for English, "zh" for Chinese, etc. + */ + readonly attribute DOMString language; +}; + +/** + * This interface is to be applied by STK_EVENT_TYPE_LANGUAGE_SELECTION. + */ +[scriptable, uuid(7ae84bde-0059-11e5-8238-8ba12036dc26)] +interface nsIStkBrowserTerminationEvent : nsIStkDownloadEvent +{ + const unsigned short BROWSER_TERMINATION_CAUSE_USER = 0x00; + const unsigned short BROWSER_TERMINATION_CAUSE_ERROR = 0x01; + /** + * The browser termination cause. + * One of BROWSER_TERMINATION_CAUSE_* + */ + readonly attribute unsigned short terminationCause; +}; diff --git a/dom/icc/ipc/IccChild.cpp b/dom/icc/ipc/IccChild.cpp index 72f784ff4e..db75bd72a2 100644 --- a/dom/icc/ipc/IccChild.cpp +++ b/dom/icc/ipc/IccChild.cpp @@ -4,8 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/dom/icc/IccChild.h" #include "IccInfo.h" +#include "mozilla/dom/icc/IccChild.h" +#include "mozilla/dom/icc/IccIPCUtils.h" +#include "nsIStkCmdFactory.h" +#include "nsIStkProactiveCmd.h" using mozilla::dom::IccInfo; @@ -82,6 +85,35 @@ IccChild::RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData) return true; } +bool +IccChild::RecvNotifyStkCommand(const nsString& aStkProactiveCmd) +{ + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, false); + + nsCOMPtr cmd; + cmdFactory->InflateCommand(aStkProactiveCmd, getter_AddRefs(cmd)); + + NS_ENSURE_TRUE(cmd, false); + + for (int32_t i = 0; i < mListeners.Count(); i++) { + mListeners[i]->NotifyStkCommand(cmd); + } + + return true; +} + +bool +IccChild::RecvNotifyStkSessionEnd() +{ + for (int32_t i = 0; i < mListeners.Count(); i++) { + mListeners[i]->NotifyStkSessionEnd(); + } + + return true; +} + PIccRequestChild* IccChild::AllocPIccRequestChild(const IccRequest& aRequest) { @@ -131,8 +163,8 @@ IccChild::UpdateIccInfo(const OptionalIccInfoData& aInfoData) { // We update the orignal one instead of replacing with a new one // if the IccType is the same. if (mIccInfo) { - nsString oldIccType; - nsString newIccType; + nsAutoString oldIccType; + nsAutoString newIccType; mIccInfo->GetIccType(oldIccType); iccInfo->GetIccType(newIccType); @@ -206,8 +238,8 @@ IccChild::UnlockCardLock(uint32_t aLockType, nsIIccCallback* aRequestReply) { return SendRequest(UnlockCardLockRequest(aLockType, - nsString(aPassword), - nsString(aNewPin)), + nsAutoString(aPassword), + nsAutoString(aNewPin)), aRequestReply) ? NS_OK : NS_ERROR_FAILURE; } @@ -219,7 +251,7 @@ IccChild::SetCardLockEnabled(uint32_t aLockType, nsIIccCallback* aRequestReply) { return SendRequest(SetCardLockEnabledRequest(aLockType, - nsString(aPassword), + nsAutoString(aPassword), aEnabled), aRequestReply) ? NS_OK : NS_ERROR_FAILURE; @@ -232,8 +264,8 @@ IccChild::ChangeCardLockPassword(uint32_t aLockType, nsIIccCallback* aRequestReply) { return SendRequest(ChangeCardLockPasswordRequest(aLockType, - nsString(aPassword), - nsString(aNewPassword)), + nsAutoString(aPassword), + nsAutoString(aNewPassword)), aRequestReply) ? NS_OK : NS_ERROR_FAILURE; } @@ -251,7 +283,7 @@ IccChild::MatchMvno(uint32_t aMvnoType, const nsAString& aMvnoData, nsIIccCallback* aRequestReply) { - return SendRequest(MatchMvnoRequest(aMvnoType, nsString(aMvnoData)), + return SendRequest(MatchMvnoRequest(aMvnoType, nsAutoString(aMvnoData)), aRequestReply) ? NS_OK : NS_ERROR_FAILURE; } @@ -285,6 +317,80 @@ IccChild::IccCloseChannel(int32_t aChannel, nsIIccChannelCallback* aCallback) return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP +IccChild::SendStkResponse(nsIStkProactiveCmd* aCommand, nsIStkTerminalResponse* aResponse) +{ + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, NS_ERROR_FAILURE); + + nsAutoString cmd, response; + + nsresult rv = cmdFactory->DeflateCommand(aCommand, cmd); + NS_ENSURE_SUCCESS(rv, rv); + + rv = cmdFactory->DeflateResponse(aResponse, response); + NS_ENSURE_SUCCESS(rv, rv); + + return PIccChild::SendStkResponse(cmd, response) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +IccChild::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested) +{ + return PIccChild::SendStkMenuSelection(aItemIdentifier, aHelpRequested) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +IccChild::SendStkTimerExpiration(uint16_t aTimerId, uint32_t aTimerValue) +{ + return PIccChild::SendStkTimerExpiration(aTimerId, aTimerValue) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +IccChild::SendStkEventDownload(nsIStkDownloadEvent* aEvent) +{ + MOZ_ASSERT(aEvent); + + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, NS_ERROR_FAILURE); + + nsAutoString event; + + nsresult rv = cmdFactory->DeflateDownloadEvent(aEvent, event); + NS_ENSURE_SUCCESS(rv, rv); + + return PIccChild::SendStkEventDownload(event) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +IccChild::ReadContacts(uint32_t aContactType, nsIIccCallback* aRequestReply) +{ + return SendRequest(ReadContactsRequest(aContactType), + aRequestReply) + ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +IccChild::UpdateContact(uint32_t aContactType, nsIIccContact* aContact, + const nsAString& aPin2, + nsIIccCallback* aRequestReply) +{ + MOZ_ASSERT(aContact); + + IccContactData contactData; + IccIPCUtils::GetIccContactDataFromIccContact(aContact, contactData); + + return SendRequest(UpdateContactRequest(aContactType, + nsAutoString(aPin2), + contactData), + aRequestReply) + ? NS_OK : NS_ERROR_FAILURE; +} + /** * PIccRequestChild Implementation. */ @@ -327,6 +433,42 @@ IccRequestChild::Recv__delete__(const IccReply& aResponse) mRequestReply->NotifyCardLockError(error.message(), error.retryCount())); } + case IccReply::TIccReplyReadContacts: { + const nsTArray& data + = aResponse.get_IccReplyReadContacts().contacts(); + + uint32_t count = data.Length(); + nsCOMArray contactList; + nsresult rv; + for (uint32_t i = 0; i < count; i++) { + nsCOMPtr contact; + rv = IccContact::Create(data[i].id(), + data[i].names(), + data[i].numbers(), + data[i].emails(), + getter_AddRefs(contact)); + NS_ENSURE_SUCCESS(rv, false); + contactList.AppendElement(contact); + } + + rv = mRequestReply->NotifyRetrievedIccContacts(contactList.Elements(), + count); + + return NS_SUCCEEDED(rv); + } + case IccReply::TIccReplyUpdateContact: { + IccContactData data + = aResponse.get_IccReplyUpdateContact().contact(); + nsCOMPtr contact; + IccContact::Create(data.id(), + data.names(), + data.numbers(), + data.emails(), + getter_AddRefs(contact)); + + return NS_SUCCEEDED( + mRequestReply->NotifyUpdatedIccContact(contact)); + } default: MOZ_CRASH("Received invalid response type!"); } diff --git a/dom/icc/ipc/IccChild.h b/dom/icc/ipc/IccChild.h index b8a58bee2c..2215f47845 100644 --- a/dom/icc/ipc/IccChild.h +++ b/dom/icc/ipc/IccChild.h @@ -49,6 +49,12 @@ protected: virtual bool RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData) override; + virtual bool + RecvNotifyStkCommand(const nsString& aStkProactiveCmd) override; + + virtual bool + RecvNotifyStkSessionEnd() override; + private: ~IccChild(); diff --git a/dom/icc/ipc/IccIPCUtils.cpp b/dom/icc/ipc/IccIPCUtils.cpp new file mode 100644 index 0000000000..850019ca88 --- /dev/null +++ b/dom/icc/ipc/IccIPCUtils.cpp @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/icc/IccIPCUtils.h" +#include "mozilla/dom/icc/PIccTypes.h" +#include "nsIIccContact.h" +#include "nsIIccInfo.h" + +namespace mozilla { +namespace dom { +namespace icc { + +/*static*/ void +IccIPCUtils::GetIccInfoDataFromIccInfo(nsIIccInfo* aInInfo, + IccInfoData& aOutData) +{ + aInInfo->GetIccType(aOutData.iccType()); + aInInfo->GetIccid(aOutData.iccid()); + aInInfo->GetMcc(aOutData.mcc()); + aInInfo->GetMnc(aOutData.mnc()); + aInInfo->GetSpn(aOutData.spn()); + aInInfo->GetIsDisplayNetworkNameRequired( + &aOutData.isDisplayNetworkNameRequired()); + aInInfo->GetIsDisplaySpnRequired( + &aOutData.isDisplaySpnRequired()); + + nsCOMPtr gsmIccInfo(do_QueryInterface(aInInfo)); + if (gsmIccInfo) { + gsmIccInfo->GetMsisdn(aOutData.phoneNumber()); + } + + nsCOMPtr cdmaIccInfo(do_QueryInterface(aInInfo)); + if (cdmaIccInfo) { + cdmaIccInfo->GetMdn(aOutData.phoneNumber()); + cdmaIccInfo->GetPrlVersion(&aOutData.prlVersion()); + } +} + +/*static*/ void +IccIPCUtils::GetIccContactDataFromIccContact(nsIIccContact* aContact, + IccContactData& aOutData){ + // Id + nsresult rv = aContact->GetId(aOutData.id()); + NS_ENSURE_SUCCESS_VOID(rv); + + // Names + char16_t** rawStringArray = nullptr; + uint32_t count = 0; + rv = aContact->GetNames(&count, &rawStringArray); + NS_ENSURE_SUCCESS_VOID(rv); + if (count > 0) { + for (uint32_t i = 0; i < count; i++) { + aOutData.names().AppendElement(nsDependentString(rawStringArray[i])); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } + + // Numbers + rawStringArray = nullptr; + count = 0; + rv = aContact->GetNumbers(&count, &rawStringArray); + NS_ENSURE_SUCCESS_VOID(rv); + if (count > 0) { + for (uint32_t i = 0; i < count; i++) { + aOutData.numbers().AppendElement(nsDependentString(rawStringArray[i])); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } + + // Emails + rawStringArray = nullptr; + count = 0; + rv = aContact->GetEmails(&count, &rawStringArray); + NS_ENSURE_SUCCESS_VOID(rv); + if (count > 0) { + for (uint32_t i = 0; i < count; i++) { + aOutData.emails().AppendElement(nsDependentString(rawStringArray[i])); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray); + } +} + +} // namespace icc +} // namespace dom +} // namespace mozilla \ No newline at end of file diff --git a/dom/icc/ipc/IccIPCUtils.h b/dom/icc/ipc/IccIPCUtils.h new file mode 100644 index 0000000000..8875d1c2a4 --- /dev/null +++ b/dom/icc/ipc/IccIPCUtils.h @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_icc_IccIPCUtils_h +#define mozilla_dom_icc_IccIPCUtils_h + +class nsIIccContact; +class nsIIccInfo; + +namespace mozilla { +namespace dom { +namespace icc { + +class IccInfoData; +class IccContactData; + +class IccIPCUtils +{ +public: + static void GetIccInfoDataFromIccInfo(nsIIccInfo* aInInfo, + IccInfoData& aOutData); + static void GetIccContactDataFromIccContact(nsIIccContact* aContact, + IccContactData& aOutData); + +private: + IccIPCUtils() {} + virtual ~IccIPCUtils() {} +}; + +} // namespace icc +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_icc_IccIPCUtils_h \ No newline at end of file diff --git a/dom/icc/ipc/IccParent.cpp b/dom/icc/ipc/IccParent.cpp index 82e0eaf37c..86c0e0c5c0 100644 --- a/dom/icc/ipc/IccParent.cpp +++ b/dom/icc/ipc/IccParent.cpp @@ -4,44 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/dom/icc/IccIPCUtils.h" #include "mozilla/dom/icc/IccParent.h" #include "nsIIccService.h" -#include "IccInfo.h" - -using mozilla::dom::IccInfo; +#include "nsIStkCmdFactory.h" +#include "nsIStkProactiveCmd.h" namespace mozilla { namespace dom { namespace icc { -namespace { - -static void -GetIccInfoDataFromIccInfo(nsIIccInfo* aInInfo, IccInfoData& aOutData) { - aInInfo->GetIccType(aOutData.iccType()); - aInInfo->GetIccid(aOutData.iccid()); - aInInfo->GetMcc(aOutData.mcc()); - aInInfo->GetMnc(aOutData.mnc()); - aInInfo->GetSpn(aOutData.spn()); - aInInfo->GetIsDisplayNetworkNameRequired( - &aOutData.isDisplayNetworkNameRequired()); - aInInfo->GetIsDisplaySpnRequired( - &aOutData.isDisplaySpnRequired()); - - nsCOMPtr gsmIccInfo(do_QueryInterface(aInInfo)); - if (gsmIccInfo) { - gsmIccInfo->GetMsisdn(aOutData.phoneNumber()); - } - - nsCOMPtr cdmaIccInfo(do_QueryInterface(aInInfo)); - if (cdmaIccInfo) { - cdmaIccInfo->GetMdn(aOutData.phoneNumber()); - cdmaIccInfo->GetPrlVersion(&aOutData.prlVersion()); - } -} - -} // anonymous namespace - /** * PIccParent Implementation. */ @@ -86,7 +58,7 @@ IccParent::RecvInit(OptionalIccInfoData* aInfoData, if (iccInfo) { IccInfoData data; - GetIccInfoDataFromIccInfo(iccInfo, data); + IccIPCUtils::GetIccInfoDataFromIccInfo(iccInfo, data); *aInfoData = OptionalIccInfoData(data); return true; @@ -97,6 +69,72 @@ IccParent::RecvInit(OptionalIccInfoData* aInfoData, return true; } +bool +IccParent::RecvStkResponse(const nsString& aCmd, const nsString& aResponse) +{ + NS_ENSURE_TRUE(mIcc, false); + + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, false); + + nsCOMPtr cmd; + cmdFactory->InflateCommand(aCmd, getter_AddRefs(cmd)); + NS_ENSURE_TRUE(cmd, false); + + nsCOMPtr response; + cmdFactory->InflateResponse(aResponse, getter_AddRefs(response)); + NS_ENSURE_TRUE(response, false); + + nsresult rv = mIcc->SendStkResponse(cmd, response); + NS_ENSURE_SUCCESS(rv, false); + + return true; +} + +bool +IccParent::RecvStkMenuSelection(const uint16_t& aItemIdentifier, + const bool& aHelpRequested) +{ + NS_ENSURE_TRUE(mIcc, false); + + nsresult rv = mIcc->SendStkMenuSelection(aItemIdentifier, aHelpRequested); + NS_ENSURE_SUCCESS(rv, false); + + return true; +} + +bool +IccParent::RecvStkTimerExpiration(const uint16_t& aTimerId, + const uint32_t& aTimerValue) +{ + NS_ENSURE_TRUE(mIcc, false); + + nsresult rv = mIcc->SendStkTimerExpiration(aTimerId, aTimerValue); + NS_ENSURE_SUCCESS(rv, false); + + return true; +} + +bool +IccParent::RecvStkEventDownload(const nsString& aEvent) +{ + NS_ENSURE_TRUE(mIcc, false); + + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, false); + + nsCOMPtr event; + cmdFactory->InflateDownloadEvent(aEvent, getter_AddRefs(event)); + NS_ENSURE_TRUE(event, false); + + nsresult rv = mIcc->SendStkEventDownload(event); + NS_ENSURE_SUCCESS(rv, false); + + return true; +} + PIccRequestParent* IccParent::AllocPIccRequestParent(const IccRequest& aRequest) { @@ -140,6 +178,10 @@ IccParent::RecvPIccRequestConstructor(PIccRequestParent* aActor, return actor->DoRequest(aRequest.get_MatchMvnoRequest()); case IccRequest::TGetServiceStateEnabledRequest: return actor->DoRequest(aRequest.get_GetServiceStateEnabledRequest()); + case IccRequest::TReadContactsRequest: + return actor->DoRequest(aRequest.get_ReadContactsRequest()); + case IccRequest::TUpdateContactRequest: + return actor->DoRequest(aRequest.get_UpdateContactRequest()); default: MOZ_CRASH("Received invalid request type!"); } @@ -154,17 +196,23 @@ IccParent::RecvPIccRequestConstructor(PIccRequestParent* aActor, NS_IMPL_ISUPPORTS(IccParent, nsIIccListener) NS_IMETHODIMP -IccParent::NotifyStkCommand(const nsAString & aMessage) +IccParent::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd) { - // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL. - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr cmdFactory = + do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); + NS_ENSURE_TRUE(cmdFactory, NS_ERROR_UNEXPECTED); + + nsAutoString cmd; + nsresult rv = cmdFactory->DeflateCommand(aStkProactiveCmd, cmd); + NS_ENSURE_SUCCESS(rv, rv); + + return SendNotifyStkCommand(cmd) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccParent::NotifyStkSessionEnd() { - // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL. - return NS_ERROR_NOT_IMPLEMENTED; + return SendNotifyStkSessionEnd() ? NS_OK : NS_ERROR_FAILURE;; } NS_IMETHODIMP @@ -194,7 +242,7 @@ IccParent::NotifyIccInfoChanged() } IccInfoData data; - GetIccInfoDataFromIccInfo(iccInfo, data); + IccIPCUtils::GetIccInfoDataFromIccInfo(iccInfo, data); return SendNotifyIccInfoChanged(OptionalIccInfoData(data)) ? NS_OK : NS_ERROR_FAILURE; @@ -272,6 +320,30 @@ IccRequestParent::DoRequest(const GetServiceStateEnabledRequest& aRequest) this)); } +bool +IccRequestParent::DoRequest(const ReadContactsRequest& aRequest) +{ + return NS_SUCCEEDED(mIcc->ReadContacts(aRequest.contactType(), + this)); +} + +bool +IccRequestParent::DoRequest(const UpdateContactRequest& aRequest) +{ + nsCOMPtr contact; + nsresult rv = IccContact::Create(aRequest.contact().id(), + aRequest.contact().names(), + aRequest.contact().numbers(), + aRequest.contact().emails(), + getter_AddRefs(contact)); + NS_ENSURE_SUCCESS(rv, false); + + return NS_SUCCEEDED(mIcc->UpdateContact(aRequest.contactType(), + contact, + aRequest.pin2(), + this)); +} + nsresult IccRequestParent::SendReply(const IccReply& aReply) { @@ -307,16 +379,46 @@ IccRequestParent::NotifyGetCardLockRetryCount(int32_t aCount) NS_IMETHODIMP IccRequestParent::NotifyError(const nsAString & aErrorMsg) { - return SendReply(IccReplyError(nsString(aErrorMsg))); + return SendReply(IccReplyError(nsAutoString(aErrorMsg))); } NS_IMETHODIMP IccRequestParent::NotifyCardLockError(const nsAString & aErrorMsg, int32_t aRetryCount) { - return SendReply(IccReplyCardLockError(aRetryCount, nsString(aErrorMsg))); + return SendReply(IccReplyCardLockError(aRetryCount, nsAutoString(aErrorMsg))); +} + +NS_IMETHODIMP +IccRequestParent::NotifyRetrievedIccContacts(nsIIccContact** aContacts, + unsigned int aCount) +{ + nsTArray contacts; + + for (uint32_t i = 0; i < aCount; i++) { + MOZ_ASSERT(aContacts[i]); + + IccContactData contactData; + + IccIPCUtils::GetIccContactDataFromIccContact(aContacts[i], contactData); + contacts.AppendElement(contactData); + } + + return SendReply(IccReplyReadContacts(contacts)); +} + +NS_IMETHODIMP +IccRequestParent::NotifyUpdatedIccContact(nsIIccContact* aContact) +{ + MOZ_ASSERT(aContact); + + IccContactData contactData; + + IccIPCUtils::GetIccContactDataFromIccContact(aContact, contactData); + + return SendReply(IccReplyUpdateContact(contactData)); } } // namespace icc } // namespace dom -} // namespace mozilla \ No newline at end of file +} // namespace mozilla diff --git a/dom/icc/ipc/IccParent.h b/dom/icc/ipc/IccParent.h index 7facce4e95..2c356d1cd6 100644 --- a/dom/icc/ipc/IccParent.h +++ b/dom/icc/ipc/IccParent.h @@ -39,6 +39,20 @@ protected: OptionalIccInfoData* aInfoData, uint32_t* aCardState) override; + virtual bool + RecvStkResponse(const nsString& aCmd, const nsString& aResponse) override; + + virtual bool + RecvStkMenuSelection(const uint16_t& aItemIdentifier, + const bool& aHelpRequested) override; + + virtual bool + RecvStkTimerExpiration(const uint16_t& aTimerId, + const uint32_t& aTimerValue) override; + + virtual bool + RecvStkEventDownload(const nsString& aEvent) override; + virtual PIccRequestParent* AllocPIccRequestParent(const IccRequest& aRequest) override; @@ -96,6 +110,12 @@ private: bool DoRequest(const GetServiceStateEnabledRequest& aRequest); + bool + DoRequest(const ReadContactsRequest& aRequest); + + bool + DoRequest(const UpdateContactRequest& aRequest); + nsresult SendReply(const IccReply& aReply); diff --git a/dom/icc/ipc/PIcc.ipdl b/dom/icc/ipc/PIcc.ipdl index 88edc2b17f..3a264a102d 100644 --- a/dom/icc/ipc/PIcc.ipdl +++ b/dom/icc/ipc/PIcc.ipdl @@ -60,6 +60,18 @@ struct GetServiceStateEnabledRequest uint32_t service; }; +struct ReadContactsRequest +{ + uint32_t contactType; +}; + +struct UpdateContactRequest +{ + uint32_t contactType; + nsString pin2; + IccContactData contact; +}; + union IccRequest { GetCardLockEnabledRequest; @@ -69,6 +81,8 @@ union IccRequest GetCardLockRetryCountRequest; MatchMvnoRequest; GetServiceStateEnabledRequest; + ReadContactsRequest; + UpdateContactRequest; }; sync protocol PIcc @@ -87,6 +101,19 @@ child: */ NotifyIccInfoChanged(OptionalIccInfoData aInfoData); + /** + * Notify STK proactive command issue by selected UICC. + * + * @param aStkProactiveCmd + * a MozStkCommand instance serialized in JSON. + */ + NotifyStkCommand(nsString aStkProactiveCmd); + + /** + * Notify that STK session is ended by selected UICC. + */ + NotifyStkSessionEnd(); + parent: /** * Sent when the child no longer needs to use PIcc. @@ -98,6 +125,34 @@ parent: */ PIccRequest(IccRequest aRequest); + /** + * Send STK response to the selected UICC. + * + * @param aCommand + * a MozStkCommand instance serialized in JSON. + * @param aResponse + * a MozStkResponse instance serialized in JSON. + */ + StkResponse(nsString aCommand, nsString aResponse); + + /** + * Send STK Menu Selection to the selected UICC. + */ + StkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested); + + /** + * Send STK Timer Expiration to the selected UICC. + */ + StkTimerExpiration(uint16_t aTimerId, uint32_t aTimerValue); + + /** + * Send STK Event Download to the selected UICC. + * + * @param aEvent + * a MozStkXxxEvent instance serialized in JSON. + */ + StkEventDownload(nsString aEvent); + /** * Sync call to initialize the updated IccInfo/CardState. */ diff --git a/dom/icc/ipc/PIccRequest.ipdl b/dom/icc/ipc/PIccRequest.ipdl index afe2c38649..5c8ab1f38c 100644 --- a/dom/icc/ipc/PIccRequest.ipdl +++ b/dom/icc/ipc/PIccRequest.ipdl @@ -34,12 +34,24 @@ struct IccReplyCardLockError nsString message; }; +struct IccReplyReadContacts +{ + IccContactData[] contacts; +}; + +struct IccReplyUpdateContact +{ + IccContactData contact; +}; + union IccReply { // Success IccReplySuccess; IccReplySuccessWithBoolean; IccReplyCardLockRetryCount; + IccReplyReadContacts; + IccReplyUpdateContact; // Error IccReplyError; IccReplyCardLockError; diff --git a/dom/icc/ipc/PIccTypes.ipdlh b/dom/icc/ipc/PIccTypes.ipdlh index 1a463f8ebc..8ba8e4afa1 100644 --- a/dom/icc/ipc/PIccTypes.ipdlh +++ b/dom/icc/ipc/PIccTypes.ipdlh @@ -19,6 +19,14 @@ struct IccInfoData int32_t prlVersion; }; +struct IccContactData +{ + nsString id; + nsString[] names; + nsString[] numbers; + nsString[] emails; +}; + } // namespace icc } // namespace dom } // namespace mozilla \ No newline at end of file diff --git a/dom/icc/moz.build b/dom/icc/moz.build index 257dc9a752..7a4f394a42 100644 --- a/dom/icc/moz.build +++ b/dom/icc/moz.build @@ -15,7 +15,8 @@ EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom.icc += [ 'ipc/IccChild.h', - 'ipc/IccParent.h', + 'ipc/IccIPCUtils.h', + 'ipc/IccParent.h' ] UNIFIED_SOURCES += [ @@ -23,11 +24,13 @@ UNIFIED_SOURCES += [ 'Icc.cpp', 'IccCallback.cpp', 'IccCardLockError.cpp', + 'IccContact.cpp', "IccInfo.cpp", 'IccListener.cpp', 'IccManager.cpp', 'ipc/IccChild.cpp', 'ipc/IccIPCService.cpp', + 'ipc/IccIPCUtils.cpp', 'ipc/IccParent.cpp', ] @@ -38,12 +41,11 @@ IPDL_SOURCES += [ ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: - EXTRA_JS_MODULES += [ - 'gonk/StkProactiveCmdFactory.jsm', - ] EXTRA_COMPONENTS += [ 'gonk/IccService.js', 'gonk/IccService.manifest', + 'gonk/StkCmdFactory.js', + 'gonk/StkCmdFactory.manifest' ] FAIL_ON_WARNINGS = True diff --git a/dom/mobileconnection/MobileConnection.cpp b/dom/mobileconnection/MobileConnection.cpp index de09623da3..febcdb188d 100644 --- a/dom/mobileconnection/MobileConnection.cpp +++ b/dom/mobileconnection/MobileConnection.cpp @@ -22,7 +22,6 @@ #include "nsIVariant.h" #include "nsJSON.h" #include "nsJSUtils.h" -#include "nsRadioInterfaceLayer.h" #include "nsServiceManagerUtils.h" #define MOBILECONN_ERROR_INVALID_PARAMETER NS_LITERAL_STRING("InvalidParameter") @@ -1129,7 +1128,7 @@ MobileConnection::NotifyNetworkSelectionModeChanged() // nsIIccListener NS_IMETHODIMP -MobileConnection::NotifyStkCommand(const nsAString& aMessage) +MobileConnection::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd) { return NS_OK; } diff --git a/dom/mobileconnection/gonk/MobileConnectionService.js b/dom/mobileconnection/gonk/MobileConnectionService.js index a1cf57ce97..3cb897dbae 100644 --- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -537,10 +537,10 @@ MobileConnectionProvider.prototype = { updateDataInfo: function(aNewInfo, aBatch = false) { // For the data connection, the `connected` flag indicates whether // there's an active data call. We get correct `connected` state here. - let active = gNetworkManager.active; + let active = gNetworkManager.activeNetworkInfo; aNewInfo.connected = false; if (active && - active.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE && + active.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE && active.serviceId === this._clientId) { aNewInfo.connected = true; } @@ -1422,11 +1422,10 @@ MobileConnectionService.prototype = { } break; case NS_DATA_CALL_ERROR_TOPIC_ID: - let network = aSubject; try { - if (network instanceof Ci.nsIRilNetworkInterface) { - let rilNetwork = network.QueryInterface(Ci.nsIRilNetworkInterface); - this.notifyDataError(rilNetwork.serviceId, rilNetwork); + if (aSubject instanceof Ci.nsIRilNetworkInfo) { + let rilInfo = aSubject.QueryInterface(Ci.nsIRilNetworkInfo); + this.notifyDataError(rilInfo.serviceId, aData); } } catch (e) {} break; diff --git a/dom/mobilemessage/gonk/MmsService.js b/dom/mobilemessage/gonk/MmsService.js index 4337b75732..0ace86cf5f 100644 --- a/dom/mobilemessage/gonk/MmsService.js +++ b/dom/mobilemessage/gonk/MmsService.js @@ -232,10 +232,10 @@ MmsConnection.prototype = { mmsProxy: "", mmsPort: -1, - setApnSetting: function(network) { - this.mmsc = network.mmsc; - this.mmsProxy = network.mmsProxy; - this.mmsPort = network.mmsPort; + setApnSetting: function(networkInfo) { + this.mmsc = networkInfo.mmsc; + this.mmsProxy = networkInfo.mmsProxy; + this.mmsPort = networkInfo.mmsPort; }, get proxyInfo() { @@ -273,8 +273,8 @@ MmsConnection.prototype = { // cache of hosts to be accessed when this connection is alive. hostsToRoute: null, - // cache of the networkInterface acquired during this connection. - networkInterface: null, + // cache of the networkInfo acquired during this connection. + networkInfo: null, connectTimer: null, @@ -308,14 +308,14 @@ MmsConnection.prototype = { // Clear cache. this.hostsToRoute = []; - this.networkInterface = null; + this.networkInfo = null; - this.radioInterface.deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS); + this.radioInterface.deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS); }; let promises = this.hostsToRoute.map((aHost) => { - return gNetworkManager.removeHostRoute(this.networkInterface, aHost); + return gNetworkManager.removeHostRoute(this.networkInfo, aHost); }); return Promise.all(promises) @@ -447,7 +447,7 @@ MmsConnection.prototype = { // Bug 1059110: Ensure all the initialization are done before setup data call. if (DEBUG) debug("acquire: buffer the MMS request and setup the MMS data call."); - this.radioInterface.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS); + this.radioInterface.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS); return false; } @@ -499,7 +499,7 @@ MmsConnection.prototype = { host = uri.host; } catch (e) {} - return gNetworkManager.addHostRoute(this.networkInterface, host) + return gNetworkManager.addHostRoute(this.networkInfo, host) .then(() => { if (this.hostsToRoute.indexOf(host) < 0) { this.hostsToRoute.push(host); @@ -522,20 +522,20 @@ MmsConnection.prototype = { observe: function(subject, topic, data) { switch (topic) { case kNetworkConnStateChangedTopic: { - // The network for MMS connection must be nsIRilNetworkInterface. - if (!(subject instanceof Ci.nsIRilNetworkInterface)) { + // The network info for MMS connection must be nsIRilNetworkInfo. + if (!(subject instanceof Ci.nsIRilNetworkInfo)) { return; } // Check if the network state change belongs to this service. - let network = subject.QueryInterface(Ci.nsIRilNetworkInterface); - if (network.serviceId != this.serviceId || - network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) { + let networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo); + if (networkInfo.serviceId != this.serviceId || + networkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS) { return; } let connected = - network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED; + networkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED; // Return if the MMS network state doesn't change, where the network // state change can come from other non-MMS networks. @@ -546,16 +546,16 @@ MmsConnection.prototype = { this.connected = connected; if (!this.connected) { this.hostsToRoute = []; - this.networkInterface = null; + this.networkInfo = null; return; } // Set up the MMS APN setting based on the connected MMS network, // which is going to be used for the HTTP requests later. - this.setApnSetting(network); + this.setApnSetting(networkInfo); - // Cache connected network. - this.networkInterface = network; + // Cache connected network info. + this.networkInfo = networkInfo; if (DEBUG) debug("Got the MMS network connected! Resend the buffered " + "MMS requests: number: " + this.pendingCallbacks.length); @@ -741,18 +741,18 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function() { cancellable.done(aHttpStatus, aData)); }; - mmsConnection.ensureRouting(url) - .then(() => startTransaction(), - (aError) => { - debug("Failed to ensureRouting: " + aError); + let onRejected = aReason => { + debug('Failed to start a transaction: ' + aReason); + mmsConnection.release(); + cancellable.done(_HTTP_STATUS_FAILED_TO_ROUTE, null); + }; // TODO: |getNetId| will be implemented as a sync call in nsINetworkManager // once Bug 1141903 is landed. mmsConnection.ensureRouting(url) - .then(() => gNetworkService.getNetId(mmsConnection.networkInterface.name), - (aReason) => onRejected('Failed to ensureRouting: ' + aReason)) - .then((netId) => startTransaction(netId), - (aReason) => onRejected('Failed to getNetId: ' + aReason)); + .then(() => gNetworkService.getNetId(mmsConnection.networkInfo.name)) + .then((netId) => startTransaction(netId)) + .catch((aReason) => onRejected(aReason)); }); return cancellable; diff --git a/dom/push/PushServiceWebSocket.jsm b/dom/push/PushServiceWebSocket.jsm index 315c87708f..b8c5a0e9fd 100644 --- a/dom/push/PushServiceWebSocket.jsm +++ b/dom/push/PushServiceWebSocket.jsm @@ -1331,8 +1331,8 @@ let PushNetworkInfo = { let nm = Cc["@mozilla.org/network/manager;1"] .getService(Ci.nsINetworkManager); - if (nm.active && - nm.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) { + if (nm.activeNetworkInfo && + nm.activeNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) { let iccService = Cc["@mozilla.org/icc/iccservice;1"] .getService(Ci.nsIIccService); // TODO: Bug 927721 - PushService for multi-sim @@ -1348,7 +1348,7 @@ let PushNetworkInfo = { let ips = {}; let prefixLengths = {}; - nm.active.getAddresses(ips, prefixLengths); + nm.activeNetworkInfo.getAddresses(ips, prefixLengths); return { mcc: iccInfo.mcc, diff --git a/dom/simplepush/PushService.jsm b/dom/simplepush/PushService.jsm index c375751e0a..d9911788dc 100644 --- a/dom/simplepush/PushService.jsm +++ b/dom/simplepush/PushService.jsm @@ -1774,7 +1774,8 @@ this.PushService = { } let nm = Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager); - if (nm.active && nm.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) { + if (nm.activeNetworkInfo && + nm.activeNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) { let iccService = Cc["@mozilla.org/icc/iccservice;1"].getService(Ci.nsIIccService); // TODO: Bug 927721 - PushService for multi-sim // In Multi-sim, there is more than one client in iccService. Each @@ -1789,7 +1790,7 @@ this.PushService = { let ips = {}; let prefixLengths = {}; - nm.active.getAddresses(ips, prefixLengths); + nm.activeNetworkInfo.getAddresses(ips, prefixLengths); return { mcc: iccInfo.mcc, diff --git a/dom/system/gonk/DataCallManager.js b/dom/system/gonk/DataCallManager.js index 02015d2943..0d8431be5f 100644 --- a/dom/system/gonk/DataCallManager.js +++ b/dom/system/gonk/DataCallManager.js @@ -53,7 +53,9 @@ const DATACALLMANAGER_CID = const DATACALLHANDLER_CID = Components.ID("{132b650f-c4d8-4731-96c5-83785cb31dee}"); const RILNETWORKINTERFACE_CID = - Components.ID("{8c11bef9-9b4f-4d96-bed7-f5a1f48eabda}"); + Components.ID("{9574ee84-5d0d-4814-b9e6-8b279e03dcf4}"); +const RILNETWORKINFO_CID = + Components.ID("{dd6cf2f0-f0e3-449f-a69e-7c34fdcb8d4b}"); const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown"; const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed"; @@ -61,20 +63,20 @@ const TOPIC_PREF_CHANGED = "nsPref:changed"; const TOPIC_DATA_CALL_ERROR = "data-call-error"; const PREF_RIL_DEBUG_ENABLED = "ril.debugging.enabled"; -const NETWORK_TYPE_UNKNOWN = Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN; -const NETWORK_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI; -const NETWORK_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE; -const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS; -const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL; -const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS; -const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN; -const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_FOTA; +const NETWORK_TYPE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_TYPE_UNKNOWN; +const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI; +const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE; +const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS; +const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL; +const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS; +const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN; +const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA; -const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN; -const NETWORK_STATE_CONNECTING = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTING; -const NETWORK_STATE_CONNECTED = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED; -const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTING; -const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED; +const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN; +const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING; +const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED; +const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING; +const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED; const INT32_MAX = 2147483647; @@ -415,7 +417,7 @@ DataCallHandler.prototype = { this._dataCalls = []; this.clientId = null; - this.dataCallinterface.unregisterListener(this); + this.dataCallInterface.unregisterListener(this); this.dataCallInterface = null; let mobileConnection = @@ -625,8 +627,8 @@ DataCallHandler.prototype = { return; } let wifi_active = false; - if (gNetworkManager.active && - gNetworkManager.active.type == NETWORK_TYPE_WIFI) { + if (gNetworkManager.activeNetworkInfo && + gNetworkManager.activeNetworkInfo.type == NETWORK_TYPE_WIFI) { wifi_active = true; } @@ -709,7 +711,7 @@ DataCallHandler.prototype = { if (!networkInterface) { return NETWORK_STATE_UNKNOWN; } - return networkInterface.state; + return networkInterface.info.state; }, setupDataCallByType: function(aNetworkType) { @@ -760,8 +762,8 @@ DataCallHandler.prototype = { let dataDisconnecting = false; this.dataNetworkInterfaces.forEach(function(networkInterface) { if (networkInterface.enabled) { - if (networkInterface.state != NETWORK_STATE_UNKNOWN && - networkInterface.state != NETWORK_STATE_DISCONNECTED) { + if (networkInterface.info.state != NETWORK_STATE_UNKNOWN && + networkInterface.info.state != NETWORK_STATE_DISCONNECTED) { dataDisconnecting = true; } networkInterface.disconnect(); @@ -836,23 +838,14 @@ DataCallHandler.prototype = { /** * Notify about data call setup error, called from DataCall. */ - notifyDataCallError: function(aMessage) { + notifyDataCallError: function(aDataCall, aErrorMsg) { // Notify data call error only for data APN let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE); if (networkInterface && networkInterface.enabled) { let dataCall = networkInterface.dataCall; - // If there is a cid, compare cid; otherwise it is probably an error on - // data call setup. - if (aMessage.cid !== undefined) { - if (aMessage.linkInfo.cid == dataCall.linkInfo.cid) { - Services.obs.notifyObservers(networkInterface, TOPIC_DATA_CALL_ERROR, - null); - } - } else { - if (this._compareDataCallOptions(dataCall, aMessage)) { - Services.obs.notifyObservers(networkInterface, TOPIC_DATA_CALL_ERROR, - null); - } + if (this._compareDataCallOptions(dataCall, aDataCall)) { + Services.obs.notifyObservers(networkInterface.info, + TOPIC_DATA_CALL_ERROR, aErrorMsg); } } }, @@ -1065,7 +1058,7 @@ DataCall.prototype = { } // Let DataCallHandler notify MobileConnectionService - this.dataCallHandler.notifyDataCallError(this); + this.dataCallHandler.notifyDataCallError(this, errorMsg); // For suggestedRetryTime, the value of INT32_MAX(0x7fffffff) means no retry. if (aDataCall.suggestedRetryTime === INT32_MAX || @@ -1242,7 +1235,7 @@ DataCall.prototype = { inRequestedTypes: function(aType) { for (let i = 0; i < this.requestedNetworkIfaces.length; i++) { - if (this.requestedNetworkIfaces[i].type == aType) { + if (this.requestedNetworkIfaces[i].info.type == aType) { return true; } } @@ -1279,7 +1272,7 @@ DataCall.prototype = { }, connect: function(aNetworkInterface) { - if (DEBUG) this.debug("connect: " + aNetworkInterface.type); + if (DEBUG) this.debug("connect: " + aNetworkInterface.info.type); if (this.requestedNetworkIfaces.indexOf(aNetworkInterface) == -1) { this.requestedNetworkIfaces.push(aNetworkInterface); @@ -1295,7 +1288,7 @@ DataCall.prototype = { Services.tm.currentThread.dispatch(() => { // Do not notify if state changed while this event was being dispatched, // the state probably was notified already or need not to be notified. - if (aNetworkInterface.state == RIL.GECKO_NETWORK_STATE_CONNECTED) { + if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_CONNECTED) { aNetworkInterface.notifyRILNetworkInterface(); } }, Ci.nsIEventTarget.DISPATCH_NORMAL); @@ -1405,7 +1398,7 @@ DataCall.prototype = { }, disconnect: function(aNetworkInterface) { - if (DEBUG) this.debug("disconnect: " + aNetworkInterface.type); + if (DEBUG) this.debug("disconnect: " + aNetworkInterface.info.type); let index = this.requestedNetworkIfaces.indexOf(aNetworkInterface); if (index != -1) { @@ -1426,7 +1419,7 @@ DataCall.prototype = { Services.tm.currentThread.dispatch(() => { // Do not notify if state changed while this event was being dispatched, // the state probably was notified already or need not to be notified. - if (aNetworkInterface.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) { + if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) { aNetworkInterface.notifyRILNetworkInterface(); // Clear link info after notifying NetworkManager. @@ -1449,7 +1442,7 @@ DataCall.prototype = { }, deactivate: function() { - let reason = Ci.nsINetworkInterface.DATACALL_DEACTIVATE_NO_REASON; + let reason = Ci.nsIDataCallInterface.DATACALL_DEACTIVATE_NO_REASON; if (DEBUG) { this.debug("Going to disconnect data connection cid " + this.linkInfo.cid); } @@ -1481,61 +1474,56 @@ DataCall.prototype = { } }; -function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) { - if (!aDataCall) { - throw new Error("No dataCall for RILNetworkInterface: " + type); - } - - this.dataCallHandler = aDataCallHandler; +function RILNetworkInfo(aClientId, aType, aNetworkInterface) +{ + this.serviceId = aClientId; this.type = aType; - this.apnSetting = aApnSetting; - this.dataCall = aDataCall; - this.enabled = false; + this.networkInterface = aNetworkInterface; } +RILNetworkInfo.prototype = { + classID: RILNETWORKINFO_CID, + classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINFO_CID, + classDescription: "RILNetworkInfo", + interfaces: [Ci.nsINetworkInfo, + Ci.nsIRilNetworkInfo]}), + QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo, + Ci.nsIRilNetworkInfo]), -RILNetworkInterface.prototype = { - classID: RILNETWORKINTERFACE_CID, - classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID, - classDescription: "RILNetworkInterface", - interfaces: [Ci.nsINetworkInterface, - Ci.nsIRilNetworkInterface]}), - QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface, - Ci.nsIRilNetworkInterface]), + networkInterface: null, - // Hold reference to DataCall object which is determined at initilization. - dataCall: null, + getDataCall: function() { + return this.networkInterface.dataCall; + }, - // If this RILNetworkInterface type is enabled or not. - enabled: null, + getApnSetting: function() { + return this.networkInterface.apnSetting; + }, + + debug: function(aMsg) { + dump("-*- RILNetworkInfo[" + this.serviceId + ":" + this.type + "]: " + + aMsg + "\n"); + }, /** - * nsINetworkInterface Implementation + * nsINetworkInfo Implementation */ - get state() { - if (!this.dataCall.inRequestedTypes(this.type)) { + let dataCall = this.getDataCall(); + if (!dataCall.inRequestedTypes(this.type)) { return NETWORK_STATE_DISCONNECTED; } - return this.dataCall.state; + return dataCall.state; }, type: null, get name() { - return this.dataCall.linkInfo.ifname; - }, - - get httpProxyHost() { - return this.apnSetting.proxy || ""; - }, - - get httpProxyPort() { - return this.apnSetting.port || ""; + return this.getDataCall().linkInfo.ifname; }, getAddresses: function(aIps, aPrefixLengths) { - let addresses = this.dataCall.linkInfo.addresses; + let addresses = this.getDataCall().linkInfo.addresses; let ips = []; let prefixLengths = []; @@ -1552,33 +1540,33 @@ RILNetworkInterface.prototype = { }, getGateways: function(aCount) { - let linkInfo = this.dataCall.linkInfo; + let linkInfo = this.getDataCall().linkInfo; if (aCount) { aCount.value = linkInfo.gateways.length; } + return linkInfo.gateways.slice(); }, getDnses: function(aCount) { - let linkInfo = this.dataCall.linkInfo; + let linkInfo = this.getDataCall().linkInfo; if (aCount) { aCount.value = linkInfo.dnses.length; } + return linkInfo.dnses.slice(); }, /** - * nsIRilNetworkInterface Implementation + * nsIRilNetworkInfo Implementation */ - get serviceId() { - return this.dataCallHandler.clientId; - }, + serviceId: 0, get iccId() { - let icc = gIccService.getIccByServiceId(this.dataCallHandler.clientId); + let icc = gIccService.getIccByServiceId(this.serviceId); let iccInfo = icc && icc.iccInfo; return iccInfo && iccInfo.iccid; @@ -1590,7 +1578,7 @@ RILNetworkInterface.prototype = { throw Cr.NS_ERROR_UNEXPECTED; } - return this.apnSetting.mmsc || ""; + return this.getApnSetting().mmsc || ""; }, get mmsProxy() { @@ -1599,7 +1587,7 @@ RILNetworkInterface.prototype = { throw Cr.NS_ERROR_UNEXPECTED; } - return this.apnSetting.mmsproxy || ""; + return this.getApnSetting().mmsproxy || ""; }, get mmsPort() { @@ -1610,26 +1598,66 @@ RILNetworkInterface.prototype = { // Note: Port 0 is reserved, so we treat it as invalid as well. // See http://www.iana.org/assignments/port-numbers - return this.apnSetting.mmsport || -1; + return this.getApnSetting().mmsport || -1; + }, +}; + +function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) { + if (!aDataCall) { + throw new Error("No dataCall for RILNetworkInterface: " + type); + } + + this.dataCallHandler = aDataCallHandler; + this.enabled = false; + this.dataCall = aDataCall; + this.apnSetting = aApnSetting; + + this.info = new RILNetworkInfo(aDataCallHandler.clientId, aType, this); +} + +RILNetworkInterface.prototype = { + classID: RILNETWORKINTERFACE_CID, + classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID, + classDescription: "RILNetworkInterface", + interfaces: [Ci.nsINetworkInterface]}), + QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]), + + // If this RILNetworkInterface type is enabled or not. + enabled: null, + + apnSetting: null, + + dataCall: null, + + /** + * nsINetworkInterface Implementation + */ + + info: null, + + get httpProxyHost() { + return this.apnSetting.proxy || ""; + }, + + get httpProxyPort() { + return this.apnSetting.port || ""; }, // Helpers debug: function(aMsg) { dump("-*- RILNetworkInterface[" + this.dataCallHandler.clientId + ":" + - this.type + "]: " + aMsg + "\n"); + this.info.type + "]: " + aMsg + "\n"); }, - apnSetting: null, - get connected() { - return this.state == NETWORK_STATE_CONNECTED; + return this.info.state == NETWORK_STATE_CONNECTED; }, notifyRILNetworkInterface: function() { if (DEBUG) { - this.debug("notifyRILNetworkInterface type: " + this.type + ", state: " + - this.state); + this.debug("notifyRILNetworkInterface type: " + this.info.type + + ", state: " + this.info.state); } gNetworkManager.updateNetworkInterface(this); diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.cpp b/dom/system/gonk/GonkGPSGeolocationProvider.cpp index 1f2110dd38..eaa5f9983e 100644 --- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp +++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp @@ -25,7 +25,7 @@ #include "nsContentUtils.h" #include "nsGeoPosition.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsINetworkManager.h" +#include "nsINetworkInterface.h" #include "nsIObserverService.h" #include "nsJSUtils.h" #include "nsPrintfCString.h" @@ -354,12 +354,12 @@ int32_t GonkGPSGeolocationProvider::GetDataConnectionState() { if (!mRadioInterface) { - return nsINetworkInterface::NETWORK_STATE_UNKNOWN; + return nsINetworkInfo::NETWORK_STATE_UNKNOWN; } int32_t state; mRadioInterface->GetDataCallStateByType( - nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL, &state); + nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL, &state); return state; } @@ -378,7 +378,7 @@ GonkGPSGeolocationProvider::SetAGpsDataConn(nsAString& aApn) int32_t connectionState = GetDataConnectionState(); NS_ConvertUTF16toUTF8 apn(aApn); - if (connectionState == nsINetworkInterface::NETWORK_STATE_CONNECTED) { + if (connectionState == nsINetworkInfo::NETWORK_STATE_CONNECTED) { // The definition of availability is // 1. The device is connected to the home network // 2. The device is connected to a foreign network and data @@ -395,7 +395,7 @@ GonkGPSGeolocationProvider::SetAGpsDataConn(nsAString& aApn) #else mAGpsInterface->data_conn_open(apn.get()); #endif - } else if (connectionState == nsINetworkInterface::NETWORK_STATE_DISCONNECTED) { + } else if (connectionState == nsINetworkInfo::NETWORK_STATE_DISCONNECTED) { if (hasUpdateNetworkAvailability) { mAGpsRilInterface->update_network_availability(false, apn.get()); } @@ -445,12 +445,12 @@ GonkGPSGeolocationProvider::RequestDataConnection() return; } - if (GetDataConnectionState() == nsINetworkInterface::NETWORK_STATE_CONNECTED) { + if (GetDataConnectionState() == nsINetworkInfo::NETWORK_STATE_CONNECTED) { // Connection is already established, we don't need to setup again. // We just get supl APN and make AGPS data connection state updated. RequestSettingValue("ril.supl.apn"); } else { - mRadioInterface->SetupDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL); + mRadioInterface->SetupDataCallByType(nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL); } } @@ -463,7 +463,7 @@ GonkGPSGeolocationProvider::ReleaseDataConnection() return; } - mRadioInterface->DeactivateDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL); + mRadioInterface->DeactivateDataCallByType(nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL); } void @@ -976,15 +976,15 @@ int ConvertToGpsNetworkType(int aNetworkInterfaceType) { switch (aNetworkInterfaceType) { - case nsINetworkInterface::NETWORK_TYPE_WIFI: + case nsINetworkInfo::NETWORK_TYPE_WIFI: return AGPS_RIL_NETWORK_TYPE_WIFI; - case nsINetworkInterface::NETWORK_TYPE_MOBILE: + case nsINetworkInfo::NETWORK_TYPE_MOBILE: return AGPS_RIL_NETWORK_TYPE_MOBILE; - case nsINetworkInterface::NETWORK_TYPE_MOBILE_MMS: + case nsINetworkInfo::NETWORK_TYPE_MOBILE_MMS: return AGPS_RIL_NETWORK_TYPE_MOBILE_MMS; - case nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL: + case nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL: return AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL; - case nsINetworkInterface::NETWORK_TYPE_MOBILE_DUN: + case nsINetworkInfo::NETWORK_TYPE_MOBILE_DUN: return AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN; default: NS_WARNING(nsPrintfCString("Unknown network type mapping %d", @@ -1003,21 +1003,21 @@ GonkGPSGeolocationProvider::Observe(nsISupports* aSubject, #ifdef MOZ_B2G_RIL if (!strcmp(aTopic, kNetworkConnStateChangedTopic)) { - nsCOMPtr iface = do_QueryInterface(aSubject); - if (!iface) { + nsCOMPtr info = do_QueryInterface(aSubject); + if (!info) { return NS_OK; } - nsCOMPtr rilface = do_QueryInterface(aSubject); + nsCOMPtr rilInfo = do_QueryInterface(aSubject); if (mAGpsRilInterface && mAGpsRilInterface->update_network_state) { int32_t state; int32_t type; - iface->GetState(&state); - iface->GetType(&type); - bool connected = (state == nsINetworkInterface::NETWORK_STATE_CONNECTED); + info->GetState(&state); + info->GetType(&type); + bool connected = (state == nsINetworkInfo::NETWORK_STATE_CONNECTED); bool roaming = false; int gpsNetworkType = ConvertToGpsNetworkType(type); if (gpsNetworkType >= 0) { - if (rilface) { + if (rilInfo) { do { nsCOMPtr service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); @@ -1048,7 +1048,7 @@ GonkGPSGeolocationProvider::Observe(nsISupports* aSubject, } } // No data connection - if (!rilface) { + if (!rilInfo) { return NS_OK; } diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js deleted file mode 100644 index b27f9f438e..0000000000 --- a/dom/system/gonk/RILContentHelper.js +++ /dev/null @@ -1,474 +0,0 @@ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -/* global RIL */ -XPCOMUtils.defineLazyGetter(this, "RIL", function () { - let obj = {}; - Cu.import("resource://gre/modules/ril_consts.js", obj); - return obj; -}); - -const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; - -const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; - -const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; -const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; - -let DEBUG; -function debug(s) { - dump("-*- RILContentHelper: " + s + "\n"); -} - -const RILCONTENTHELPER_CID = - Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}"); - -const RIL_IPC_MSG_NAMES = [ - "RIL:StkCommand", - "RIL:StkSessionEnd", - "RIL:ReadIccContacts", - "RIL:UpdateIccContact", -]; - -/* global cpmm */ -XPCOMUtils.defineLazyServiceGetter(this, "cpmm", - "@mozilla.org/childprocessmessagemanager;1", - "nsISyncMessageSender"); - -/* global UUIDGenerator */ -XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator", - "@mozilla.org/uuid-generator;1", - "nsIUUIDGenerator"); - -/* global gNumRadioInterfaces */ -XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() { - let appInfo = Cc["@mozilla.org/xre/app-info;1"]; - let isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - - if (isParentProcess) { - let ril = { numRadioInterfaces: 0 }; - try { - ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer); - } catch(e) {} - return ril.numRadioInterfaces; - } - - return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); -}); - -function RILContentHelper() { - this.updateDebugFlag(); - - this.numClients = gNumRadioInterfaces; - if (DEBUG) debug("Number of clients: " + this.numClients); - - this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES); - this._windowsMap = []; - this._iccListeners = []; - - Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - - Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); -} - -RILContentHelper.prototype = { - __proto__: DOMRequestIpcHelper.prototype, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccProvider, - Ci.nsIObserver, - Ci.nsISupportsWeakReference]), - classID: RILCONTENTHELPER_CID, - classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID, - classDescription: "RILContentHelper", - interfaces: [Ci.nsIIccProvider]}), - - updateDebugFlag: function() { - try { - DEBUG = RIL.DEBUG_CONTENT_HELPER || - Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); - } catch (e) {} - }, - - _windowsMap: null, - - /** - * nsIIccProvider - */ - - sendStkResponse: function(clientId, window, command, response) { - if (window == null) { - throw Components.Exception("Can't get window object", - Cr.NS_ERROR_UNEXPECTED); - } - response.command = command; - cpmm.sendAsyncMessage("RIL:SendStkResponse", { - clientId: clientId, - data: response - }); - }, - - sendStkMenuSelection: function(clientId, window, itemIdentifier, - helpRequested) { - if (window == null) { - throw Components.Exception("Can't get window object", - Cr.NS_ERROR_UNEXPECTED); - } - cpmm.sendAsyncMessage("RIL:SendStkMenuSelection", { - clientId: clientId, - data: { - itemIdentifier: itemIdentifier, - helpRequested: helpRequested - } - }); - }, - - sendStkTimerExpiration: function(clientId, window, timer) { - if (window == null) { - throw Components.Exception("Can't get window object", - Cr.NS_ERROR_UNEXPECTED); - } - cpmm.sendAsyncMessage("RIL:SendStkTimerExpiration", { - clientId: clientId, - data: { - timer: timer - } - }); - }, - - sendStkEventDownload: function(clientId, window, event) { - if (window == null) { - throw Components.Exception("Can't get window object", - Cr.NS_ERROR_UNEXPECTED); - } - cpmm.sendAsyncMessage("RIL:SendStkEventDownload", { - clientId: clientId, - data: { - event: event - } - }); - }, - - readContacts: function(clientId, window, contactType) { - 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); - this._windowsMap[requestId] = window; - - cpmm.sendAsyncMessage("RIL:ReadIccContacts", { - clientId: clientId, - data: { - requestId: requestId, - contactType: contactType - } - }); - return request; - }, - - updateContact: function(clientId, window, contactType, contact, pin2) { - 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); - this._windowsMap[requestId] = window; - - // Parsing nsDOMContact to Icc Contact format - let iccContact = {}; - - if (Array.isArray(contact.name) && contact.name[0]) { - iccContact.alphaId = contact.name[0]; - } - - if (Array.isArray(contact.tel)) { - iccContact.number = contact.tel[0] && contact.tel[0].value; - let telArray = contact.tel.slice(1); - let length = telArray.length; - if (length > 0) { - iccContact.anr = []; - } - for (let i = 0; i < telArray.length; i++) { - iccContact.anr.push(telArray[i].value); - } - } - - if (Array.isArray(contact.email) && contact.email[0]) { - iccContact.email = contact.email[0].value; - } - - iccContact.contactId = contact.id; - - cpmm.sendAsyncMessage("RIL:UpdateIccContact", { - clientId: clientId, - data: { - requestId: requestId, - contactType: contactType, - contact: iccContact, - pin2: pin2 - } - }); - - return request; - }, - - _iccListeners: null, - - registerListener: function(listenerType, clientId, listener) { - if (!this[listenerType]) { - return; - } - let listeners = this[listenerType][clientId]; - if (!listeners) { - listeners = this[listenerType][clientId] = []; - } - - if (listeners.indexOf(listener) != -1) { - throw new Error("Already registered this listener!"); - } - - listeners.push(listener); - if (DEBUG) debug("Registered " + listenerType + " listener: " + listener); - }, - - unregisterListener: function(listenerType, clientId, listener) { - if (!this[listenerType]) { - return; - } - let listeners = this[listenerType][clientId]; - if (!listeners) { - return; - } - - let index = listeners.indexOf(listener); - if (index != -1) { - listeners.splice(index, 1); - if (DEBUG) debug("Unregistered listener: " + listener); - } - }, - - registerIccMsg: function(clientId, listener) { - if (DEBUG) debug("Registering for ICC related messages"); - this.registerListener("_iccListeners", clientId, listener); - cpmm.sendAsyncMessage("RIL:RegisterIccMsg"); - }, - - unregisterIccMsg: function(clientId, listener) { - this.unregisterListener("_iccListeners", clientId, listener); - }, - - // nsIObserver - - observe: function(subject, topic, data) { - switch (topic) { - case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: - if (data == kPrefRilDebuggingEnabled) { - this.updateDebugFlag(); - } - break; - - case NS_XPCOM_SHUTDOWN_OBSERVER_ID: - this.destroyDOMRequestHelper(); - Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - break; - } - }, - - // nsIMessageListener - - fireRequestSuccess: function(requestId, result) { - let request = this.takeRequest(requestId); - if (!request) { - if (DEBUG) { - debug("not firing success for id: " + requestId + - ", result: " + JSON.stringify(result)); - } - return; - } - - if (DEBUG) { - debug("fire request success, id: " + requestId + - ", result: " + JSON.stringify(result)); - } - Services.DOMRequest.fireSuccess(request, result); - }, - - dispatchFireRequestSuccess: function(requestId, result) { - let currentThread = Services.tm.currentThread; - - currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result), - Ci.nsIThread.DISPATCH_NORMAL); - }, - - fireRequestError: function(requestId, error) { - let request = this.takeRequest(requestId); - if (!request) { - if (DEBUG) { - debug("not firing error for id: " + requestId + - ", error: " + JSON.stringify(error)); - } - return; - } - - if (DEBUG) { - debug("fire request error, id: " + requestId + - ", result: " + JSON.stringify(error)); - } - Services.DOMRequest.fireError(request, error); - }, - - dispatchFireRequestError: function(requestId, error) { - let currentThread = Services.tm.currentThread; - - currentThread.dispatch(this.fireRequestError.bind(this, requestId, error), - Ci.nsIThread.DISPATCH_NORMAL); - }, - - fireRequestDetailedError: function(requestId, detailedError) { - let request = this.takeRequest(requestId); - if (!request) { - if (DEBUG) { - debug("not firing detailed error for id: " + requestId + - ", detailedError: " + JSON.stringify(detailedError)); - } - return; - } - - Services.DOMRequest.fireDetailedError(request, detailedError); - }, - - receiveMessage: function(msg) { - let request; - if (DEBUG) { - debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json)); - } - - let data = msg.json.data; - let clientId = msg.json.clientId; - switch (msg.name) { - case "RIL:StkCommand": - this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand", - [JSON.stringify(data)]); - break; - case "RIL:StkSessionEnd": - this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null); - break; - case "RIL:ReadIccContacts": - this.handleReadIccContacts(data); - break; - case "RIL:UpdateIccContact": - this.handleUpdateIccContact(data); - break; - } - }, - - handleReadIccContacts: function(message) { - if (message.errorMsg) { - this.fireRequestError(message.requestId, message.errorMsg); - return; - } - - let window = this._windowsMap[message.requestId]; - delete this._windowsMap[message.requestId]; - let contacts = message.contacts; - let result = new window.Array(); - contacts.forEach(function(c) { - let prop = {name: [c.alphaId], tel: [{value: c.number}]}; - - if (c.email) { - prop.email = [{value: c.email}]; - } - - // ANR - Additional Number - let anrLen = c.anr ? c.anr.length : 0; - for (let i = 0; i < anrLen; i++) { - prop.tel.push({value: c.anr[i]}); - } - - let contact = new window.mozContact(prop); - contact.id = c.contactId; - result.push(contact); - }); - - this.fireRequestSuccess(message.requestId, result); - }, - - handleUpdateIccContact: function(message) { - if (message.errorMsg) { - this.fireRequestError(message.requestId, message.errorMsg); - return; - } - - let window = this._windowsMap[message.requestId]; - delete this._windowsMap[message.requestId]; - let iccContact = message.contact; - let prop = {name: [iccContact.alphaId], tel: [{value: iccContact.number}]}; - if (iccContact.email) { - prop.email = [{value: iccContact.email}]; - } - - // ANR - Additional Number - let anrLen = iccContact.anr ? iccContact.anr.length : 0; - for (let i = 0; i < anrLen; i++) { - prop.tel.push({value: iccContact.anr[i]}); - } - - let contact = new window.mozContact(prop); - contact.id = iccContact.contactId; - - this.fireRequestSuccess(message.requestId, contact); - }, - - _deliverEvent: function(clientId, listenerType, name, args) { - if (!this[listenerType]) { - return; - } - let thisListeners = this[listenerType][clientId]; - if (!thisListeners) { - return; - } - - let listeners = thisListeners.slice(); - for (let listener of listeners) { - if (thisListeners.indexOf(listener) == -1) { - continue; - } - let handler = listener[name]; - if (typeof handler != "function") { - throw new Error("No handler for " + name); - } - try { - handler.apply(listener, args); - } catch (e) { - if (DEBUG) debug("listener for " + name + " threw an exception: " + e); - } - } - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper]); diff --git a/dom/system/gonk/RILContentHelper.manifest b/dom/system/gonk/RILContentHelper.manifest deleted file mode 100644 index c9a871ba58..0000000000 --- a/dom/system/gonk/RILContentHelper.manifest +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2012 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# RILContentHelper.js -# TODO: Bug 815526, deprecate RILContentHelper: -# To be removed from b2g/installer/package-manifest.in as well. -component {472816e1-1fd6-4405-996c-806f9ea68174} RILContentHelper.js -contract @mozilla.org/ril/content-helper;1 {472816e1-1fd6-4405-996c-806f9ea68174} -category profile-after-change RILContentHelper @mozilla.org/ril/content-helper;1 diff --git a/dom/system/gonk/RILSystemMessenger.jsm b/dom/system/gonk/RILSystemMessenger.jsm index 26fa2d8b45..81373458ce 100644 --- a/dom/system/gonk/RILSystemMessenger.jsm +++ b/dom/system/gonk/RILSystemMessenger.jsm @@ -14,12 +14,6 @@ XPCOMUtils.defineLazyGetter(this, "RIL", function () { return obj; }); -XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() { - let stk = {}; - Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk); - return stk.StkProactiveCmdFactory; -}); - /** * RILSystemMessenger */ @@ -38,6 +32,18 @@ RILSystemMessenger.prototype = { // Function stub to be replaced by the owner of this messenger. }, + /** + * Hook of the function to create MozStkCommand message. + * @param aStkProactiveCmd + * nsIStkProactiveCmd instance. + * + * @return a JS object which complies the dictionary of MozStkCommand defined + * in MozStkCommandEvent.webidl + */ + createCommandMessage: function(aStkProactiveCmd) { + // Function stub to be replaced by the owner of this messenger. + }, + /** * Wrapper to send "telephony-new-call" system message. */ @@ -322,7 +328,7 @@ RILSystemMessenger.prototype = { notifyStkProactiveCommand: function(aIccId, aCommand) { this.broadcastMessage("icc-stkcommand", { iccId: aIccId, - command: gStkCmdFactory.createCommandMessage(aCommand) + command: this.createCommandMessage(aCommand) }); } }; diff --git a/dom/system/gonk/RILSystemMessengerHelper.js b/dom/system/gonk/RILSystemMessengerHelper.js index 642791f8e0..d35fd7a82f 100644 --- a/dom/system/gonk/RILSystemMessengerHelper.js +++ b/dom/system/gonk/RILSystemMessengerHelper.js @@ -21,6 +21,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", "@mozilla.org/system-message-internal;1", "nsISystemMessagesInternal"); +XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory", + "@mozilla.org/icc/stkcmdfactory;1", + "nsIStkCmdFactory"); + let DEBUG = false; function debug(s) { dump("-@- RILSystemMessenger: " + s + "\n"); @@ -45,6 +49,10 @@ function RILSystemMessengerHelper() { gSystemMessenger.broadcastMessage(aType, aMessage); }; + + this.messenger.createCommandMessage = (aStkProactiveCmd) => { + return gStkCmdFactory.createCommandMessage(aStkProactiveCmd); + }; } RILSystemMessengerHelper.prototype = { diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 1701f10e5a..d0e4f76554 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -75,19 +75,8 @@ const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; const RADIO_POWER_OFF_TIMEOUT = 30000; const HW_DEFAULT_CLIENT_ID = 0; -const NETWORK_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI; -const NETWORK_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE; - -// TODO: Bug 815526, deprecate RILContentHelper. -const RIL_IPC_ICCMANAGER_MSG_NAMES = [ - "RIL:SendStkResponse", - "RIL:SendStkMenuSelection", - "RIL:SendStkTimerExpiration", - "RIL:SendStkEventDownload", - "RIL:ReadIccContacts", - "RIL:UpdateIccContact", - "RIL:RegisterIccMsg", -]; +const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI; +const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE; // set to true in ril_consts.js to see debug messages var DEBUG = RIL.DEBUG_RIL; @@ -152,10 +141,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService", "@mozilla.org/cellbroadcast/cellbroadcastservice;1", "nsIGonkCellBroadcastService"); -XPCOMUtils.defineLazyServiceGetter(this, "gIccMessenger", - "@mozilla.org/ril/system-messenger-helper;1", - "nsIIccMessenger"); - XPCOMUtils.defineLazyServiceGetter(this, "gDataCallManager", "@mozilla.org/datacall/manager;1", "nsIDataCallManager"); @@ -164,215 +149,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDataCallInterfaceService", "@mozilla.org/datacall/interfaceservice;1", "nsIGonkDataCallInterfaceService"); -XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() { - let stk = {}; - Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk); - return stk.StkProactiveCmdFactory; -}); - -// TODO: Bug 815526, deprecate RILContentHelper. -XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() { - return { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, - Ci.nsIObserver]), - - ril: null, - - // Manage message targets in terms of topic. Only the authorized and - // registered contents can receive related messages. - targetsByTopic: {}, - topics: [], - - targetMessageQueue: [], - ready: false, - - init: function(ril) { - this.ril = ril; - - Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false); - this._registerMessageListeners(); - }, - - _shutdown: function() { - this.ril = null; - - Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - this._unregisterMessageListeners(); - }, - - _registerMessageListeners: function() { - ppmm.addMessageListener("child-process-shutdown", this); - for (let msgName of RIL_IPC_ICCMANAGER_MSG_NAMES) { - ppmm.addMessageListener(msgName, this); - } - }, - - _unregisterMessageListeners: function() { - ppmm.removeMessageListener("child-process-shutdown", this); - for (let msgName of RIL_IPC_ICCMANAGER_MSG_NAMES) { - ppmm.removeMessageListener(msgName, this); - } - ppmm = null; - }, - - _registerMessageTarget: function(topic, target) { - let targets = this.targetsByTopic[topic]; - if (!targets) { - targets = this.targetsByTopic[topic] = []; - let list = this.topics; - if (list.indexOf(topic) == -1) { - list.push(topic); - } - } - - if (targets.indexOf(target) != -1) { - if (DEBUG) debug("Already registered this target!"); - return; - } - - targets.push(target); - if (DEBUG) debug("Registered " + topic + " target: " + target); - }, - - _unregisterMessageTarget: function(topic, target) { - if (topic == null) { - // Unregister the target for every topic when no topic is specified. - for (let type of this.topics) { - this._unregisterMessageTarget(type, target); - } - return; - } - - // Unregister the target for a specified topic. - let targets = this.targetsByTopic[topic]; - if (!targets) { - return; - } - - let index = targets.indexOf(target); - if (index != -1) { - targets.splice(index, 1); - if (DEBUG) debug("Unregistered " + topic + " target: " + target); - } - }, - - _enqueueTargetMessage: function(topic, message, options) { - let msg = { topic : topic, - message : message, - options : options }; - // Remove previous queued message with the same message type and client Id - // , only one message per (message type + client Id) is allowed in queue. - let messageQueue = this.targetMessageQueue; - for(let i = 0; i < messageQueue.length; i++) { - if (messageQueue[i].message === message && - messageQueue[i].options.clientId === options.clientId) { - messageQueue.splice(i, 1); - break; - } - } - - messageQueue.push(msg); - }, - - _sendTargetMessage: function(topic, message, options) { - if (!this.ready) { - this._enqueueTargetMessage(topic, message, options); - return; - } - - let targets = this.targetsByTopic[topic]; - if (!targets) { - return; - } - - for (let target of targets) { - target.sendAsyncMessage(message, options); - } - }, - - _resendQueuedTargetMessage: function() { - this.ready = true; - - // Here uses this._sendTargetMessage() to resend message, which will - // enqueue message if listener is not ready. - // So only resend after listener is ready, or it will cause infinate loop and - // hang the system. - - // Dequeue and resend messages. - for each (let msg in this.targetMessageQueue) { - this._sendTargetMessage(msg.topic, msg.message, msg.options); - } - this.targetMessageQueue = null; - }, - - /** - * nsIMessageListener interface methods. - */ - - receiveMessage: function(msg) { - if (DEBUG) debug("Received '" + msg.name + "' message from content process"); - if (msg.name == "child-process-shutdown") { - // By the time we receive child-process-shutdown, the child process has - // already forgotten its permissions so we need to unregister the target - // for every permission. - this._unregisterMessageTarget(null, msg.target); - return null; - } - - if (RIL_IPC_ICCMANAGER_MSG_NAMES.indexOf(msg.name) != -1) { - if (!msg.target.assertPermission("mobileconnection")) { - if (DEBUG) { - debug("IccManager message " + msg.name + - " from a content process with no 'mobileconnection' privileges."); - } - return null; - } - } else { - if (DEBUG) debug("Ignoring unknown message type: " + msg.name); - return null; - } - - switch (msg.name) { - case "RIL:RegisterIccMsg": - this._registerMessageTarget("icc", msg.target); - return null; - } - - let clientId = msg.json.clientId || 0; - let radioInterface = this.ril.getRadioInterface(clientId); - if (!radioInterface) { - if (DEBUG) debug("No such radio interface: " + clientId); - return null; - } - - return radioInterface.receiveMessage(msg); - }, - - /** - * nsIObserver interface methods. - */ - - observe: function(subject, topic, data) { - switch (topic) { - case kSysMsgListenerReadyObserverTopic: - Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic); - this._resendQueuedTargetMessage(); - break; - case NS_XPCOM_SHUTDOWN_OBSERVER_ID: - this._shutdown(); - break; - } - }, - - sendIccMessage: function(message, clientId, data) { - this._sendTargetMessage("icc", message, { - clientId: clientId, - data: data - }); - } - }; -}); +XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory", + "@mozilla.org/icc/stkcmdfactory;1", + "nsIStkCmdFactory"); XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() { let _ril = null; @@ -646,7 +425,6 @@ function RadioInterfaceLayer() { Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); - gMessageManager.init(this); // TODO: Bug 815526, deprecate RILContentHelper. gRadioEnabledController.init(this); } RadioInterfaceLayer.prototype = { @@ -870,39 +648,13 @@ WorkerMessenger.prototype = { message.rilMessageType = rilMessageType; this.worker.postMessage(message); - }, - - /** - * Send message to worker and return worker reply to RILContentHelper. - * - * @param msg - * A message object from ppmm. - * @param rilMessageType - * A text string for worker message type. - * @param ipcType [optinal] - * A text string for ipc message type. "msg.name" if omitted. - * - * @TODO: Bug 815526 - deprecate RILContentHelper. - */ - sendWithIPCMessage: function(clientId, msg, rilMessageType, ipcType) { - this.send(clientId, rilMessageType, msg.json.data, (function(reply) { - ipcType = ipcType || msg.name; - msg.target.sendAsyncMessage(ipcType, { - clientId: clientId, - data: reply - }); - return false; - }).bind(this)); } }; function RadioInterface(aClientId, aWorkerMessenger) { this.clientId = aClientId; this.workerMessenger = { - send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId), - // TODO: Bug 815526, deprecate RILContentHelper. - sendWithIPCMessage: - aWorkerMessenger.sendWithIPCMessage.bind(aWorkerMessenger, aClientId), + send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId) }; aWorkerMessenger.registerClient(aClientId, this); @@ -963,11 +715,6 @@ RadioInterface.prototype = { Services.obs.removeObserver(this, kNetworkConnStateChangedTopic); }, - getIccInfo: function() { - let icc = gIccService.getIccByServiceId(this.clientId); - return icc ? icc.iccInfo : null; - }, - isCardPresent: function() { let icc = gIccService.getIccByServiceId(this.clientId); let cardState = icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN; @@ -975,35 +722,6 @@ RadioInterface.prototype = { cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN; }, - /** - * Process a message from the content process. - * - * TODO: Bug 815526, deprecate RILContentHelper - */ - receiveMessage: function(msg) { - switch (msg.name) { - case "RIL:SendStkResponse": - this.workerMessenger.send("sendStkTerminalResponse", msg.json.data); - break; - case "RIL:SendStkMenuSelection": - this.workerMessenger.send("sendStkMenuSelection", msg.json.data); - break; - case "RIL:SendStkTimerExpiration": - this.workerMessenger.send("sendStkTimerExpiration", msg.json.data); - break; - case "RIL:SendStkEventDownload": - this.workerMessenger.send("sendStkEventDownload", msg.json.data); - break; - case "RIL:ReadIccContacts": - this.workerMessenger.sendWithIPCMessage(msg, "readICCContacts"); - break; - case "RIL:UpdateIccContact": - this.workerMessenger.sendWithIPCMessage(msg, "updateICCContact"); - break; - } - return null; - }, - handleUnsolicitedWorkerMessage: function(message) { switch (message.rilMessageType) { case "callRing": @@ -1094,11 +812,11 @@ RadioInterface.prototype = { this.handleIccMwis(message.mwi); break; case "stkcommand": - this.handleStkProactiveCommand(message); + gIccService.notifyStkCommand(this.clientId, + gStkCmdFactory.createCommand(message)); break; case "stksessionend": - // TODO: Bug 815526, deprecate RILContentHelper. - gMessageManager.sendIccMessage("RIL:StkSessionEnd", this.clientId, null); + gIccService.notifyStkSessionEnd(this.clientId); break; case "cdma-info-rec-received": this.handleCdmaInformationRecords(message.records); @@ -1287,18 +1005,6 @@ RadioInterface.prototype = { null, null); }, - handleStkProactiveCommand: function(message) { - if (DEBUG) this.debug("handleStkProactiveCommand " + JSON.stringify(message)); - let iccInfo = this.getIccInfo(); - if (iccInfo && iccInfo.iccid) { - gIccMessenger - .notifyStkProactiveCommand(iccInfo.iccid, - gStkCmdFactory.createCommand(message)); - } - // TODO: Bug 815526, deprecate RILContentHelper. - gMessageManager.sendIccMessage("RIL:StkCommand", this.clientId, message); - }, - _convertCbGsmGeographicalScope: function(aGeographicalScope) { return (aGeographicalScope != null) ? aGeographicalScope @@ -1454,21 +1160,21 @@ RadioInterface.prototype = { this._sntp.updateOffset(offset); break; case kNetworkConnStateChangedTopic: - let network = subject.QueryInterface(Ci.nsINetworkInterface); - if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) { + let networkInfo = subject.QueryInterface(Ci.nsINetworkInfo); + if (networkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { return; } // SNTP can only update when we have mobile or Wifi connections. - if (network.type != NETWORK_TYPE_WIFI && - network.type != NETWORK_TYPE_MOBILE) { + if (networkInfo.type != NETWORK_TYPE_WIFI && + networkInfo.type != NETWORK_TYPE_MOBILE) { return; } // If the network comes from RIL, make sure the RIL service is matched. - if (subject instanceof Ci.nsIRilNetworkInterface) { - network = subject.QueryInterface(Ci.nsIRilNetworkInterface); - if (network.serviceId != this.clientId) { + if (subject instanceof Ci.nsIRilNetworkInfo) { + networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo); + if (networkInfo.serviceId != this.clientId) { return; } } @@ -1548,8 +1254,9 @@ RadioInterface.prototype = { // Set the latest cached NITZ time if it's available. if (this._lastNitzMessage) { this.setClockByNitz(this._lastNitzMessage); - } else if (gNetworkManager.active && gNetworkManager.active.state == - Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) { + } else if (gNetworkManager.activeNetworkInfo && + gNetworkManager.activeNetworkInfo.state == + Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { // Set the latest cached SNTP time if it's available. if (!this._sntp.isExpired()) { this.setClockBySntp(this._sntp.getOffset()); diff --git a/dom/system/gonk/SystemWorkerManager.cpp b/dom/system/gonk/SystemWorkerManager.cpp index a5622f57c9..16d391ad9f 100644 --- a/dom/system/gonk/SystemWorkerManager.cpp +++ b/dom/system/gonk/SystemWorkerManager.cpp @@ -35,7 +35,6 @@ #include "nsIObserverService.h" #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" -#include "nsRadioInterfaceLayer.h" #include "WifiWorker.h" #include "mozilla/Services.h" diff --git a/dom/system/gonk/TetheringService.js b/dom/system/gonk/TetheringService.js index ee61efebdd..4ace5926d6 100644 --- a/dom/system/gonk/TetheringService.js +++ b/dom/system/gonk/TetheringService.js @@ -252,7 +252,7 @@ TetheringService.prototype = { this.handle(aSubject.key, aSubject.value); break; case TOPIC_CONNECTION_STATE_CHANGED: - network = aSubject.QueryInterface(Ci.nsINetworkInterface); + network = aSubject.QueryInterface(Ci.nsINetworkInfo); debug("Network " + network.type + "/" + network.name + " changed state to " + network.state); this.onConnectionChanged(network); @@ -360,18 +360,18 @@ TetheringService.prototype = { libcutils.property_get("ro.tethering.dun_required") === "1"; }, - getNetworkInterface: function(aType, aServiceId) { - for each (let network in gNetworkManager.networkInterfaces) { - if (network.type == aType) { + getNetworkInfo: function(aType, aServiceId) { + for each (let networkInfo in gNetworkManager.allNetworkInfo) { + if (networkInfo.type == aType) { try { - if (network instanceof Ci.nsIRilNetworkInterface) { - let rilNetwork = network.QueryInterface(Ci.nsIRilNetworkInterface); + if (networkInfo instanceof Ci.nsIRilNetworkInfo) { + let rilNetwork = networkInfo.QueryInterface(Ci.nsIRilNetworkInfo); if (rilNetwork.serviceId != aServiceId) { continue; } } } catch (e) {} - return network; + return networkInfo; } } return null; @@ -427,7 +427,7 @@ TetheringService.prototype = { let ril = gRil.getRadioInterface(this._dataDefaultServiceId); this.dunRetryTimes = 0; - ril.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN); + ril.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN); this.dunConnectTimer.cancel(); this.dunConnectTimer. initWithCallback(this.onDunConnectTimerTimeout.bind(this), @@ -452,8 +452,8 @@ TetheringService.prototype = { _dunActiveUsers: 0, handleDunConnection: function(aEnable, aCallback) { debug("handleDunConnection: " + aEnable); - let dun = this.getNetworkInterface( - Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId); + let dun = this.getNetworkInfo( + Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId); if (!aEnable) { this._dunActiveUsers--; @@ -467,15 +467,15 @@ TetheringService.prototype = { this.dunConnectTimer.cancel(); this._pendingTetheringRequests = []; - if (dun && (dun.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) { + if (dun && (dun.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) { gRil.getRadioInterface(this._dataDefaultServiceId) - .deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN); + .deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN); } return; } this._dunActiveUsers++; - if (!dun || (dun.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) { + if (!dun || (dun.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) { debug("DUN data call inactive, setup dun data call!") this._pendingTetheringRequests.push(aCallback); this.dunRetryTimes = 0; @@ -517,23 +517,24 @@ TetheringService.prototype = { this._usbTetheringAction = TETHERING_STATE_ONGOING; if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(true, (aNetwork) => { - if (!aNetwork){ + this.handleDunConnection(true, (aNetworkInfo) => { + if (!aNetworkInfo){ this.usbTetheringResultReport(aEnable, "Dun connection failed"); return; } - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = aNetwork.name; + this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = + aNetworkInfo.name; gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this)); }); return; } - if (gNetworkManager.active) { + if (gNetworkManager.activeNetworkInfo) { this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = - gNetworkManager.active.name; + gNetworkManager.activeNetworkInfo.name; } else { - let mobile = this.getNetworkInterface( - Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); + let mobile = this.getNetworkInfo( + Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); if (mobile && mobile.name) { this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name; } @@ -621,10 +622,10 @@ TetheringService.prototype = { }, // Enable/disable WiFi tethering by sending commands to netd. - setWifiTethering: function(aEnable, aNetwork, aConfig, aCallback) { + setWifiTethering: function(aEnable, aInterfaceName, aConfig, aCallback) { debug("setWifiTethering: " + aEnable); - if (!aNetwork) { - this.notifyError(true, aCallback, "invalid network information"); + if (!aInterfaceName) { + this.notifyError(true, aCallback, "invalid network interface name"); return; } @@ -648,22 +649,24 @@ TetheringService.prototype = { return; } - this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = aNetwork.name; + this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = + aInterfaceName; if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(true, (aNetwork) => { - if (!aNetwork) { + this.handleDunConnection(true, (aNetworkInfo) => { + if (!aNetworkInfo) { this.notifyError(true, aCallback, "Dun connection failed"); return; } - this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = aNetwork.name; + this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = + aNetworkInfo.name; this.enableWifiTethering(true, aConfig, aCallback); }); return; } - let mobile = this.getNetworkInterface( - Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); + let mobile = this.getNetworkInfo( + Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); // Update the real interface name if (mobile && mobile.name) { this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name; @@ -763,20 +766,20 @@ TetheringService.prototype = { } }, - onConnectionChanged: function(aNetwork) { - if (aNetwork.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) { + onConnectionChanged: function(aNetworkInfo) { + if (aNetworkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { debug("We are only interested in CONNECTED event"); return; } if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] && - aNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) { + aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) { this.dunConnectTimer.cancel(); debug("DUN data call connected, process callbacks."); while (this._pendingTetheringRequests.length > 0) { let callback = this._pendingTetheringRequests.shift(); if (typeof callback === 'function') { - callback(aNetwork); + callback(aNetworkInfo); } } return; @@ -788,15 +791,15 @@ TetheringService.prototype = { } if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] && - aNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN && + aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN && this._tetheringInterface[TETHERING_TYPE_USB].externalInterface === - aNetwork.name) { + aNetworkInfo.name) { debug("Dun required and dun interface is the same"); return; } if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface === - gNetworkManager.active.name) { + gNetworkManager.activeNetworkInfo.name) { debug("The active interface is the same"); return; } @@ -808,12 +811,12 @@ TetheringService.prototype = { let current = { internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface, - externalIfname: aNetwork.name + externalIfname: aNetworkInfo.name }; let callback = (() => { // Update external network interface. - debug("Update upstream interface to " + aNetwork.name); + debug("Update upstream interface to " + aNetworkInfo.name); gNetworkService.updateUpStream(previous, current, this.onConnectionChangedReport.bind(this)); }); diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build index ef447bbee7..2a5d8946ca 100644 --- a/dom/system/gonk/moz.build +++ b/dom/system/gonk/moz.build @@ -97,8 +97,6 @@ if CONFIG['MOZ_B2G_RIL']: EXTRA_COMPONENTS += [ 'DataCallManager.js', 'DataCallManager.manifest', - 'RILContentHelper.js', # TODO: Bug 815526, deprecate RILContentHelper. - 'RILContentHelper.manifest', # TODO: Bug 815526, deprecate RILContentHelper. 'RILSystemMessengerHelper.js', 'RILSystemMessengerHelper.manifest', ] diff --git a/dom/system/gonk/nsIRadioInterfaceLayer.idl b/dom/system/gonk/nsIRadioInterfaceLayer.idl index ae03c1341b..d30801429f 100644 --- a/dom/system/gonk/nsIRadioInterfaceLayer.idl +++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl @@ -35,6 +35,13 @@ interface nsIRadioInterface : nsISupports [optional] in nsIRilSendWorkerMessageCallback callback); }; +%{C++ +#define NS_RADIOINTERFACELAYER_CID \ + { 0x2d831c8d, 0x6017, 0x435b, \ + { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } } +#define NS_RADIOINTERFACELAYER_CONTRACTID "@mozilla.org/ril;1" +%} + [scriptable, uuid(78b65e8c-68e7-4510-9a05-65bba12b283e)] interface nsIRadioInterfaceLayer : nsISupports { diff --git a/dom/system/gonk/nsITetheringService.idl b/dom/system/gonk/nsITetheringService.idl index 7d8b6ac3a1..d9492b4493 100644 --- a/dom/system/gonk/nsITetheringService.idl +++ b/dom/system/gonk/nsITetheringService.idl @@ -7,7 +7,7 @@ interface nsINetworkInterface; interface nsIWifiTetheringCallback; -[scriptable, uuid(80d65940-bd99-458f-8529-e438c7348087)] +[scriptable, uuid(993b79df-f10e-4697-a5dc-5981cf8ff7e6)] interface nsITetheringService : nsISupports { /** @@ -16,15 +16,15 @@ interface nsITetheringService : nsISupports * @param enabled * Boolean that indicates whether tethering should be enabled (true) or * disabled (false). - * @param networkInterface - * The Wifi network interface with at least name of network interface. + * @param interfaceName + * The Wifi network interface name for internal interface. * @param config * The Wifi Tethering configuration from settings db. * @param callback * Callback function used to report status to WifiManager. */ void setWifiTethering(in boolean enabled, - in nsINetworkInterface networkInterface, + in DOMString interfaceName, in jsval config, in nsIWifiTetheringCallback callback); }; \ No newline at end of file diff --git a/dom/system/gonk/nsRadioInterfaceLayer.h b/dom/system/gonk/nsRadioInterfaceLayer.h deleted file mode 100644 index a623a18825..0000000000 --- a/dom/system/gonk/nsRadioInterfaceLayer.h +++ /dev/null @@ -1,16 +0,0 @@ -/* 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/. */ - -// These must always match the values given in RadioInterfaceLayer.manifest! - -#define NS_RADIOINTERFACELAYER_CID \ - { 0x2d831c8d, 0x6017, 0x435b, \ - { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } } - -#define NS_RILCONTENTHELPER_CID \ - { 0x472816e1, 0x1fd6, 0x4405, \ - { 0x99, 0x6c, 0x80, 0x6f, 0x9e, 0xa6, 0x81, 0x74 } } - -#define NS_RADIOINTERFACELAYER_CONTRACTID "@mozilla.org/ril;1" -#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1" diff --git a/dom/system/gonk/tests/marionette/test_ril_code_quality.py b/dom/system/gonk/tests/marionette/test_ril_code_quality.py index 1002b99486..b58f9216db 100644 --- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py +++ b/dom/system/gonk/tests/marionette/test_ril_code_quality.py @@ -2,7 +2,6 @@ The test performs the static code analysis check by JSHint. Target js files: -- RILContentHelper.js TODO: Bug 815526, deprecate RILContentHelper. - RadioInterfaceLayer.js - ril_worker.js - ril_consts.js @@ -100,7 +99,6 @@ class ResourceUriFileReader: URI_PREFIX = 'resource://gre/' URI_PATH = { - 'RILContentHelper.js': 'components/RILContentHelper.js', #TODO: Bug 815526, deprecate RILContentHelper. 'RadioInterfaceLayer.js': 'components/RadioInterfaceLayer.js', 'ril_worker.js': 'modules/ril_worker.js', 'ril_consts.js': 'modules/ril_consts.js', @@ -354,10 +352,6 @@ class TestRILCodeQuality(MarionetteTestCase): def tearDown(self): MarionetteTestCase.tearDown(self) - # TODO: Bug 815526, deprecate RILContentHelper. - def test_RILContentHelper(self): - self._check('RILContentHelper.js') - def test_RadioInterfaceLayer(self): self._check('RadioInterfaceLayer.js') diff --git a/dom/system/gonk/tests/test_ril_system_messenger.js b/dom/system/gonk/tests/test_ril_system_messenger.js index aa7769c8b0..0336febb3f 100644 --- a/dom/system/gonk/tests/test_ril_system_messenger.js +++ b/dom/system/gonk/tests/test_ril_system_messenger.js @@ -8,11 +8,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); let RIL = {}; Cu.import("resource://gre/modules/ril_consts.js", RIL); -XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() { - let stk = {}; - Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk); - return stk.StkProactiveCmdFactory; -}); +XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory", + "@mozilla.org/icc/stkcmdfactory;1", + "nsIStkCmdFactory"); /** * Name space for RILSystemMessenger.jsm. Only initialized after first call to @@ -40,6 +38,10 @@ function newRILSystemMessenger() { gReceivedMessage = aMessage; }; + rsm.createCommandMessage = (aStkProactiveCmd) => { + return gStkCmdFactory.createCommandMessage(aStkProactiveCmd); + }; + return rsm; } @@ -541,7 +543,8 @@ add_test(function test_icc_stk_cmd_factory_create_command_error() { ok(false, "Failed to verify the protection of createCommand()!"); } catch (e) { - equal(e.message, "Unknown Command Type: " + RIL.STK_CMD_MORE_TIME); + ok(e.message.indexOf("Unknown Command Type") !== -1, + "Invalid typeOfCommand!"); } run_next_test(); @@ -567,7 +570,8 @@ add_test(function test_icc_stk_cmd_factory_create_system_msg_invalid_cmd_type() ok(false, "Failed to identify invalid typeOfCommand!"); } catch (e) { - equal(e.message, "Unknown Command Type: " + RIL.STK_CMD_MORE_TIME); + ok(e.message.indexOf("Unknown Command Type") !== -1, + "Invalid typeOfCommand!"); } run_next_test(); diff --git a/dom/webidl/MozIcc.webidl b/dom/webidl/MozIcc.webidl index f068b3dd2e..371c1c7a64 100644 --- a/dom/webidl/MozIcc.webidl +++ b/dom/webidl/MozIcc.webidl @@ -333,7 +333,7 @@ interface MozIcc : EventTarget */ [Throws] DOMRequest updateContact(IccContactType contactType, - any contact, + mozContact contact, optional DOMString? pin2 = null); // Integrated Circuit Card Helpers. diff --git a/dom/webidl/MozStkCommandEvent.webidl b/dom/webidl/MozStkCommandEvent.webidl index 21a2123ba6..0f144276b1 100644 --- a/dom/webidl/MozStkCommandEvent.webidl +++ b/dom/webidl/MozStkCommandEvent.webidl @@ -342,12 +342,12 @@ dictionary MozStkLocationInfo /** * Mobile Country Code (MCC) of the current serving operator. */ - unsigned short mcc; + DOMString mcc; /** * Mobile Network Code (MNC) of the current serving operator. */ - unsigned short mnc; + DOMString mnc; /** * Mobile Location Area Code (LAC) for the current serving operator. diff --git a/dom/wifi/WifiNetUtil.jsm b/dom/wifi/WifiNetUtil.jsm index 2d80de6b43..2a18665150 100644 --- a/dom/wifi/WifiNetUtil.jsm +++ b/dom/wifi/WifiNetUtil.jsm @@ -30,9 +30,13 @@ this.WifiNetUtil = function(controlMessage) { var util = {}; - util.runDhcp = function (ifname, callback) { - gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) { - util.runIpConfig(ifname, dhcpInfo, callback); + util.runDhcp = function (ifname, gen, callback) { + util.stopDhcp(ifname, function() { + gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) { + util.runIpConfig(ifname, dhcpInfo, function(data) { + callback(data, gen); + }); + }); }); }; @@ -44,7 +48,16 @@ this.WifiNetUtil = function(controlMessage) { let dhcpService = DHCP_PROP + "_" + ifname; let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname; let processName = DHCP + "_" + suffix; - stopProcess(dhcpService, processName, callback); + + // The implementation of |dhcp_do_request| would wait until the + // |result_prop_name| (e.g. dhcp.wlan0.result) to be non-null + // or 30 second timeout. So we manually change the result property + // to 'ko' to avoid timeout. + // + // http://androidxref.com/4.4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#234 + setProperty('dhcp.' + suffix + '.result', 'ko', function() { + stopProcess(dhcpService, processName, callback); + }); }; util.startDhcpServer = function (config, callback) { diff --git a/dom/wifi/WifiP2pManager.jsm b/dom/wifi/WifiP2pManager.jsm index 90be2d8582..de6fc25edc 100644 --- a/dom/wifi/WifiP2pManager.jsm +++ b/dom/wifi/WifiP2pManager.jsm @@ -490,39 +490,44 @@ function P2pStateMachine(aP2pCommand, aNetUtil) { let _p2pNetworkInterface = { QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]), - state: Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED, - type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI_P2P, - name: P2P_INTERFACE_NAME, - ips: [], - prefixLengths: [], - dnses: [], - gateways: [], + info: { + QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]), + + state: Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED, + type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI_P2P, + name: P2P_INTERFACE_NAME, + ips: [], + prefixLengths: [], + dnses: [], + gateways: [], + + getAddresses: function (ips, prefixLengths) { + ips.value = this.ips.slice(); + prefixLengths.value = this.prefixLengths.slice(); + + return this.ips.length; + }, + + getGateways: function (count) { + if (count) { + count.value = this.gateways.length; + } + return this.gateways.slice(); + }, + + getDnses: function (count) { + if (count) { + count.value = this.dnses.length; + } + return this.dnses.slice(); + } + }, + httpProxyHost: null, httpProxyPort: null, // help - registered: false, - - getAddresses: function (ips, prefixLengths) { - ips.value = this.ips.slice(); - prefixLengths.value = this.prefixLengths.slice(); - - return this.ips.length; - }, - - getGateways: function (count) { - if (count) { - count.value = this.gateways.length; - } - return this.gateways.slice(); - }, - - getDnses: function (count) { - if (count) { - count.value = this.dnses.length; - } - return this.dnses.slice(); - } + registered: false }; //--------------------------------------------------------- @@ -1419,10 +1424,10 @@ function P2pStateMachine(aP2pCommand, aNetUtil) { } // Update p2p network interface. - _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED; - _p2pNetworkInterface.ips = [GO_NETWORK_INTERFACE.ip]; - _p2pNetworkInterface.prefixLengths = [GO_NETWORK_INTERFACE.maskLength]; - _p2pNetworkInterface.gateways = [GO_NETWORK_INTERFACE.ip]; + _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED; + _p2pNetworkInterface.info.ips = [GO_NETWORK_INTERFACE.ip]; + _p2pNetworkInterface.info.prefixLengths = [GO_NETWORK_INTERFACE.maskLength]; + _p2pNetworkInterface.info.gateways = [GO_NETWORK_INTERFACE.ip]; handleP2pNetworkInterfaceStateChanged(); _groupInfo.networkInterface = _p2pNetworkInterface; @@ -1454,18 +1459,18 @@ function P2pStateMachine(aP2pCommand, aNetUtil) { if (!maskLength) { maskLength = 32; // max prefix for IPv4. } - _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED; - _p2pNetworkInterface.ips = [dhcpData.info.ipaddr_str]; - _p2pNetworkInterface.prefixLengths = [maskLength]; + _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED; + _p2pNetworkInterface.info.ips = [dhcpData.info.ipaddr_str]; + _p2pNetworkInterface.info.prefixLengths = [maskLength]; if (typeof dhcpData.info.dns1_str == "string" && dhcpData.info.dns1_str.length) { - _p2pNetworkInterface.dnses.push(dhcpData.info.dns1_str); + _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns1_str); } if (typeof dhcpData.info.dns2_str == "string" && dhcpData.info.dns2_str.length) { - _p2pNetworkInterface.dnses.push(dhcpData.info.dns2_str); + _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns2_str); } - _p2pNetworkInterface.gateways = [dhcpData.info.gateway_str]; + _p2pNetworkInterface.info.gateways = [dhcpData.info.gateway_str]; handleP2pNetworkInterfaceStateChanged(); _groupInfo.networkInterface = _p2pNetworkInterface; @@ -1476,11 +1481,11 @@ function P2pStateMachine(aP2pCommand, aNetUtil) { } function resetP2pNetworkInterface() { - _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED; - _p2pNetworkInterface.ips = []; - _p2pNetworkInterface.prefixLengths = []; - _p2pNetworkInterface.dnses = []; - _p2pNetworkInterface.gateways = []; + _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED; + _p2pNetworkInterface.info.ips = []; + _p2pNetworkInterface.info.prefixLengths = []; + _p2pNetworkInterface.info.dnses = []; + _p2pNetworkInterface.info.gateways = []; } function registerP2pNetworkInteface() { @@ -1523,7 +1528,7 @@ function P2pStateMachine(aP2pCommand, aNetUtil) { } // Update p2p network interface. - _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED; + _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED; handleP2pNetworkInterfaceStateChanged(); if (P2P_ROLE_GO === aInfo.role) { diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index 7d775e0cd1..7df032a5ab 100755 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -403,8 +403,8 @@ var WifiManager = (function() { WifiNetworkInterface.httpProxyHost = network.httpProxyHost; WifiNetworkInterface.httpProxyPort = network.httpProxyPort; - if (WifiNetworkInterface.state == - Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) { + if (WifiNetworkInterface.info.state == + Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { gNetworkManager.updateNetworkInterface(WifiNetworkInterface); } } @@ -633,6 +633,8 @@ var WifiManager = (function() { wifiCommand.connectToSupplicant(connectCallback); } + let dhcpRequestGen = 0; + function onconnected() { // For now we do our own DHCP. In the future, this should be handed // off to the Network Manager. @@ -648,9 +650,14 @@ var WifiManager = (function() { runStaticIp(manager.ifname, key); return; } - netUtil.runDhcp(manager.ifname, function(data) { + netUtil.runDhcp(manager.ifname, dhcpRequestGen++, function(data, gen) { dhcpInfo = data.info; + debug('dhcpRequestGen: ' + dhcpRequestGen + ', gen: ' + gen); if (!dhcpInfo) { + if (gen + 1 < dhcpRequestGen) { + debug('Do not bother younger DHCP request.'); + return; + } if (++manager.dhcpFailuresCount >= MAX_RETRIES_ON_DHCP_FAILURE) { manager.dhcpFailuresCount = 0; notify("disconnected", {connectionInfo: manager.connectionInfo}); @@ -993,16 +1000,17 @@ var WifiManager = (function() { if (enabled) { manager.state = "INITIALIZING"; // Register as network interface. - WifiNetworkInterface.name = manager.ifname; + WifiNetworkInterface.info.name = manager.ifname; if (!WifiNetworkInterface.registered) { gNetworkManager.registerNetworkInterface(WifiNetworkInterface); WifiNetworkInterface.registered = true; } - WifiNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED; - WifiNetworkInterface.ips = []; - WifiNetworkInterface.prefixLengths = []; - WifiNetworkInterface.gateways = []; - WifiNetworkInterface.dnses = []; + WifiNetworkInterface.info.state = + Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED; + WifiNetworkInterface.info.ips = []; + WifiNetworkInterface.info.prefixLengths = []; + WifiNetworkInterface.info.gateways = []; + WifiNetworkInterface.info.dnses = []; gNetworkManager.updateNetworkInterface(WifiNetworkInterface); prepareForStartup(function() { @@ -1147,8 +1155,10 @@ var WifiManager = (function() { function doStartWifiTethering() { cancelWaitForDriverReadyTimer(); - WifiNetworkInterface.name = libcutils.property_get("wifi.tethering.interface", manager.ifname); - gTetheringService.setWifiTethering(enabled, WifiNetworkInterface, + WifiNetworkInterface.info.name = + libcutils.property_get("wifi.tethering.interface", manager.ifname); + gTetheringService.setWifiTethering(enabled, + WifiNetworkInterface.info.name, configuration, function(result) { if (result) { manager.tetheringState = "UNINITIALIZED"; @@ -1762,55 +1772,59 @@ let WifiNetworkInterface = { // nsINetworkInterface - NETWORK_STATE_UNKNOWN: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN, - NETWORK_STATE_CONNECTING: Ci.nsINetworkInterface.CONNECTING, - NETWORK_STATE_CONNECTED: Ci.nsINetworkInterface.CONNECTED, - NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInterface.DISCONNECTING, - NETWORK_STATE_DISCONNECTED: Ci.nsINetworkInterface.DISCONNECTED, + NETWORK_STATE_UNKNOWN: Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN, + NETWORK_STATE_CONNECTING: Ci.nsINetworkInfo.CONNECTING, + NETWORK_STATE_CONNECTED: Ci.nsINetworkInfo.CONNECTED, + NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInfo.DISCONNECTING, + NETWORK_STATE_DISCONNECTED: Ci.nsINetworkInfo.DISCONNECTED, - state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN, + NETWORK_TYPE_WIFI: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, + NETWORK_TYPE_MOBILE: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, + NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS, + NETWORK_TYPE_MOBILE_SUPL: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL, - NETWORK_TYPE_WIFI: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, - NETWORK_TYPE_MOBILE: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, - NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS, - NETWORK_TYPE_MOBILE_SUPL: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL, + info: { + QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]), - type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, + state: Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN, - name: null, + type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, - ips: [], + name: null, - prefixLengths: [], + ips: [], - dnses: [], + prefixLengths: [], - gateways: [], + dnses: [], + + gateways: [], + + getAddresses: function (ips, prefixLengths) { + ips.value = this.ips.slice(); + prefixLengths.value = this.prefixLengths.slice(); + + return this.ips.length; + }, + + getGateways: function (count) { + if (count) { + count.value = this.gateways.length; + } + return this.gateways.slice(); + }, + + getDnses: function (count) { + if (count) { + count.value = this.dnses.length; + } + return this.dnses.slice(); + } + }, httpProxyHost: null, - httpProxyPort: null, - - getAddresses: function (ips, prefixLengths) { - ips.value = this.ips.slice(); - prefixLengths.value = this.prefixLengths.slice(); - - return this.ips.length; - }, - - getGateways: function (count) { - if (count) { - count.value = this.gateways.length; - } - return this.gateways.slice(); - }, - - getDnses: function (count) { - if (count) { - count.value = this.dnses.length; - } - return this.dnses.slice(); - } + httpProxyPort: null }; function WifiScanResult() {} @@ -2228,8 +2242,8 @@ function WifiWorker() { case "DISCONNECTED": // wpa_supplicant may give us a "DISCONNECTED" event even if // we are already in "DISCONNECTED" state. - if ((WifiNetworkInterface.state === - Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED) && + if ((WifiNetworkInterface.info.state === + Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) && (this.prevState === "INITIALIZING" || this.prevState === "DISCONNECTED" || this.prevState === "INTERFACE_DISABLED" || @@ -2261,13 +2275,16 @@ function WifiWorker() { } }); - WifiNetworkInterface.state = - Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED; - WifiNetworkInterface.ips = []; - WifiNetworkInterface.prefixLengths = []; - WifiNetworkInterface.gateways = []; - WifiNetworkInterface.dnses = []; + WifiNetworkInterface.info.state = + Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED; + + // Update network infterface first then clear properties. gNetworkManager.updateNetworkInterface(WifiNetworkInterface); + WifiNetworkInterface.info.ips = []; + WifiNetworkInterface.info.prefixLengths = []; + WifiNetworkInterface.info.gateways = []; + WifiNetworkInterface.info.dnses = []; + break; case "WPS_TIMEOUT": @@ -2309,18 +2326,18 @@ function WifiWorker() { WifiNetworkInterface.httpProxyPort = netConnect.httpProxyPort; } - WifiNetworkInterface.state = - Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED; - WifiNetworkInterface.ips = [this.info.ipaddr_str]; - WifiNetworkInterface.prefixLengths = [maskLength]; - WifiNetworkInterface.gateways = [this.info.gateway_str]; + WifiNetworkInterface.info.state = + Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED; + WifiNetworkInterface.info.ips = [this.info.ipaddr_str]; + WifiNetworkInterface.info.prefixLengths = [maskLength]; + WifiNetworkInterface.info.gateways = [this.info.gateway_str]; if (typeof this.info.dns1_str == "string" && this.info.dns1_str.length) { - WifiNetworkInterface.dnses.push(this.info.dns1_str); + WifiNetworkInterface.info.dnses.push(this.info.dns1_str); } if (typeof this.info.dns2_str == "string" && this.info.dns2_str.length) { - WifiNetworkInterface.dnses.push(this.info.dns2_str); + WifiNetworkInterface.info.dnses.push(this.info.dns2_str); } gNetworkManager.updateNetworkInterface(WifiNetworkInterface); diff --git a/toolkit/devtools/discovery/discovery.js b/toolkit/devtools/discovery/discovery.js index 851af05227..546b94d9d6 100644 --- a/toolkit/devtools/discovery/discovery.js +++ b/toolkit/devtools/discovery/discovery.js @@ -381,16 +381,16 @@ Discovery.prototype = { if (topic !== "network-active-changed") { return; } - let activeNetwork = subject; - if (!activeNetwork) { - log("No active network"); + let activeNetworkInfo = subject; + if (!activeNetworkInfo) { + log("No active network info"); return; } - activeNetwork = activeNetwork.QueryInterface(Ci.nsINetworkInterface); - log("Active network changed to: " + activeNetwork.type); + activeNetworkInfo = activeNetworkInfo.QueryInterface(Ci.nsINetworkInfo); + log("Active network changed to: " + activeNetworkInfo.type); // UDP sockets go down when the device goes offline, so we'll restart them // when the active network goes back to WiFi. - if (activeNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) { + if (activeNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) { this._restartListening(); } },