Bug 814637 - Part 3: DOM changes for IccManager support multiple sim. f=hsinyi. r=smaug

This commit is contained in:
Edgar Chen 2013-10-09 17:40:12 +08:00
parent fab68d299c
commit 32a51f2f8c
10 changed files with 830 additions and 287 deletions

View File

@ -719,7 +719,9 @@ GK_ATOM(onheld, "onheld")
GK_ATOM(onhfpstatuschanged, "onhfpstatuschanged")
GK_ATOM(onholding, "onholding")
GK_ATOM(oniccchange, "oniccchange")
GK_ATOM(oniccdetected, "oniccdetected")
GK_ATOM(oniccinfochange, "oniccinfochange")
GK_ATOM(oniccundetected, "oniccundetected")
GK_ATOM(onincoming, "onincoming")
GK_ATOM(oninput, "oninput")
GK_ATOM(oninvalid, "oninvalid")

View File

@ -1236,8 +1236,7 @@ Navigator::GetMozIccManager(ErrorResult& aRv)
}
NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
mIccManager = new IccManager();
mIccManager->Init(mWindow);
mIccManager = new IccManager(mWindow);
}
return mIccManager;

View File

@ -789,6 +789,10 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::CellBroadcast',
},
'MozIcc': {
'nativeType': 'mozilla::dom::Icc',
},
'MozMobileConnectionArray': {
'nativeType': 'mozilla::dom::network::MobileConnectionArray',
'resultNotAddRefed': [ 'item' ]

358
dom/icc/src/Icc.cpp Normal file
View File

@ -0,0 +1,358 @@
/* 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 "Icc.h"
#include "mozilla/dom/MozIccBinding.h"
#include "mozilla/dom/MozStkCommandEvent.h"
#include "nsIDOMDOMRequest.h"
#include "nsIDOMIccInfo.h"
#include "nsJSON.h"
#include "nsRadioInterfaceLayer.h"
#include "nsServiceManagerUtils.h"
using namespace mozilla::dom;
Icc::Icc(nsPIDOMWindow* aWindow, long aClientId, const nsAString& aIccId)
: mLive(true)
, mClientId(aClientId)
, mIccId(aIccId)
{
SetIsDOMBinding();
BindToOwner(aWindow);
mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
// 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!");
}
}
void
Icc::Shutdown()
{
mProvider = nullptr;
mLive = false;
}
nsresult
Icc::NotifyEvent(const nsAString& aName)
{
return DispatchTrustedEvent(aName);
}
nsresult
Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage)
{
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
AutoPushJSContext cx(sc->GetNativeContext());
JS::Rooted<JS::Value> value(cx);
if (!aMessage.IsEmpty()) {
nsCOMPtr<nsIJSON> json(new nsJSON());
nsresult rv = json->DecodeToJSVal(aMessage, cx, value.address());
NS_ENSURE_SUCCESS(rv, rv);
} else {
value = JS::NullValue();
}
MozStkCommandEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mCommand = value;
nsRefPtr<MozStkCommandEvent> event =
MozStkCommandEvent::Constructor(this, aName, init);
return DispatchTrustedEvent(event);
}
// WrapperCache
JSObject*
Icc::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return MozIccBinding::Wrap(aCx, aScope, this);
}
// MozIcc WebIDL
already_AddRefed<nsIDOMMozIccInfo>
Icc::GetIccInfo() const
{
if (!mProvider) {
return nullptr;
}
nsCOMPtr<nsIDOMMozIccInfo> iccInfo;
nsresult rv = mProvider->GetIccInfo(mClientId, getter_AddRefs(iccInfo));
if (NS_FAILED(rv)) {
return nullptr;
}
return iccInfo.forget();
}
void
Icc::GetCardState(nsString& aCardState) const
{
aCardState.SetIsVoid(true);
if (!mProvider) {
return;
}
nsresult rv = mProvider->GetCardState(mClientId, aCardState);
if (NS_FAILED(rv)) {
aCardState.SetIsVoid(true);
}
}
void
Icc::SendStkResponse(const JSContext* aCx, const JS::Value& aCommand,
const JS::Value& aResponse, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsresult rv = mProvider->SendStkResponse(mClientId, GetOwner(), aCommand,
aResponse);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
Icc::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsresult rv = mProvider->SendStkMenuSelection(mClientId,
GetOwner(),
aItemIdentifier,
aHelpRequested);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
Icc::SendStkTimerExpiration(const JSContext* aCx, const JS::Value& aTimer,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsresult rv = mProvider->SendStkTimerExpiration(mClientId, GetOwner(),
aTimer);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
Icc::SendStkEventDownload(const JSContext* aCx, const JS::Value& aEvent,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsresult rv = mProvider->SendStkEventDownload(mClientId, GetOwner(), aEvent);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
already_AddRefed<nsISupports>
Icc::GetCardLock(const nsAString& aLockType, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->GetCardLockState(mClientId, GetOwner(), aLockType,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::UnlockCardLock(const JSContext* aCx, const JS::Value& aInfo,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->UnlockCardLock(mClientId, GetOwner(), aInfo,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::SetCardLock(const JSContext* aCx, const JS::Value& aInfo, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->SetCardLock(mClientId, GetOwner(), aInfo,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::GetCardLockRetryCount(const nsAString& aLockType, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->GetCardLockRetryCount(mClientId,
GetOwner(),
aLockType,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::ReadContacts(const nsAString& aContactType, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->ReadContacts(mClientId, GetOwner(), aContactType,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::UpdateContact(const JSContext* aCx, const nsAString& aContactType,
const JS::Value& aContact, const nsAString& aPin2,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->UpdateContact(mClientId, GetOwner(), aContactType,
aContact, aPin2,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::IccOpenChannel(const nsAString& aAid, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->IccOpenChannel(mClientId, GetOwner(), aAid,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::IccExchangeAPDU(const JSContext* aCx, int32_t aChannel, const jsval& aApdu,
ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->IccExchangeAPDU(mClientId, GetOwner(), aChannel,
aApdu, getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}
already_AddRefed<nsISupports>
Icc::IccCloseChannel(int32_t aChannel, ErrorResult& aRv)
{
if (!mProvider) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->IccCloseChannel(mClientId, GetOwner(), aChannel,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return request.forget();
}

117
dom/icc/src/Icc.h Normal file
View File

@ -0,0 +1,117 @@
/* 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_h
#define mozilla_dom_Icc_h
#include "nsDOMEventTargetHelper.h"
#include "nsIIccProvider.h"
namespace mozilla {
namespace dom {
class Icc MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
Icc(nsPIDOMWindow* aWindow, long aClientId, const nsAString& aIccId);
void
Shutdown();
nsresult
NotifyEvent(const nsAString& aName);
nsresult
NotifyStkEvent(const nsAString& aName, const nsAString& aMessage);
nsString
GetIccId()
{
return mIccId;
}
nsPIDOMWindow*
GetParentObject() const
{
return GetOwner();
}
// WrapperCache
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// MozIcc WebIDL
already_AddRefed<nsIDOMMozIccInfo>
GetIccInfo() const;
void
GetCardState(nsString& aCardState) const;
void
SendStkResponse(const JSContext* aCx, const JS::Value& aCommand,
const JS::Value& aResponse, ErrorResult& aRv);
void
SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested,
ErrorResult& aRv);
void
SendStkTimerExpiration(const JSContext* aCx, const JS::Value& aTimer,
ErrorResult& aRv);
void
SendStkEventDownload(const JSContext* aCx, const JS::Value& aEvent,
ErrorResult& aRv);
already_AddRefed<nsISupports>
GetCardLock(const nsAString& aLockType, ErrorResult& aRv);
already_AddRefed<nsISupports>
UnlockCardLock(const JSContext* aCx, const JS::Value& aInfo,
ErrorResult& aRv);
already_AddRefed<nsISupports>
SetCardLock(const JSContext* aCx, const JS::Value& aInfo, ErrorResult& aRv);
already_AddRefed<nsISupports>
GetCardLockRetryCount(const nsAString& aLockType, ErrorResult& aRv);
already_AddRefed<nsISupports>
ReadContacts(const nsAString& aContactType, ErrorResult& aRv);
already_AddRefed<nsISupports>
UpdateContact(const JSContext* aCx, const nsAString& aContactType,
const JS::Value& aContact, const nsAString& aPin2,
ErrorResult& aRv);
already_AddRefed<nsISupports>
IccOpenChannel(const nsAString& aAid, ErrorResult& aRv);
already_AddRefed<nsISupports>
IccExchangeAPDU(const JSContext* aCx, int32_t aChannel, const jsval& aApdu,
ErrorResult& aRv);
already_AddRefed<nsISupports>
IccCloseChannel(int32_t aChannel, ErrorResult& aRv);
IMPL_EVENT_HANDLER(iccinfochange)
IMPL_EVENT_HANDLER(cardstatechange)
IMPL_EVENT_HANDLER(stkcommand)
IMPL_EVENT_HANDLER(stksessionend)
private:
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<nsIIccProvider> mProvider;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_icc_Icc_h

130
dom/icc/src/IccListener.cpp Normal file
View File

@ -0,0 +1,130 @@
/* 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 "IccListener.h"
#include "Icc.h"
#include "IccManager.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMIccInfo.h"
#include "nsRadioInterfaceLayer.h"
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS1(IccListener, nsIIccListener)
IccListener::IccListener(IccManager* aIccManager, uint32_t aClientId)
: mClientId(aClientId)
, mIccManager(aIccManager)
{
MOZ_ASSERT(mIccManager);
mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
if (!mProvider) {
NS_WARNING("Could not acquire nsIIccProvider!");
return;
}
nsCOMPtr<nsIDOMMozIccInfo> iccInfo;
mProvider->GetIccInfo(mClientId, getter_AddRefs(iccInfo));
if (iccInfo) {
nsString iccId;
iccInfo->GetIccid(iccId);
if (!iccId.IsEmpty()) {
mIcc = new Icc(mIccManager->GetOwner(), mClientId, iccId);
}
}
DebugOnly<nsresult> rv = mProvider->RegisterIccMsg(mClientId, this);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Failed registering icc messages with provider");
}
IccListener::~IccListener()
{
Shutdown();
}
void
IccListener::Shutdown()
{
if (mProvider) {
mProvider->UnregisterIccMsg(mClientId, this);
mProvider = nullptr;
}
if (mIcc) {
mIcc->Shutdown();
mIcc = nullptr;
}
mIccManager = nullptr;
}
// nsIIccListener
NS_IMETHODIMP
IccListener::NotifyStkCommand(const nsAString& aMessage)
{
if (!mIcc) {
return NS_OK;
}
return mIcc->NotifyStkEvent(NS_LITERAL_STRING("stkcommand"), aMessage);
}
NS_IMETHODIMP
IccListener::NotifyStkSessionEnd()
{
if (!mIcc) {
return NS_OK;
}
return mIcc->NotifyEvent(NS_LITERAL_STRING("stksessionend"));
}
NS_IMETHODIMP
IccListener::NotifyCardStateChanged()
{
if (!mIcc) {
return NS_OK;
}
return mIcc->NotifyEvent(NS_LITERAL_STRING("cardstatechange"));
}
NS_IMETHODIMP
IccListener::NotifyIccInfoChanged()
{
nsCOMPtr<nsIDOMMozIccInfo> iccInfo;
mProvider->GetIccInfo(mClientId, getter_AddRefs(iccInfo));
// Create/delete icc object based on current iccInfo.
// 1. If the mIcc is nullptr and iccInfo has valid data, create icc object and
// notify mIccManager a new icc is added.
// 2. If the mIcc is not nullptr and iccInfo becomes to null, delete existed
// icc object and notify mIccManager the icc is removed.
if (!mIcc) {
if (iccInfo) {
nsString iccId;
iccInfo->GetIccid(iccId);
if (!iccId.IsEmpty()) {
mIcc = new Icc(mIccManager->GetOwner(), mClientId, iccId);
mIccManager->NotifyIccAdd(iccId);
mIcc->NotifyEvent(NS_LITERAL_STRING("iccinfochange"));
}
}
} else {
mIcc->NotifyEvent(NS_LITERAL_STRING("iccinfochange"));
if (!iccInfo) {
nsString iccId = mIcc->GetIccId();
mIcc->Shutdown();
mIcc = nullptr;
mIccManager->NotifyIccRemove(iccId);
}
}
return NS_OK;
}

52
dom/icc/src/IccListener.h Normal file
View File

@ -0,0 +1,52 @@
/* 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_IccListener_h
#define mozilla_dom_IccListener_h
#include "nsAutoPtr.h"
#include "nsIIccProvider.h"
namespace mozilla {
namespace dom {
class IccManager;
class Icc;
class IccListener : public nsIIccListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIICCLISTENER
IccListener(IccManager* aIccManager, uint32_t aClientId);
~IccListener();
void
Shutdown();
already_AddRefed<Icc>
GetIcc()
{
nsRefPtr<Icc> icc = mIcc;
return icc.forget();
}
private:
uint32_t mClientId;
// We did not setup 'mIcc' and 'mIccManager' being a participant of cycle
// collection is because in Navigator->Invalidate() it will call
// mIccManager->Shutdown(), then IccManager will call Shutdown() of each
// IccListener, this will release the reference and break the cycle.
nsRefPtr<Icc> mIcc;
nsRefPtr<IccManager> mIccManager;
// mProvider is a xpcom service and will be released at shutdown, so it
// doesn't need to be cycle collected.
nsCOMPtr<nsIIccProvider> mProvider;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_IccListener_h

View File

@ -2,47 +2,42 @@
* 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/IccManager.h"
#include "IccManager.h"
#include "GeneratedEvents.h"
#include "mozilla/dom/MozStkCommandEvent.h"
#include "Icc.h"
#include "IccListener.h"
#include "mozilla/dom/IccChangeEvent.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMIccInfo.h"
#include "nsJSON.h"
#include "SimToolKit.h"
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
using namespace mozilla::dom;
class IccManager::Listener : public nsIIccListener
{
IccManager* mIccManager;
public:
NS_DECL_ISUPPORTS
NS_FORWARD_SAFE_NSIICCLISTENER(mIccManager)
Listener(IccManager* aIccManager)
: mIccManager(aIccManager)
{
MOZ_ASSERT(mIccManager);
}
void
Disconnect()
{
MOZ_ASSERT(mIccManager);
mIccManager = nullptr;
}
};
NS_IMPL_ISUPPORTS1(IccManager::Listener, nsIIccListener)
DOMCI_DATA(MozIccManager, IccManager)
NS_INTERFACE_MAP_BEGIN(IccManager)
NS_IMPL_CYCLE_COLLECTION_CLASS(IccManager)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IccManager,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsIccIds)
// We did not setup 'mIccListeners' being a participant of cycle collection is
// because in Navigator->Invalidate() it will call mIccManager->Shutdown(),
// then IccManager will call Shutdown() of each IccListener, this will release
// the reference that held by each mIccListener and break the cycle.
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IccManager,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IccManager,
nsDOMEventTargetHelper)
tmp->Unroot();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IccManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozIccManager)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozIccManager)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
@ -50,261 +45,134 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IccManager, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IccManager, nsDOMEventTargetHelper)
IccManager::IccManager()
{
mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
// 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!");
return;
}
// TODO: Bug 814637 - WebIccManager API: support multiple sim cards
// In Multi-sim, there is more than one client in iccProvider. Each client
// represents a icc service. To maintain the backward compatibility with
// single sim, we always use client 0 for now. Adding support for multiple sim
// will be addressed in bug 814637.
mClientId = 0;
mListener = new Listener(this);
DebugOnly<nsresult> rv = mProvider->RegisterIccMsg(mClientId, mListener);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Failed registering icc messages with provider");
}
void
IccManager::Init(nsPIDOMWindow* aWindow)
IccManager::IccManager(nsPIDOMWindow* aWindow)
: mJsIccIds(nullptr)
, mRooted(false)
{
BindToOwner(aWindow);
uint32_t numberOfServices =
mozilla::Preferences::GetUint("ril.numRadioInterfaces", 1);
for (uint32_t i = 0; i < numberOfServices; i++) {
nsRefPtr<IccListener> iccListener = new IccListener(this, i);
mIccListeners.AppendElement(iccListener);
}
}
IccManager::~IccManager()
{
Shutdown();
Unroot();
}
void
IccManager::Shutdown()
{
if (mProvider && mListener) {
mListener->Disconnect();
mProvider->UnregisterIccMsg(mClientId, mListener);
mProvider = nullptr;
mListener = nullptr;
for (uint32_t i = 0; i < mIccListeners.Length(); i++) {
mIccListeners[i]->Shutdown();
mIccListeners[i] = nullptr;
}
mIccListeners.Clear();
}
nsresult
IccManager::NotifyIccAdd(const nsAString& aIccId)
{
mJsIccIds = nullptr;
IccChangeEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mIccId = aIccId;
nsRefPtr<IccChangeEvent> event =
IccChangeEvent::Constructor(this, NS_LITERAL_STRING("iccdetected"), init);
return DispatchTrustedEvent(event);
}
nsresult
IccManager::NotifyIccRemove(const nsAString& aIccId)
{
mJsIccIds = nullptr;
IccChangeEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mIccId = aIccId;
nsRefPtr<IccChangeEvent> event =
IccChangeEvent::Constructor(this, NS_LITERAL_STRING("iccundetected"), init);
return DispatchTrustedEvent(event);
}
void
IccManager::Root()
{
if (!mRooted) {
mozilla::HoldJSObjects(this);
mRooted = true;
}
}
void
IccManager::Unroot()
{
if (mRooted) {
mJsIccIds = nullptr;
mozilla::DropJSObjects(this);
mRooted = false;
}
}
// nsIDOMMozIccManager
NS_IMETHODIMP
IccManager::SendStkResponse(const JS::Value& aCommand,
const JS::Value& aResponse)
IccManager::GetIccIds(JS::Value* aIccIds)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
if (!mJsIccIds) {
nsTArray<nsString> iccIds;
for (uint32_t i = 0; i < mIccListeners.Length(); i++) {
nsRefPtr<Icc> icc = mIccListeners[i]->GetIcc();
if (icc) {
iccIds.AppendElement(icc->GetIccId());
}
}
mProvider->SendStkResponse(mClientId, GetOwner(), aCommand, aResponse);
return NS_OK;
}
NS_IMETHODIMP
IccManager::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
mProvider->SendStkMenuSelection(mClientId, GetOwner(), aItemIdentifier, aHelpRequested);
return NS_OK;
}
NS_IMETHODIMP
IccManager::SendStkTimerExpiration(const JS::Value& aTimer)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
mProvider->SendStkTimerExpiration(mClientId, GetOwner(), aTimer);
return NS_OK;
}
NS_IMETHODIMP
IccManager::SendStkEventDownload(const JS::Value& aEvent)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
mProvider->SendStkEventDownload(mClientId, GetOwner(), aEvent);
return NS_OK;
}
NS_IMETHODIMP
IccManager::GetIccInfo(nsIDOMMozIccInfo** aIccInfo)
{
*aIccInfo = nullptr;
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->GetIccInfo(mClientId, aIccInfo);
}
NS_IMETHODIMP
IccManager::GetCardState(nsAString& cardState)
{
cardState.SetIsVoid(true);
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->GetCardState(mClientId, cardState);
}
NS_IMETHODIMP
IccManager::GetCardLock(const nsAString& aLockType, nsIDOMDOMRequest** aDomRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->GetCardLockState(mClientId, GetOwner(), aLockType, aDomRequest);
}
NS_IMETHODIMP
IccManager::SetCardLock(const JS::Value& aInfo, nsIDOMDOMRequest** aDomRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->SetCardLock(mClientId, GetOwner(), aInfo, aDomRequest);
}
NS_IMETHODIMP
IccManager::UnlockCardLock(const JS::Value& aInfo, nsIDOMDOMRequest** aDomRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->UnlockCardLock(mClientId, GetOwner(), aInfo, aDomRequest);
}
NS_IMETHODIMP
IccManager::GetCardLockRetryCount(const nsAString& aLockType, nsIDOMDOMRequest** aDomRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->GetCardLockRetryCount(mClientId, GetOwner(), aLockType, aDomRequest);
}
NS_IMETHODIMP
IccManager::IccOpenChannel(const nsAString& aAid, nsIDOMDOMRequest** aRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->IccOpenChannel(mClientId, GetOwner(), aAid, aRequest);
}
NS_IMETHODIMP
IccManager::IccExchangeAPDU(int32_t aChannel, const jsval& aApdu, nsIDOMDOMRequest** aRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->IccExchangeAPDU(mClientId, GetOwner(), aChannel, aApdu, aRequest);
}
NS_IMETHODIMP
IccManager::IccCloseChannel(int32_t aChannel, nsIDOMDOMRequest** aRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->IccCloseChannel(mClientId, GetOwner(), aChannel, aRequest);
}
NS_IMETHODIMP
IccManager::ReadContacts(const nsAString& aContactType, nsIDOMDOMRequest** aRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->ReadContacts(mClientId, GetOwner(), aContactType, aRequest);
}
NS_IMETHODIMP
IccManager::UpdateContact(const nsAString& aContactType,
const JS::Value& aContact,
const nsAString& aPin2,
nsIDOMDOMRequest** aRequest)
{
if (!mProvider) {
return NS_ERROR_FAILURE;
}
return mProvider->UpdateContact(mClientId, GetOwner(), aContactType, aContact, aPin2, aRequest);
}
NS_IMPL_EVENT_HANDLER(IccManager, stkcommand)
NS_IMPL_EVENT_HANDLER(IccManager, stksessionend)
NS_IMPL_EVENT_HANDLER(IccManager, cardstatechange)
NS_IMPL_EVENT_HANDLER(IccManager, iccinfochange)
// nsIIccListener
NS_IMETHODIMP
IccManager::NotifyStkCommand(const nsAString& aMessage)
{
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
AutoPushJSContext cx(sc->GetNativeContext());
JS::Rooted<JS::Value> value(cx);
if (!aMessage.IsEmpty()) {
nsCOMPtr<nsIJSON> json(new nsJSON());
nsresult rv = json->DecodeToJSVal(aMessage, cx, value.address());
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
} else {
value = JSVAL_VOID;
AutoPushJSContext cx(sc->GetNativeContext());
JS::Rooted<JSObject*> jsIccIds(cx);
rv = nsTArrayToJSArray(cx, iccIds, jsIccIds.address());
NS_ENSURE_SUCCESS(rv, rv);
mJsIccIds = jsIccIds;
Root();
}
MozStkCommandEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mCommand = value;
nsRefPtr<MozStkCommandEvent> event =
MozStkCommandEvent::Constructor(this, NS_LITERAL_STRING("stkcommand"), init);
return DispatchTrustedEvent(event);
aIccIds->setObject(*mJsIccIds);
return NS_OK;
}
NS_IMETHODIMP
IccManager::NotifyStkSessionEnd()
IccManager::GetIccById(const nsAString& aIccId, nsISupports** aIcc)
{
return DispatchTrustedEvent(NS_LITERAL_STRING("stksessionend"));
*aIcc = nullptr;
for (uint32_t i = 0; i < mIccListeners.Length(); i++) {
nsRefPtr<Icc> icc = mIccListeners[i]->GetIcc();
if (icc && aIccId == icc->GetIccId()) {
icc.forget(aIcc);
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
IccManager::NotifyCardStateChanged()
{
return DispatchTrustedEvent(NS_LITERAL_STRING("cardstatechange"));
}
NS_IMETHODIMP
IccManager::NotifyIccInfoChanged()
{
return DispatchTrustedEvent(NS_LITERAL_STRING("iccinfochange"));
}
NS_IMPL_EVENT_HANDLER(IccManager, iccdetected)
NS_IMPL_EVENT_HANDLER(IccManager, iccundetected)

View File

@ -9,40 +9,48 @@
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMIccManager.h"
#include "nsIIccProvider.h"
#include "nsTArrayHelpers.h"
namespace mozilla {
namespace dom {
class IccManager : public nsDOMEventTargetHelper
, public nsIDOMMozIccManager
{
/**
* Class IccManager doesn't actually inherit nsIIccListener. Instead, it owns
* an nsIIccListener derived instance mListener and passes it to
* nsIIccProvider. The onreceived events are first delivered to mListener and
* then forwarded to its owner, IccManager. See also bug 775997 comment #51.
*/
class Listener;
class IccListener;
class IccManager MOZ_FINAL : public nsDOMEventTargetHelper
, public nsIDOMMozIccManager
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMMOZICCMANAGER
NS_DECL_NSIICCLISTENER
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
IccManager();
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IccManager,
nsDOMEventTargetHelper)
void Init(nsPIDOMWindow *aWindow);
void Shutdown();
IccManager(nsPIDOMWindow* aWindow);
~IccManager();
void
Shutdown();
nsresult
NotifyIccAdd(const nsAString& aIccId);
nsresult
NotifyIccRemove(const nsAString& aIccId);
private:
// TODO: Bug 814637 - WebIccManager API: support multiple sim cards
// The private member, mClient, will be moved to other proper place for
// supporting multiple sim cards.
uint32_t mClientId;
nsCOMPtr<nsIIccProvider> mProvider;
nsRefPtr<Listener> mListener;
nsTArray<nsRefPtr<IccListener>> mIccListeners;
// Cached iccIds js array object. Cleared whenever the NotifyIccAdd() or
// NotifyIccRemove() is called, and then rebuilt once a page looks for the
// iccIds attribute.
JS::Heap<JSObject*> mJsIccIds;
bool mRooted;
void Root();
void Unroot();
};
} // namespace dom

View File

@ -5,10 +5,13 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
'Icc.h',
'IccManager.h',
]
SOURCES += [
'Icc.cpp',
'IccListener.cpp',
'IccManager.cpp',
]
@ -17,7 +20,9 @@ FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'gklayout'
LOCAL_INCLUDES += [
'../../system/gonk',
'/content/events/src',
]