зеркало из https://github.com/mozilla/gecko-dev.git
Bug 674726 - WebTelephony. r=philikon+mounir, sr=sicking. Not part of the default build.
--HG-- extra : transplant_source : %1A%23%10d%88%B3%DA%87%C9%DD0%E6P%1Ct%AD%7D%80%B6%B4
This commit is contained in:
Родитель
03ac2b686a
Коммит
288be4f200
|
@ -46,6 +46,9 @@ pref("browser.homescreenURL", "file:///system/home/homescreen.html");
|
|||
pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system/home/homescreen.html");
|
||||
#endif
|
||||
|
||||
// URL for the dialer application.
|
||||
pref("dom.telephony.app.phone.url", "http://localhost:7777/dialer/dialer.html");
|
||||
|
||||
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
|
||||
pref("browser.viewport.scaleRatio", -1);
|
||||
|
||||
|
|
|
@ -83,12 +83,12 @@ DIRS += \
|
|||
workers \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
ifdef MOZ_B2G_RIL
|
||||
DIRS += \
|
||||
telephony \
|
||||
wifi \
|
||||
$(NULL)
|
||||
endif #}
|
||||
endif
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
|
|
|
@ -137,6 +137,10 @@ ifdef MOZ_JSDEBUGGER
|
|||
DEFINES += -DMOZ_JSDEBUGGER
|
||||
endif
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
DEFINES += -DMOZ_B2G_RIL
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
|
|
|
@ -75,6 +75,10 @@
|
|||
#include "nsIWebNavigation.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "TelephonyFactory.h"
|
||||
#endif
|
||||
|
||||
// This should not be in the namespace.
|
||||
DOMCI_DATA(Navigator, mozilla::dom::Navigator)
|
||||
|
||||
|
@ -123,6 +127,9 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorBattery)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDesktopNotification)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorTelephony)
|
||||
#endif
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
@ -159,6 +166,12 @@ Navigator::Invalidate()
|
|||
mSmsManager->Shutdown();
|
||||
mSmsManager = nsnull;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (mTelephony) {
|
||||
mTelephony = nsnull;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPIDOMWindow *
|
||||
|
@ -1018,6 +1031,34 @@ Navigator::GetMozSms(nsIDOMMozSmsManager** aSmsManager)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
||||
//*****************************************************************************
|
||||
// nsNavigator::nsIDOMNavigatorTelephony
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMETHODIMP
|
||||
Navigator::GetMozTelephony(nsIDOMTelephony** aTelephony)
|
||||
{
|
||||
nsCOMPtr<nsIDOMTelephony> telephony = mTelephony;
|
||||
|
||||
if (!telephony) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = NS_NewTelephony(window, getter_AddRefs(mTelephony));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// mTelephony may be null here!
|
||||
telephony = mTelephony;
|
||||
}
|
||||
|
||||
telephony.forget(aTelephony);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
PRInt64
|
||||
Navigator::SizeOf() const
|
||||
{
|
||||
|
|
|
@ -58,6 +58,11 @@ class nsGeolocation;
|
|||
class nsDesktopNotificationCenter;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIDOMNavigatorTelephony.h"
|
||||
class nsIDOMTelephony;
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
// Navigator: Script "navigator" object
|
||||
//*****************************************************************************
|
||||
|
@ -79,6 +84,9 @@ class Navigator : public nsIDOMNavigator,
|
|||
public nsIDOMNavigatorDesktopNotification,
|
||||
public nsIDOMMozNavigatorBattery,
|
||||
public nsIDOMMozNavigatorSms
|
||||
#ifdef MOZ_B2G_RIL
|
||||
, public nsIDOMNavigatorTelephony
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
Navigator(nsPIDOMWindow *aInnerWindow);
|
||||
|
@ -92,6 +100,10 @@ public:
|
|||
NS_DECL_NSIDOMMOZNAVIGATORBATTERY
|
||||
NS_DECL_NSIDOMMOZNAVIGATORSMS
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DECL_NSIDOMNAVIGATORTELEPHONY
|
||||
#endif
|
||||
|
||||
static void Init();
|
||||
|
||||
void Invalidate();
|
||||
|
@ -118,6 +130,9 @@ private:
|
|||
nsRefPtr<nsDesktopNotificationCenter> mNotification;
|
||||
nsRefPtr<battery::BatteryManager> mBatteryManager;
|
||||
nsRefPtr<sms::SmsManager> mSmsManager;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsCOMPtr<nsIDOMTelephony> mTelephony;
|
||||
#endif
|
||||
nsWeakPtr mWindow;
|
||||
};
|
||||
|
||||
|
|
|
@ -516,6 +516,12 @@
|
|||
#include "nsIDOMSmsEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "Telephony.h"
|
||||
#include "TelephonyCall.h"
|
||||
#include "CallEvent.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -1553,6 +1559,15 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CustomEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DEFINE_CLASSINFO_DATA(Telephony, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CallEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
};
|
||||
|
||||
// Objects that should be constructable through |new Name();|
|
||||
|
@ -2341,6 +2356,9 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorBattery,
|
||||
battery::BatteryManager::HasSupport())
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorSms)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorTelephony)
|
||||
#endif
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Plugin, nsIDOMPlugin)
|
||||
|
@ -4245,6 +4263,23 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
DOM_CLASSINFO_MAP_BEGIN(Telephony, nsIDOMTelephony)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMTelephony)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(TelephonyCall, nsIDOMTelephonyCall)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMTelephonyCall)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CallEvent, nsIDOMCallEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCallEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
{
|
||||
PRUint32 i = ArrayLength(sClassInfoData);
|
||||
|
|
|
@ -526,3 +526,9 @@ DOMCI_CLASS(MozCSSKeyframesRule)
|
|||
|
||||
DOMCI_CLASS(MediaQueryList)
|
||||
DOMCI_CLASS(CustomEvent)
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
DOMCI_CLASS(Telephony)
|
||||
DOMCI_CLASS(TelephonyCall)
|
||||
DOMCI_CLASS(CallEvent)
|
||||
#endif
|
||||
|
|
|
@ -56,8 +56,10 @@
|
|||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
|
||||
#else
|
||||
#elif defined(__GNUC__)
|
||||
#define LOG(args...) printf(args);
|
||||
#else
|
||||
#define LOG(args) printf args
|
||||
#endif
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
@ -150,7 +152,8 @@ ConnectWorkerToRIL::RunTask(JSContext *aCx)
|
|||
NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
|
||||
JSObject *workerGlobal = JS_GetGlobalObject(aCx);
|
||||
|
||||
return JS_DefineFunction(aCx, workerGlobal, "postRILMessage", PostToRIL, 1, 0);
|
||||
return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage", PostToRIL, 1,
|
||||
0);
|
||||
}
|
||||
|
||||
class RILReceiver : public RilConsumer
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CallEvent.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
#include "Telephony.h"
|
||||
#include "TelephonyCall.h"
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
|
||||
// static
|
||||
already_AddRefed<CallEvent>
|
||||
CallEvent::Create(TelephonyCall* aCall)
|
||||
{
|
||||
NS_ASSERTION(aCall, "Null pointer!");
|
||||
|
||||
nsRefPtr<CallEvent> event = new CallEvent();
|
||||
|
||||
event->mCall = aCall;
|
||||
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CallEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent,
|
||||
nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mCall->ToISupports(),
|
||||
TelephonyCall, "mCall")
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent,
|
||||
nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCall)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CallEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMCallEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CallEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(CallEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(CallEvent, nsDOMEvent)
|
||||
|
||||
DOMCI_DATA(CallEvent, CallEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CallEvent::GetCall(nsIDOMTelephonyCall** aCall)
|
||||
{
|
||||
nsCOMPtr<nsIDOMTelephonyCall> call = mCall;
|
||||
call.forget(aCall);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_callevent_h__
|
||||
#define mozilla_dom_telephony_callevent_h__
|
||||
|
||||
#include "TelephonyCommon.h"
|
||||
|
||||
#include "nsIDOMCallEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
||||
#include "nsDOMEvent.h"
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class CallEvent : public nsDOMEvent,
|
||||
public nsIDOMCallEvent
|
||||
{
|
||||
nsRefPtr<TelephonyCall> mCall;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
NS_DECL_NSIDOMCALLEVENT
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, nsDOMEvent)
|
||||
|
||||
static already_AddRefed<CallEvent>
|
||||
Create(TelephonyCall* aCall);
|
||||
|
||||
nsresult
|
||||
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
|
||||
{
|
||||
NS_ASSERTION(aTarget, "Null pointer!");
|
||||
NS_ASSERTION(!aEventType.IsEmpty(), "Empty event type!");
|
||||
|
||||
nsresult rv = InitEvent(aEventType, false, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetTrusted(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIDOMEvent* thisEvent =
|
||||
static_cast<nsDOMEvent*>(const_cast<CallEvent*>(this));
|
||||
|
||||
bool dummy;
|
||||
rv = aTarget->DispatchEvent(thisEvent, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
CallEvent()
|
||||
: nsDOMEvent(nsnull, nsnull)
|
||||
{ }
|
||||
|
||||
~CallEvent()
|
||||
{ }
|
||||
};
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_telephony_callevent_h__
|
|
@ -50,14 +50,21 @@ FORCE_STATIC_LIB = 1
|
|||
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
CPPSRCS = \
|
||||
Telephony.cpp \
|
||||
TelephonyCall.cpp \
|
||||
CallEvent.cpp \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
mozIDOMTelephony.idl \
|
||||
nsIDOMNavigatorTelephony.idl \
|
||||
nsIDOMTelephony.idl \
|
||||
nsIDOMTelephonyCall.idl \
|
||||
nsIDOMCallEvent.idl \
|
||||
nsITelephone.idl \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
Telephony.manifest \
|
||||
Telephony.js \
|
||||
nsTelephonyWorker.manifest \
|
||||
nsTelephonyWorker.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,465 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Telephony.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "CallEvent.h"
|
||||
#include "TelephonyCall.h"
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
using mozilla::Preferences;
|
||||
|
||||
#define DOM_TELEPHONY_APP_PHONE_URL_PREF "dom.telephony.app.phone.url"
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
inline nsresult
|
||||
nsTArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
|
||||
const nsTArray<nsRefPtr<T> >& aSourceArray,
|
||||
JSObject** aResultArray)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
NS_ASSERTION(aGlobal, "Null global!");
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(aCx, aGlobal)) {
|
||||
NS_WARNING("Failed to enter compartment!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSObject* arrayObj;
|
||||
|
||||
if (aSourceArray.IsEmpty()) {
|
||||
arrayObj = JS_NewArrayObject(aCx, 0, nsnull);
|
||||
} else {
|
||||
nsTArray<jsval> valArray;
|
||||
valArray.SetLength(aSourceArray.Length());
|
||||
|
||||
for (PRUint32 index = 0; index < valArray.Length(); index++) {
|
||||
nsISupports* obj = aSourceArray[index]->ToISupports();
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, aGlobal, obj, &valArray[index]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
arrayObj = JS_NewArrayObject(aCx, valArray.Length(), valArray.Elements());
|
||||
}
|
||||
|
||||
if (!arrayObj) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// XXX This is not what Jonas wants. He wants it to be live.
|
||||
if (!JS_FreezeObject(aCx, arrayObj)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResultArray = arrayObj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Telephony::~Telephony()
|
||||
{
|
||||
if (mTelephone && mTelephoneCallback) {
|
||||
mTelephone->UnregisterCallback(mTelephoneCallback);
|
||||
}
|
||||
|
||||
if (mRooted) {
|
||||
NS_DROP_JS_OBJECTS(this, Telephony);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<Telephony>
|
||||
Telephony::Create(nsPIDOMWindow* aOwner, nsITelephone* aTelephone)
|
||||
{
|
||||
NS_ASSERTION(aOwner, "Null owner!");
|
||||
NS_ASSERTION(aTelephone, "Null telephone!");
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
|
||||
NS_ENSURE_TRUE(sgo, nsnull);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(scriptContext, nsnull);
|
||||
|
||||
nsRefPtr<Telephony> telephony = new Telephony();
|
||||
|
||||
telephony->mOwner = aOwner;
|
||||
telephony->mScriptContext.swap(scriptContext);
|
||||
telephony->mTelephone = aTelephone;
|
||||
telephony->mTelephoneCallback = new TelephoneCallback(telephony);
|
||||
|
||||
nsresult rv = aTelephone->EnumerateCalls(telephony->mTelephoneCallback);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
rv = aTelephone->RegisterCallback(telephony->mTelephoneCallback);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
return telephony.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Telephony::SwitchActiveCall(TelephonyCall* aCall)
|
||||
{
|
||||
if (mActiveCall) {
|
||||
// Put the call on hold?
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
}
|
||||
mActiveCall = aCall;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(incoming)
|
||||
for (PRUint32 index = 0; index < tmp->mCalls.Length(); index++) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCalls[i]");
|
||||
cb.NoteXPCOMChild(tmp->mCalls[index]->ToISupports());
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Telephony,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mCallsArray, "mCallsArray")
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Telephony,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(incoming)
|
||||
tmp->mCalls.Clear();
|
||||
tmp->mActiveCall = nsnull;
|
||||
tmp->mCallsArray = nsnull;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMTelephony)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Telephony)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Telephony, nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_RELEASE_INHERITED(Telephony, nsDOMEventTargetWrapperCache)
|
||||
|
||||
DOMCI_DATA(Telephony, Telephony)
|
||||
|
||||
NS_IMPL_ISUPPORTS1(Telephony::TelephoneCallback, nsITelephoneCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(!aNumber.IsEmpty());
|
||||
|
||||
nsresult rv = mTelephone->Dial(aNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<TelephonyCall> call =
|
||||
TelephonyCall::Create(this, aNumber, nsITelephone::CALL_STATE_DIALING);
|
||||
NS_ASSERTION(call, "This should never fail!");
|
||||
|
||||
NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
|
||||
|
||||
call.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetMuted(bool* aMuted)
|
||||
{
|
||||
nsresult rv = mTelephone->GetMicrophoneMuted(aMuted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::SetMuted(bool aMuted)
|
||||
{
|
||||
nsresult rv = mTelephone->SetMicrophoneMuted(aMuted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetSpeakerEnabled(bool* aSpeakerEnabled)
|
||||
{
|
||||
nsresult rv = mTelephone->GetSpeakerEnabled(aSpeakerEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::SetSpeakerEnabled(bool aSpeakerEnabled)
|
||||
{
|
||||
nsresult rv = mTelephone->SetSpeakerEnabled(aSpeakerEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetActive(jsval* aActive)
|
||||
{
|
||||
if (!mActiveCall) {
|
||||
aActive->setNull();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(mScriptContext->GetNativeContext(),
|
||||
mScriptContext->GetNativeGlobal(),
|
||||
mActiveCall->ToISupports(), aActive);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::SetActive(const jsval& aActive)
|
||||
{
|
||||
if (aActive.isObject()) {
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
NS_ASSERTION(xpc, "This should never be null!");
|
||||
|
||||
nsISupports* native =
|
||||
xpc->GetNativeOfWrapper(mScriptContext->GetNativeContext(),
|
||||
&aActive.toObject());
|
||||
|
||||
nsCOMPtr<nsIDOMTelephonyCall> call = do_QueryInterface(native);
|
||||
if (call) {
|
||||
// See if this call has the same telephony object. Otherwise we can't use
|
||||
// it.
|
||||
TelephonyCall* concreteCall = static_cast<TelephonyCall*>(call.get());
|
||||
if (this == concreteCall->mTelephony) {
|
||||
SwitchActiveCall(concreteCall);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetCalls(jsval* aCalls)
|
||||
{
|
||||
JSObject* calls = mCallsArray;
|
||||
if (!calls) {
|
||||
nsresult rv =
|
||||
nsTArrayToJSArray(mScriptContext->GetNativeContext(),
|
||||
mScriptContext->GetNativeGlobal(), mCalls, &calls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mRooted) {
|
||||
NS_HOLD_JS_OBJECTS(this, Telephony);
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
mCallsArray = calls;
|
||||
}
|
||||
|
||||
aCalls->setObject(*calls);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::StartTone(const nsAString& aDTMFChar)
|
||||
{
|
||||
if (aDTMFChar.IsEmpty()) {
|
||||
NS_WARNING("Empty tone string will be ignored");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aDTMFChar.Length() > 1) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv = mTelephone->StartTone(aDTMFChar);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::StopTone()
|
||||
{
|
||||
nsresult rv = mTelephone->StopTone();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::SendTones(const nsAString& aTones, PRUint32 aToneDuration,
|
||||
PRUint32 aIntervalDuration)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(Telephony, incoming)
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
const nsAString& aNumber)
|
||||
{
|
||||
// If we already know about this call then just update its state.
|
||||
for (PRUint32 index = 0; index < mCalls.Length(); index++) {
|
||||
nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
|
||||
if (tempCall->CallIndex() == aCallIndex) {
|
||||
// This can call back and modify the array... Grab a real ref here.
|
||||
nsRefPtr<TelephonyCall> call = tempCall;
|
||||
|
||||
// See if this should replace our current active call.
|
||||
if (aCallState == nsITelephone::CALL_STATE_CONNECTED) {
|
||||
SwitchActiveCall(call);
|
||||
}
|
||||
|
||||
// Change state.
|
||||
call->ChangeState(aCallState);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't know anything about this call before now, must be incoming.
|
||||
NS_ASSERTION(aCallState == nsITelephone::CALL_STATE_INCOMING,
|
||||
"Serious logic problem here!");
|
||||
|
||||
nsRefPtr<TelephonyCall> call =
|
||||
TelephonyCall::Create(this, aNumber, aCallState, aCallIndex);
|
||||
NS_ASSERTION(call, "This should never fail!");
|
||||
|
||||
NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
|
||||
|
||||
// Dispatch incoming event.
|
||||
nsRefPtr<CallEvent> event = CallEvent::Create(call);
|
||||
NS_ASSERTION(event, "This should never fail!");
|
||||
|
||||
nsresult rv =
|
||||
event->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("incoming"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::EnumerateCallState(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
const nsAString& aNumber, bool aIsActive,
|
||||
bool* aContinue)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Make sure we don't somehow add duplicates.
|
||||
for (PRUint32 index = 0; index < mCalls.Length(); index++) {
|
||||
NS_ASSERTION(mCalls[index]->CallIndex() != aCallIndex,
|
||||
"Something is really wrong here!");
|
||||
}
|
||||
#endif
|
||||
nsRefPtr<TelephonyCall> call =
|
||||
TelephonyCall::Create(this, aNumber, aCallState, aCallIndex);
|
||||
NS_ASSERTION(call, "This should never fail!");
|
||||
|
||||
NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
|
||||
|
||||
if (aIsActive) {
|
||||
NS_ASSERTION(!mActiveCall, "Already have an active call!");
|
||||
mActiveCall = call;
|
||||
}
|
||||
|
||||
*aContinue = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony)
|
||||
{
|
||||
NS_ASSERTION(aWindow, "Null pointer!");
|
||||
|
||||
// Make sure we're dealing with an inner window.
|
||||
nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
|
||||
aWindow :
|
||||
aWindow->GetCurrentInnerWindow();
|
||||
NS_ENSURE_TRUE(innerWindow, NS_ERROR_FAILURE);
|
||||
|
||||
if (!nsContentUtils::CanCallerAccess(innerWindow)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> document =
|
||||
do_QueryInterface(innerWindow->GetExtantDocument());
|
||||
NS_ENSURE_TRUE(document, NS_NOINTERFACE);
|
||||
|
||||
nsCOMPtr<nsIURI> documentURI;
|
||||
nsresult rv = document->NodePrincipal()->GetURI(getter_AddRefs(documentURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString documentURL;
|
||||
rv = documentURI->GetSpec(documentURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString phoneAppURL;
|
||||
rv = Preferences::GetCString(DOM_TELEPHONY_APP_PHONE_URL_PREF, &phoneAppURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<Telephony> telephony;
|
||||
if (phoneAppURL.Equals(documentURL, nsCaseInsensitiveCStringComparator())) {
|
||||
nsCOMPtr<nsITelephone> telephone =
|
||||
do_GetService("@mozilla.org/telephony/radio-interface;1");
|
||||
NS_ENSURE_TRUE(telephone, NS_ERROR_FAILURE);
|
||||
|
||||
telephony = Telephony::Create(innerWindow, telephone);
|
||||
}
|
||||
telephony.forget(aTelephony);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_telephony_h__
|
||||
#define mozilla_dom_telephony_telephony_h__
|
||||
|
||||
#include "TelephonyCommon.h"
|
||||
|
||||
#include "nsIDOMTelephony.h"
|
||||
#include "nsIDOMTelephonyCall.h"
|
||||
#include "nsITelephone.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class Telephony : public nsDOMEventTargetWrapperCache,
|
||||
public nsIDOMTelephony
|
||||
{
|
||||
nsCOMPtr<nsITelephone> mTelephone;
|
||||
nsCOMPtr<nsITelephoneCallback> mTelephoneCallback;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(incoming);
|
||||
|
||||
TelephonyCall* mActiveCall;
|
||||
nsTArray<nsRefPtr<TelephonyCall> > mCalls;
|
||||
|
||||
// Cached calls array object. Cleared whenever mCalls changes and then rebuilt
|
||||
// once a page looks for the liveCalls attribute.
|
||||
JSObject* mCallsArray;
|
||||
|
||||
bool mRooted;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMTELEPHONY
|
||||
NS_DECL_NSITELEPHONECALLBACK
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
|
||||
Telephony,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
|
||||
static already_AddRefed<Telephony>
|
||||
Create(nsPIDOMWindow* aOwner, nsITelephone* aTelephone);
|
||||
|
||||
nsIDOMEventTarget*
|
||||
ToIDOMEventTarget() const
|
||||
{
|
||||
return static_cast<nsDOMEventTargetWrapperCache*>(
|
||||
const_cast<Telephony*>(this));
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
ToISupports() const
|
||||
{
|
||||
return ToIDOMEventTarget();
|
||||
}
|
||||
|
||||
void
|
||||
AddCall(TelephonyCall* aCall)
|
||||
{
|
||||
NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!");
|
||||
mCalls.AppendElement(aCall);
|
||||
mCallsArray = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveCall(TelephonyCall* aCall)
|
||||
{
|
||||
NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!");
|
||||
mCalls.RemoveElement(aCall);
|
||||
mCallsArray = nsnull;
|
||||
}
|
||||
|
||||
nsITelephone*
|
||||
Telephone() const
|
||||
{
|
||||
return mTelephone;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
Owner() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
nsIScriptContext*
|
||||
ScriptContext() const
|
||||
{
|
||||
return mScriptContext;
|
||||
}
|
||||
|
||||
private:
|
||||
Telephony()
|
||||
: mActiveCall(nsnull), mCallsArray(nsnull), mRooted(false)
|
||||
{ }
|
||||
|
||||
~Telephony();
|
||||
|
||||
void
|
||||
SwitchActiveCall(TelephonyCall* aCall);
|
||||
|
||||
class TelephoneCallback : public nsITelephoneCallback
|
||||
{
|
||||
Telephony* mTelephony;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSITELEPHONECALLBACK(mTelephony->)
|
||||
|
||||
TelephoneCallback(Telephony* aTelephony)
|
||||
: mTelephony(aTelephony)
|
||||
{
|
||||
NS_ASSERTION(mTelephony, "Null pointer!");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_telephony_telephony_h__
|
|
@ -1,448 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const TELEPHONY_CID = Components.ID("{37e248d2-02ff-469b-bb31-eef5a4a4bee3}");
|
||||
const TELEPHONY_CONTRACTID = "@mozilla.org/telephony;1";
|
||||
|
||||
const TELEPHONY_CALL_CID = Components.ID("{6b9b3daf-e5ea-460b-89a5-641ee20dd577}");
|
||||
const TELEPHONY_CALL_CONTRACTID = "@mozilla.org/telephony-call;1";
|
||||
|
||||
|
||||
const DOM_RADIOSTATE_UNAVAILABLE = "unavailable";
|
||||
const DOM_RADIOSTATE_OFF = "off";
|
||||
const DOM_RADIOSTATE_READY = "ready";
|
||||
|
||||
const DOM_CARDSTATE_UNAVAILABLE = "unavailable";
|
||||
const DOM_CARDSTATE_ABSENT = "absent";
|
||||
const DOM_CARDSTATE_PIN_REQUIRED = "pin_required";
|
||||
const DOM_CARDSTATE_PUK_REQUIRED = "puk_required";
|
||||
const DOM_CARDSTATE_NETWORK_LOCKED = "network_locked";
|
||||
const DOM_CARDSTATE_NOT_READY = "not_ready";
|
||||
const DOM_CARDSTATE_READY = "ready";
|
||||
|
||||
const DOM_CALL_READYSTATE_DIALING = "dialing";
|
||||
const DOM_CALL_READYSTATE_RINGING = "ringing";
|
||||
const DOM_CALL_READYSTATE_BUSY = "busy";
|
||||
const DOM_CALL_READYSTATE_CONNECTING = "connecting";
|
||||
const DOM_CALL_READYSTATE_CONNECTED = "connected";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTING = "disconnecting";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTED = "disconnected";
|
||||
const DOM_CALL_READYSTATE_INCOMING = "incoming";
|
||||
const DOM_CALL_READYSTATE_HOLDING = "holding";
|
||||
const DOM_CALL_READYSTATE_HELD = "held";
|
||||
|
||||
const CALLINDEX_TEMPORARY_DIALING = -1;
|
||||
|
||||
/**
|
||||
* Define an event listener slot on an object, e.g.
|
||||
*
|
||||
* obj.onerror = function () {...}
|
||||
*
|
||||
* will register the function as an event handler for the "error" event
|
||||
* if the "error" slot was defined on 'obj' or its prototype.
|
||||
*/
|
||||
function defineEventListenerSlot(object, event_type) {
|
||||
let property_name = "on" + event_type;
|
||||
let hidden_name = "_on" + event_type;
|
||||
let bound_name = "_bound_on" + event_type;
|
||||
object.__defineGetter__(property_name, function getter() {
|
||||
return this[hidden_name];
|
||||
});
|
||||
object.__defineSetter__(property_name, function setter(handler) {
|
||||
let old_handler = this[bound_name];
|
||||
if (old_handler) {
|
||||
this.removeEventListener(event_type, old_handler);
|
||||
}
|
||||
// Bind the handler to the object so that its 'this' is correct.
|
||||
let bound_handler = handler.bind(this);
|
||||
this.addEventListener(event_type, bound_handler);
|
||||
this[hidden_name] = handler;
|
||||
this[bound_name] = bound_handler;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base object for event targets.
|
||||
*/
|
||||
function EventTarget() {}
|
||||
EventTarget.prototype = {
|
||||
|
||||
addEventListener: function addEventListener(type, handler) {
|
||||
//TODO verify that handler is an nsIDOMEventListener (or function)
|
||||
if (!this._listeners) {
|
||||
this._listeners = {};
|
||||
}
|
||||
if (!this._listeners[type]) {
|
||||
this._listeners[type] = [];
|
||||
}
|
||||
if (this._listeners[type].indexOf(handler) != -1) {
|
||||
// The handler is already registered. Ignore.
|
||||
return;
|
||||
}
|
||||
this._listeners[type].push(handler);
|
||||
},
|
||||
|
||||
removeEventListener: function removeEventListener(type, handler) {
|
||||
let list, index;
|
||||
if (this._listeners &&
|
||||
(list = this._listeners[type]) &&
|
||||
(index = list.indexOf(handler) != -1)) {
|
||||
list.splice(index, 1);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
dispatchEvent: function dispatchEvent(event) {
|
||||
//TODO this does not deal with bubbling, defaultPrevented, canceling, etc.
|
||||
//TODO disallow re-dispatch of the same event if it's already being
|
||||
// dispatched (recursion).
|
||||
if (!this._listeners) {
|
||||
return;
|
||||
}
|
||||
let handlerList = this._listeners[event.type];
|
||||
if (!handlerList) {
|
||||
return;
|
||||
}
|
||||
event.target = this;
|
||||
|
||||
// We need to worry about event handler mutations during the event firing.
|
||||
// The correct behaviour is to *not* call any listeners that are added
|
||||
// during the firing and to *not* call any listeners that are removed
|
||||
// during the firing. To address this, we make a copy of the listener list
|
||||
// before dispatching and then double-check that each handler is still
|
||||
// registered before firing it.
|
||||
let handlers = handlerList.slice();
|
||||
handlers.forEach(function (handler) {
|
||||
if (handlerList.indexOf(handler) == -1) {
|
||||
return;
|
||||
}
|
||||
switch (typeof handler) {
|
||||
case "function":
|
||||
handler(event);
|
||||
break;
|
||||
case "object":
|
||||
handler.handleEvent(event);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback object that Telephony registers with nsITelephone.
|
||||
* Telephony can't use itself because that might overload event handler
|
||||
* attributes ('onfoobar').
|
||||
*/
|
||||
function TelephoneCallback(telephony) {
|
||||
this.telephony = telephony;
|
||||
}
|
||||
TelephoneCallback.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephoneCallback]),
|
||||
|
||||
// nsITelephoneCallback
|
||||
|
||||
onsignalstrengthchange: function onsignalstrengthchange(event) {
|
||||
this.telephony.signalStrength = event.signalStrength;
|
||||
this.telephony._dispatchEventByType("signalstrengthchange");
|
||||
},
|
||||
|
||||
onoperatorchange: function onoperatorchange(event) {
|
||||
this.telephony.operator = event.operator;
|
||||
this.telephony._dispatchEventByType("operatorchange");
|
||||
},
|
||||
|
||||
onradiostatechange: function onradiostatechange(event) {
|
||||
this.telephony.radioState = event.radioState;
|
||||
this.telephony._dispatchEventByType("radiostatechange");
|
||||
},
|
||||
|
||||
oncardstatechange: function oncardstatechange(event) {
|
||||
this.telephony.cardState = event.cardState;
|
||||
this.telephony._dispatchEventByType("cardstatechange");
|
||||
},
|
||||
|
||||
oncallstatechange: function oncallstatechange(event) {
|
||||
this.telephony._processCallState(event);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The navigator.mozTelephony object.
|
||||
*/
|
||||
function Telephony() {}
|
||||
Telephony.prototype = {
|
||||
|
||||
__proto__: EventTarget.prototype,
|
||||
|
||||
classID: TELEPHONY_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: TELEPHONY_CID,
|
||||
contractID: TELEPHONY_CONTRACTID,
|
||||
interfaces: [Ci.mozIDOMTelephony,
|
||||
Ci.nsIDOMEventTarget],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Telephony"}),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMTelephony,
|
||||
Ci.nsIDOMEventTarget,
|
||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer
|
||||
|
||||
init: function init(window) {
|
||||
this.window = window;
|
||||
this.telephone = Cc["@mozilla.org/telephony/radio-interface;1"]
|
||||
.createInstance(Ci.nsITelephone);
|
||||
this.telephoneCallback = new TelephoneCallback(this);
|
||||
//TODO switch to method suggested by bz in bug 707507
|
||||
window.addEventListener("unload", function onunload(event) {
|
||||
this.telephone.unregisterCallback(this.telephoneCallback);
|
||||
this.telephoneCallback = null;
|
||||
this.window = null;
|
||||
}.bind(this));
|
||||
this.telephone.registerCallback(this.telephoneCallback);
|
||||
this.callsByIndex = {};
|
||||
this.liveCalls = [];
|
||||
|
||||
// Populate existing state.
|
||||
let currentState = this.telephone.currentState;
|
||||
let states = currentState.currentCalls;
|
||||
for (let i = 0; i < states.length; i++) {
|
||||
let state = states[i];
|
||||
let call = new TelephonyCall(this.telephone, state.callIndex);
|
||||
call.readyState = state.callState;
|
||||
call.number = state.number;
|
||||
this.liveCalls.push(call);
|
||||
this.callsByIndex[state.callIndex] = call;
|
||||
}
|
||||
|
||||
this.operator = currentState.operator;
|
||||
this.radioState = currentState.radioState;
|
||||
this.cardState = currentState.cardState;
|
||||
this.signalStrength = currentState.signalStrength;
|
||||
},
|
||||
|
||||
_dispatchEventByType: function _dispatchEventByType(type) {
|
||||
let event = this.window.document.createEvent("Event");
|
||||
event.initEvent(type, false, false);
|
||||
//event.isTrusted = true;
|
||||
this.dispatchEvent(event);
|
||||
},
|
||||
|
||||
_dispatchCallEvent: function _dispatchCallEvent(call, type, target) {
|
||||
let event = this.window.document.createEvent("Event");
|
||||
event.initEvent(type, false, false);
|
||||
event.call = call; //XXX this is probably not going to work
|
||||
//event.isTrusted = true;
|
||||
target = target || call;
|
||||
target.dispatchEvent(event);
|
||||
},
|
||||
|
||||
_processCallState: function _processCallState(state) {
|
||||
// If the call is dialing, chances are good that we just kicked that off
|
||||
// so there's a call object without a callIndex. Let's fix that.
|
||||
if (state.callState == DOM_CALL_READYSTATE_DIALING) {
|
||||
let call = this.callsByIndex[CALLINDEX_TEMPORARY_DIALING];
|
||||
if (call) {
|
||||
call.callIndex = state.callIndex;
|
||||
delete this.callsByIndex[CALLINDEX_TEMPORARY_DIALING];
|
||||
this.callsByIndex[call.callIndex] = call;
|
||||
// Nothing else to do, since the initial call state will already be
|
||||
// DOM_CALL_READYSTATE_DIALING, so there's no event to dispatch.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an existing call object, update state and dispatch event
|
||||
// on it.
|
||||
let call = this.callsByIndex[state.callIndex];
|
||||
if (call) {
|
||||
if (call.readyState == state.callState) {
|
||||
// No change in ready state, don't dispatch an event.
|
||||
return;
|
||||
}
|
||||
if (state.readyState == DOM_CALL_READYSTATE_DISCONNECTED) {
|
||||
let index = this.liveCalls.indexOf(call);
|
||||
if (index != -1) {
|
||||
this.liveCalls.splice(index, 1);
|
||||
}
|
||||
delete this.callsByIndex[call.callIndex];
|
||||
}
|
||||
call.readyState = state.callState;
|
||||
this._dispatchCallEvent(call, "readystatechange");
|
||||
this._dispatchCallEvent(call, state.callState);
|
||||
return;
|
||||
}
|
||||
|
||||
// There's no call object yet, so let's create a new one, except when
|
||||
// the state notified means that the call is over.
|
||||
if (state.readyState == DOM_CALL_READYSTATE_DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
call = new TelephonyCall(this.telephone, state.callIndex);
|
||||
call.number = state.number;
|
||||
call.readyState = state.callState;
|
||||
this.callsByIndex[state.callIndex] = call;
|
||||
this.liveCalls.push(call);
|
||||
|
||||
let target;
|
||||
if (call.readyState == DOM_CALL_READYSTATE_INCOMING) {
|
||||
target = this;
|
||||
} else {
|
||||
target = call;
|
||||
this._dispatchCallEvent(call, "readystatechange");
|
||||
}
|
||||
this._dispatchCallEvent(call, state.callState, target);
|
||||
},
|
||||
|
||||
callsByIndex: null,
|
||||
|
||||
// mozIDOMTelephony
|
||||
|
||||
liveCalls: null,
|
||||
|
||||
dial: function dial(number) {
|
||||
this.telephone.dial(number);
|
||||
|
||||
// We don't know ahead of time what callIndex the call is going to have
|
||||
// so let's assign a temp value for now and sort it out on the first
|
||||
// 'callstatechange' event.
|
||||
//TODO ensure there isn't already an outgoing call
|
||||
let callIndex = CALLINDEX_TEMPORARY_DIALING;
|
||||
let call = new TelephonyCall(this.telephone, callIndex);
|
||||
call.readyState = DOM_CALL_READYSTATE_DIALING;
|
||||
call.number = number;
|
||||
this.callsByIndex[callIndex] = call;
|
||||
this.liveCalls.push(call);
|
||||
return call;
|
||||
},
|
||||
|
||||
startTone: function startTone(dtmfChar) {
|
||||
this.telephone.startTone(dtmfChar);
|
||||
},
|
||||
|
||||
stopTone: function stopTone() {
|
||||
this.telephone.stopTone();
|
||||
},
|
||||
|
||||
get muted() {
|
||||
return this.telephone.microphoneMuted;
|
||||
},
|
||||
set muted(value) {
|
||||
this.telephone.microphoneMuted = value;
|
||||
},
|
||||
|
||||
get speakerOn() {
|
||||
return this.telephone.speakerEnabled;
|
||||
},
|
||||
set speakerOn(value) {
|
||||
this.telephone.speakerEnabled = value;
|
||||
},
|
||||
|
||||
// Additional stuff that's useful.
|
||||
|
||||
signalStrength: null,
|
||||
operator: null,
|
||||
radioState: DOM_RADIOSTATE_UNAVAILABLE,
|
||||
cardState: DOM_CARDSTATE_UNAVAILABLE,
|
||||
|
||||
};
|
||||
defineEventListenerSlot(Telephony.prototype, DOM_CALL_READYSTATE_INCOMING);
|
||||
//XXX philikon's additions
|
||||
defineEventListenerSlot(Telephony.prototype, "radiostatechange");
|
||||
defineEventListenerSlot(Telephony.prototype, "cardstatechange");
|
||||
defineEventListenerSlot(Telephony.prototype, "signalstrengthchange");
|
||||
defineEventListenerSlot(Telephony.prototype, "operatorchange");
|
||||
|
||||
|
||||
function TelephonyCall(telephone, callIndex) {
|
||||
this.telephone = telephone;
|
||||
this.callIndex = callIndex;
|
||||
}
|
||||
TelephonyCall.prototype = {
|
||||
|
||||
__proto__: EventTarget.prototype,
|
||||
|
||||
classID: TELEPHONY_CALL_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: TELEPHONY_CALL_CID,
|
||||
contractID: TELEPHONY_CALL_CONTRACTID,
|
||||
interfaces: [Ci.mozIDOMTelephonyCall,
|
||||
Ci.nsIDOMEventTarget],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "TelephonyCall"}),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMTelephonyCall,
|
||||
Ci.nsIDOMEventTarget]),
|
||||
|
||||
|
||||
callIndex: null,
|
||||
|
||||
// mozIDOMTelephonyCall
|
||||
|
||||
number: null,
|
||||
readyState: null,
|
||||
|
||||
answer: function answer() {
|
||||
if (this.readyState != DOM_CALL_READYSTATE_INCOMING) {
|
||||
throw "Can only answer an incoming call!";
|
||||
}
|
||||
this.telephone.answerCall();
|
||||
},
|
||||
|
||||
disconnect: function disconnect() {
|
||||
if (this.readyState == DOM_CALL_READYSTATE_INCOMING) {
|
||||
this.telephone.rejectCall();
|
||||
} else {
|
||||
this.telephone.hangUp(this.callIndex);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
defineEventListenerSlot(TelephonyCall.prototype, "readystatechange");
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_RINGING);
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_BUSY);
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_CONNECTING);
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_CONNECTED);
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_DISCONNECTING);
|
||||
defineEventListenerSlot(TelephonyCall.prototype, DOM_CALL_READYSTATE_DISCONNECTED);
|
||||
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Telephony]);
|
|
@ -1,4 +0,0 @@
|
|||
# Telephony.js
|
||||
component {37e248d2-02ff-469b-bb31-eef5a4a4bee3} Telephony.js
|
||||
contract @mozilla.org/telephony;1 {37e248d2-02ff-469b-bb31-eef5a4a4bee3}
|
||||
category JavaScript-navigator-property mozTelephony @mozilla.org/telephony;1
|
|
@ -0,0 +1,245 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "TelephonyCall.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
#include "CallEvent.h"
|
||||
#include "Telephony.h"
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
|
||||
// static
|
||||
already_AddRefed<TelephonyCall>
|
||||
TelephonyCall::Create(Telephony* aTelephony, const nsAString& aNumber,
|
||||
PRUint16 aCallState, PRUint32 aCallIndex)
|
||||
{
|
||||
NS_ASSERTION(aTelephony, "Null pointer!");
|
||||
NS_ASSERTION(!aNumber.IsEmpty(), "Empty number!");
|
||||
NS_ASSERTION(aCallIndex >= 1, "Invalid call index!");
|
||||
|
||||
nsRefPtr<TelephonyCall> call = new TelephonyCall();
|
||||
|
||||
call->mOwner = aTelephony->Owner();
|
||||
call->mScriptContext = aTelephony->ScriptContext();
|
||||
call->mTelephony = aTelephony;
|
||||
call->mNumber = aNumber;
|
||||
call->mCallIndex = aCallIndex;
|
||||
|
||||
call->ChangeStateInternal(aCallState, false);
|
||||
|
||||
return call.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TelephonyCall::ChangeStateInternal(PRUint16 aCallState, bool aFireEvents)
|
||||
{
|
||||
nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
|
||||
|
||||
nsString stateString;
|
||||
switch (aCallState) {
|
||||
case nsITelephone::CALL_STATE_DIALING:
|
||||
stateString.AssignLiteral("dialing");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_RINGING:
|
||||
stateString.AssignLiteral("ringing");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_BUSY:
|
||||
stateString.AssignLiteral("busy");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_CONNECTING:
|
||||
stateString.AssignLiteral("connecting");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_CONNECTED:
|
||||
stateString.AssignLiteral("connected");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_HOLDING:
|
||||
stateString.AssignLiteral("holding");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_HELD:
|
||||
stateString.AssignLiteral("held");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_RESUMING:
|
||||
stateString.AssignLiteral("resuming");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_DISCONNECTING:
|
||||
stateString.AssignLiteral("disconnecting");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_DISCONNECTED:
|
||||
stateString.AssignLiteral("disconnected");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_INCOMING:
|
||||
stateString.AssignLiteral("incoming");
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Unknown state!");
|
||||
}
|
||||
|
||||
mState = stateString;
|
||||
mCallState = aCallState;
|
||||
|
||||
if (aCallState == nsITelephone::CALL_STATE_DISCONNECTED) {
|
||||
NS_ASSERTION(mLive, "Should be live!");
|
||||
mTelephony->RemoveCall(this);
|
||||
mLive = false;
|
||||
} else if (!mLive) {
|
||||
mTelephony->AddCall(this);
|
||||
mLive = true;
|
||||
}
|
||||
|
||||
if (aFireEvents) {
|
||||
nsRefPtr<CallEvent> event = CallEvent::Create(this);
|
||||
NS_ASSERTION(event, "This should never fail!");
|
||||
|
||||
if (NS_FAILED(event->Dispatch(ToIDOMEventTarget(),
|
||||
NS_LITERAL_STRING("statechange")))) {
|
||||
NS_WARNING("Failed to dispatch statechange event!");
|
||||
}
|
||||
|
||||
// This can change if the statechange handler called back here... Need to
|
||||
// figure out something smarter.
|
||||
if (mCallState == aCallState) {
|
||||
event = CallEvent::Create(this);
|
||||
NS_ASSERTION(event, "This should never fail!");
|
||||
|
||||
if (NS_FAILED(event->Dispatch(ToIDOMEventTarget(), stateString))) {
|
||||
NS_WARNING("Failed to dispatch specific event!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(TelephonyCall)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCall,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mTelephony->ToISupports(),
|
||||
Telephony, "mTelephony")
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(statechange)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(dialing)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(ringing)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(busy)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(connecting)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(connected)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(disconnecting)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(disconnected)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(incoming)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCall,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTelephony)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(statechange)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(dialing)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(ringing)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(busy)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(connecting)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(connected)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(disconnecting)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(disconnected)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(incoming)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCall)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMTelephonyCall)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TelephonyCall)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(TelephonyCall, nsDOMEventTargetWrapperCache)
|
||||
NS_IMPL_RELEASE_INHERITED(TelephonyCall, nsDOMEventTargetWrapperCache)
|
||||
|
||||
DOMCI_DATA(TelephonyCall, TelephonyCall)
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::GetNumber(nsAString& aNumber)
|
||||
{
|
||||
aNumber.Assign(mNumber);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::GetState(nsAString& aState)
|
||||
{
|
||||
aState.Assign(mState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::Answer()
|
||||
{
|
||||
if (mCallState != nsITelephone::CALL_STATE_INCOMING) {
|
||||
NS_WARNING("Answer on non-incoming call ignored!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mTelephony->Telephone()->AnswerCall(mCallIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ChangeStateInternal(nsITelephone::CALL_STATE_CONNECTING, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::HangUp()
|
||||
{
|
||||
if (mCallState == nsITelephone::CALL_STATE_DISCONNECTING ||
|
||||
mCallState == nsITelephone::CALL_STATE_DISCONNECTED) {
|
||||
NS_WARNING("HangUp on previously disconnected call ignored!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mCallState == nsITelephone::CALL_STATE_INCOMING ?
|
||||
mTelephony->Telephone()->RejectCall(mCallIndex) :
|
||||
mTelephony->Telephone()->HangUp(mCallIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ChangeStateInternal(nsITelephone::CALL_STATE_DISCONNECTING, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, statechange)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, dialing)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, ringing)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, busy)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, connecting)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, connected)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnecting)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnected)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, incoming)
|
|
@ -0,0 +1,131 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_telephonycall_h__
|
||||
#define mozilla_dom_telephony_telephonycall_h__
|
||||
|
||||
#include "TelephonyCommon.h"
|
||||
|
||||
#include "nsIDOMTelephonyCall.h"
|
||||
#include "nsITelephone.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class TelephonyCall : public nsDOMEventTargetWrapperCache,
|
||||
public nsIDOMTelephonyCall
|
||||
{
|
||||
NS_DECL_EVENT_HANDLER(statechange);
|
||||
NS_DECL_EVENT_HANDLER(dialing);
|
||||
NS_DECL_EVENT_HANDLER(ringing);
|
||||
NS_DECL_EVENT_HANDLER(busy);
|
||||
NS_DECL_EVENT_HANDLER(connecting);
|
||||
NS_DECL_EVENT_HANDLER(connected);
|
||||
NS_DECL_EVENT_HANDLER(disconnecting);
|
||||
NS_DECL_EVENT_HANDLER(disconnected);
|
||||
NS_DECL_EVENT_HANDLER(incoming);
|
||||
|
||||
nsRefPtr<Telephony> mTelephony;
|
||||
|
||||
nsString mNumber;
|
||||
nsString mState;
|
||||
|
||||
PRUint32 mCallIndex;
|
||||
PRUint16 mCallState;
|
||||
bool mLive;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMTELEPHONYCALL
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TelephonyCall,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
|
||||
static already_AddRefed<TelephonyCall>
|
||||
Create(Telephony* aTelephony, const nsAString& aNumber, PRUint16 aCallState,
|
||||
PRUint32 aCallIndex = PR_UINT32_MAX);
|
||||
|
||||
nsIDOMEventTarget*
|
||||
ToIDOMEventTarget() const
|
||||
{
|
||||
return static_cast<nsDOMEventTargetWrapperCache*>(
|
||||
const_cast<TelephonyCall*>(this));
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
ToISupports() const
|
||||
{
|
||||
return ToIDOMEventTarget();
|
||||
}
|
||||
|
||||
void
|
||||
ChangeState(PRUint16 aCallState)
|
||||
{
|
||||
ChangeStateInternal(aCallState, true);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
CallIndex() const
|
||||
{
|
||||
return mCallIndex;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
CallState() const
|
||||
{
|
||||
return mCallState;
|
||||
}
|
||||
|
||||
private:
|
||||
TelephonyCall()
|
||||
: mCallIndex(PR_UINT32_MAX), mCallState(nsITelephone::CALL_STATE_UNKNOWN),
|
||||
mLive(false)
|
||||
{ }
|
||||
|
||||
~TelephonyCall()
|
||||
{ }
|
||||
|
||||
void
|
||||
ChangeStateInternal(PRUint16 aCallState, bool aFireEvents);
|
||||
};
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_telephony_telephonycall_h__
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_telephonycommon_h__
|
||||
#define mozilla_dom_telephony_telephonycommon_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDOMEventTargetWrapperCache.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define BEGIN_TELEPHONY_NAMESPACE \
|
||||
namespace mozilla { namespace dom { namespace telephony {
|
||||
#define END_TELEPHONY_NAMESPACE \
|
||||
} /* namespace telephony */ } /* namespace dom */ } /* namespace mozilla */
|
||||
#define USING_TELEPHONY_NAMESPACE \
|
||||
using namespace mozilla::dom::telephony;
|
||||
|
||||
class nsIDOMTelephony;
|
||||
class nsIDOMTelephonyCall;
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class Telephony;
|
||||
class TelephonyCall;
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_telephony_telephonycommon_h__
|
|
@ -0,0 +1,51 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_telephonyfactory_h__
|
||||
#define mozilla_dom_telephony_telephonyfactory_h__
|
||||
|
||||
#include "nsIDOMTelephony.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
// Implemented in Telephony.cpp.
|
||||
|
||||
nsresult
|
||||
NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony);
|
||||
|
||||
#endif // mozilla_dom_telephony_telephonyfactory_h__
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIDOMTelephonyCall;
|
||||
|
||||
[scriptable, builtinclass, uuid(95625a90-7f1c-493b-b4bd-73f05834c6dd)]
|
||||
interface nsIDOMCallEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute nsIDOMTelephonyCall call;
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMTelephony;
|
||||
|
||||
[scriptable, builtinclass, uuid(fb2f5927-41ea-442a-8292-81074f69dc41)]
|
||||
interface nsIDOMNavigatorTelephony : nsISupports
|
||||
{
|
||||
readonly attribute nsIDOMTelephony mozTelephony;
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
interface nsIDOMEventListener;
|
||||
interface nsIDOMTelephonyCall;
|
||||
|
||||
[scriptable, builtinclass, uuid(047be0d8-a9cd-49aa-8948-2f60ff3a7a18)]
|
||||
interface nsIDOMTelephony : nsIDOMEventTarget
|
||||
{
|
||||
nsIDOMTelephonyCall dial(in DOMString number);
|
||||
|
||||
attribute boolean muted;
|
||||
attribute boolean speakerEnabled;
|
||||
|
||||
// The call that is "active", i.e. receives microphone input and tones
|
||||
// generated via startTone.
|
||||
attribute jsval active;
|
||||
|
||||
// Array of all calls that are currently connected.
|
||||
readonly attribute jsval calls;
|
||||
|
||||
void startTone(in DOMString tone);
|
||||
void stopTone();
|
||||
void sendTones(in DOMString tones,
|
||||
[optional] in unsigned long toneDuration,
|
||||
[optional] in unsigned long intervalDuration);
|
||||
|
||||
attribute nsIDOMEventListener onincoming;
|
||||
};
|
|
@ -1,3 +1,5 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -14,12 +16,12 @@
|
|||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -36,52 +38,27 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIDOMEventListener;
|
||||
interface mozIDOMTelephonyCall;
|
||||
|
||||
[scriptable, uuid(c7b0046b-ee80-447c-8a95-a389003891bc)]
|
||||
interface mozIDOMTelephony : nsIDOMEventTarget {
|
||||
|
||||
readonly attribute jsval liveCalls;
|
||||
mozIDOMTelephonyCall dial(in DOMString number);
|
||||
void startTone(in DOMString dtmfChar);
|
||||
void stopTone();
|
||||
attribute nsIDOMEventListener onincoming;
|
||||
|
||||
attribute boolean muted;
|
||||
attribute boolean speakerOn;
|
||||
|
||||
//XXX philikon's additions
|
||||
attribute nsIDOMEventListener onoperatorchange;
|
||||
attribute nsIDOMEventListener onradiostatechange;
|
||||
attribute nsIDOMEventListener oncardstatechange;
|
||||
attribute nsIDOMEventListener onsignalstrengthchange;
|
||||
readonly attribute jsval signalStrength;
|
||||
readonly attribute jsval operator;
|
||||
readonly attribute jsval radioState;
|
||||
readonly attribute jsval cardState;
|
||||
};
|
||||
|
||||
[scriptable, uuid(3d0060db-72ef-4b87-aceb-a16ed4c5253e)]
|
||||
interface mozIDOMTelephonyCall : nsIDOMEventTarget {
|
||||
|
||||
[scriptable, builtinclass, uuid(832b7551-ff53-403f-9e2c-d7d28e2bb40b)]
|
||||
interface nsIDOMTelephonyCall : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString number;
|
||||
readonly attribute DOMString readyState;
|
||||
|
||||
readonly attribute DOMString state;
|
||||
|
||||
void answer();
|
||||
void disconnect();
|
||||
void hangUp();
|
||||
|
||||
attribute nsIDOMEventListener onreadystatechange;
|
||||
attribute nsIDOMEventListener onstatechange;
|
||||
|
||||
attribute nsIDOMEventListener ondialing;
|
||||
attribute nsIDOMEventListener onringing;
|
||||
attribute nsIDOMEventListener onbusy;
|
||||
attribute nsIDOMEventListener onconnecting;
|
||||
attribute nsIDOMEventListener onconnected;
|
||||
attribute nsIDOMEventListener ondisconnecting;
|
||||
attribute nsIDOMEventListener ondisconnected;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c8c42b0c-a0dd-4702-9425-a7a80b2075c3)]
|
||||
interface mozIDOMTelephonyCallEvent : nsIDOMEvent {
|
||||
readonly attribute mozIDOMTelephonyCall call;
|
||||
attribute nsIDOMEventListener onincoming;
|
||||
};
|
|
@ -40,31 +40,58 @@
|
|||
[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)]
|
||||
interface nsITelephoneCallback : nsISupports
|
||||
{
|
||||
void oncallstatechange(in jsval event);
|
||||
// 'callState' uses the CALL_STATE values from nsITelephone.
|
||||
void callStateChanged(in unsigned long callIndex,
|
||||
in unsigned short callState,
|
||||
in AString number);
|
||||
|
||||
//XXX philikon's additions
|
||||
void onoperatorchange(in jsval event);
|
||||
void onradiostatechange(in jsval event);
|
||||
void oncardstatechange(in jsval event);
|
||||
void onsignalstrengthchange(in jsval event);
|
||||
// 'callState' uses the CALL_STATE values from nsITelephone. Return true to
|
||||
// continue enumeration or false to cancel.
|
||||
boolean enumerateCallState(in unsigned long callIndex,
|
||||
in unsigned short callState,
|
||||
in AString number,
|
||||
in boolean isActive);
|
||||
};
|
||||
|
||||
[scriptable, uuid(5be6e41d-3aee-4f5c-8284-95cf529dd6fe)]
|
||||
interface nsITelephone : nsISupports
|
||||
{
|
||||
const unsigned short CALL_STATE_UNKNOWN = 0;
|
||||
const unsigned short CALL_STATE_DIALING = 1;
|
||||
const unsigned short CALL_STATE_RINGING = 2;
|
||||
const unsigned short CALL_STATE_BUSY = 3;
|
||||
const unsigned short CALL_STATE_CONNECTING = 4;
|
||||
const unsigned short CALL_STATE_CONNECTED = 5;
|
||||
const unsigned short CALL_STATE_HOLDING = 6;
|
||||
const unsigned short CALL_STATE_HELD = 7;
|
||||
const unsigned short CALL_STATE_RESUMING = 8;
|
||||
const unsigned short CALL_STATE_DISCONNECTING = 9;
|
||||
const unsigned short CALL_STATE_DISCONNECTED = 10;
|
||||
const unsigned short CALL_STATE_INCOMING = 11;
|
||||
|
||||
readonly attribute jsval currentState;
|
||||
|
||||
void registerCallback(in nsITelephoneCallback callback);
|
||||
void unregisterCallback(in nsITelephoneCallback callback);
|
||||
|
||||
/**
|
||||
* Will continue calling callback.enumerateCallState until the callback
|
||||
* returns false.
|
||||
*/
|
||||
void enumerateCalls(in nsITelephoneCallback callback);
|
||||
|
||||
/**
|
||||
* Functionality for making and managing phone calls.
|
||||
*/
|
||||
void dial(in DOMString number);
|
||||
void hangUp(in long callIndex);
|
||||
void hangUp(in unsigned long callIndex);
|
||||
|
||||
void startTone(in DOMString dtmfChar);
|
||||
void stopTone();
|
||||
void answerCall();
|
||||
void rejectCall();
|
||||
|
||||
void answerCall(in unsigned long callIndex);
|
||||
void rejectCall(in unsigned long callIndex);
|
||||
|
||||
attribute bool microphoneMuted;
|
||||
attribute bool speakerEnabled;
|
||||
|
||||
|
|
|
@ -36,26 +36,23 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var RIL = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
const DEBUG = true; // set to false to suppress debug messages
|
||||
|
||||
const TELEPHONYWORKER_CONTRACTID = "@mozilla.org/telephony/worker;1";
|
||||
const TELEPHONYWORKER_CID = Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
||||
|
||||
const DOM_CALL_READYSTATE_DIALING = "dialing";
|
||||
const DOM_CALL_READYSTATE_RINGING = "ringing";
|
||||
const DOM_CALL_READYSTATE_BUSY = "busy";
|
||||
const DOM_CALL_READYSTATE_CONNECTING = "connecting";
|
||||
const DOM_CALL_READYSTATE_CONNECTED = "connected";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTING = "disconnecting";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTED = "disconnected";
|
||||
const DOM_CALL_READYSTATE_INCOMING = "incoming";
|
||||
const DOM_CALL_READYSTATE_HOLDING = "holding";
|
||||
const DOM_CALL_READYSTATE_HELD = "held";
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
const nsITelephone = Ci.nsITelephone;
|
||||
|
||||
const kSmsReceivedObserverTopic = "sms-received";
|
||||
const DOM_SMS_DELIVERY_RECEIVED = "received";
|
||||
|
@ -64,6 +61,25 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
|
|||
"@mozilla.org/sms/smsservice;1",
|
||||
"nsISmsService");
|
||||
|
||||
function convertRILCallState(state) {
|
||||
switch (state) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
return nsITelephone.CALL_STATE_CONNECTED;
|
||||
case RIL.CALL_STATE_HOLDING:
|
||||
return nsITelephone.CALL_STATE_HELD;
|
||||
case RIL.CALL_STATE_DIALING:
|
||||
return nsITelephone.CALL_STATE_DIALING;
|
||||
case RIL.CALL_STATE_ALERTING:
|
||||
return nsITelephone.CALL_STATE_RINGING;
|
||||
case RIL.CALL_STATE_INCOMING:
|
||||
return nsITelephone.CALL_STATE_INCOMING;
|
||||
case RIL.CALL_STATE_WAITING:
|
||||
return nsITelephone.CALL_STATE_HELD; // XXX This may not be right...
|
||||
default:
|
||||
throw new Error("Unknown rilCallState: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake nsIAudioManager implementation so that we can run the telephony
|
||||
* code in a non-Gonk build.
|
||||
|
@ -72,20 +88,20 @@ let FakeAudioManager = {
|
|||
microphoneMuted: false,
|
||||
masterVolume: 1.0,
|
||||
masterMuted: false,
|
||||
phoneState: Ci.nsIAudioManager.PHONE_STATE_CURRENT,
|
||||
phoneState: nsIAudioManager.PHONE_STATE_CURRENT,
|
||||
_forceForUse: {},
|
||||
setForceForUse: function setForceForUse(usage, force) {
|
||||
this._forceForUse[usage] = force;
|
||||
},
|
||||
getForceForUse: function setForceForUse(usage) {
|
||||
return this._forceForUse[usage] || Ci.nsIAudioManager.FORCE_NONE;
|
||||
return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
|
||||
try {
|
||||
return Cc["@mozilla.org/telephony/audiomanager;1"]
|
||||
.getService(Ci.nsIAudioManager);
|
||||
.getService(nsIAudioManager);
|
||||
} catch (ex) {
|
||||
//TODO on the phone this should not fall back as silently.
|
||||
debug("Using fake audio manager.");
|
||||
|
@ -98,14 +114,12 @@ function nsTelephonyWorker() {
|
|||
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
|
||||
this.worker.onerror = this.onerror.bind(this);
|
||||
this.worker.onmessage = this.onmessage.bind(this);
|
||||
|
||||
this._callbacks = [];
|
||||
debug("Starting Worker\n");
|
||||
this.currentState = {
|
||||
signalStrength: null,
|
||||
operator: null,
|
||||
radioState: null,
|
||||
cardState: null,
|
||||
currentCalls: {}
|
||||
cardState: null
|
||||
};
|
||||
}
|
||||
nsTelephonyWorker.prototype = {
|
||||
|
@ -113,7 +127,7 @@ nsTelephonyWorker.prototype = {
|
|||
classID: TELEPHONYWORKER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: TELEPHONYWORKER_CID,
|
||||
contractID: TELEPHONYWORKER_CONTRACTID,
|
||||
classDescription: "TelephonyWorker",
|
||||
classDescription: "Telephone",
|
||||
interfaces: [Ci.nsIRadioWorker,
|
||||
Ci.nsITelephone]}),
|
||||
|
||||
|
@ -121,18 +135,9 @@ nsTelephonyWorker.prototype = {
|
|||
Ci.nsITelephone]),
|
||||
|
||||
onerror: function onerror(event) {
|
||||
// It is very important to call preventDefault on the event here.
|
||||
// If an exception is thrown on the worker, it bubbles out to the
|
||||
// component that created it. If that component doesn't have an
|
||||
// onerror handler, the worker will try to call the error reporter
|
||||
// on the context it was created on. However, That doesn't work
|
||||
// for component contexts and can result in crashes. This onerror
|
||||
// handler has to make sure that it calls preventDefault on the
|
||||
// incoming event.
|
||||
event.preventDefault();
|
||||
|
||||
debug("Got an error: " + event.filename + ":" +
|
||||
event.lineno + ": " + event.message + "\n");
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -146,8 +151,19 @@ nsTelephonyWorker.prototype = {
|
|||
onmessage: function onmessage(event) {
|
||||
let message = event.data;
|
||||
debug("Received message: " + JSON.stringify(message));
|
||||
let value;
|
||||
switch (message.type) {
|
||||
case "callStateChange":
|
||||
// This one will handle its own notifications.
|
||||
this.handleCallStateChange(message.call);
|
||||
break;
|
||||
case "callDisconnected":
|
||||
// This one will handle its own notifications.
|
||||
this.handleCallDisconnected(message.call);
|
||||
break;
|
||||
case "enumerateCalls":
|
||||
// This one will handle its own notifications.
|
||||
this.handleEnumerateCalls(message.calls);
|
||||
break;
|
||||
case "signalstrengthchange":
|
||||
this.currentState.signalStrength = message.signalStrength;
|
||||
break;
|
||||
|
@ -160,69 +176,100 @@ nsTelephonyWorker.prototype = {
|
|||
case "cardstatechange":
|
||||
this.currentState.cardState = message.cardState;
|
||||
break;
|
||||
case "callstatechange":
|
||||
this.handleCallState(message);
|
||||
break;
|
||||
case "sms-received":
|
||||
this.handleSmsReceived(message);
|
||||
break;
|
||||
return;
|
||||
default:
|
||||
// Got some message from the RIL worker that we don't know about.
|
||||
return;
|
||||
throw new Error("Don't know about this message type: " + message.type);
|
||||
}
|
||||
let methodname = "on" + message.type;
|
||||
this._callbacks.forEach(function (callback) {
|
||||
let method = callback[methodname];
|
||||
if (typeof method != "function") {
|
||||
return;
|
||||
}
|
||||
method.call(callback, message);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call state changes by updating our current state and
|
||||
* the audio system.
|
||||
* Track the active call and update the audio system as its state changes.
|
||||
*
|
||||
* XXX Needs some more work to support hold/resume.
|
||||
*/
|
||||
handleCallState: function handleCallState(message) {
|
||||
let currentCalls = this.currentState.currentCalls;
|
||||
let oldState = currentCalls[message.callIndex];
|
||||
|
||||
// Update current state.
|
||||
if (message.callState == DOM_CALL_READYSTATE_DISCONNECTED) {
|
||||
delete currentCalls[message.callIndex];
|
||||
} else {
|
||||
currentCalls[message.callIndex] = message;
|
||||
_activeCall: null,
|
||||
get activeCall() {
|
||||
return this._activeCall;
|
||||
},
|
||||
set activeCall(val) {
|
||||
if (val && !this._activeCall) {
|
||||
// Enable audio.
|
||||
switch (val.state) {
|
||||
case nsITelephone.CALL_STATE_INCOMING:
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
break;
|
||||
case nsITelephone.CALL_STATE_DIALING: // Fall through...
|
||||
case nsITelephone.CALL_STATE_CONNECTED:
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
||||
nsIAudioManager.FORCE_NONE);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid call state for active call: " + val.state);
|
||||
}
|
||||
} else if (!val && this._activeCall) {
|
||||
// Disable audio.
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
this._activeCall = val;
|
||||
},
|
||||
|
||||
// Update the audio system.
|
||||
//TODO this does not handle multiple concurrent calls yet.
|
||||
switch (message.callState) {
|
||||
case DOM_CALL_READYSTATE_DIALING:
|
||||
this.worker.postMessage({type: "setMute", mute: false});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION,
|
||||
Ci.nsIAudioManager.FORCE_NONE);
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_INCOMING:
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_CONNECTED:
|
||||
if (!oldState ||
|
||||
oldState.callState == DOM_CALL_READYSTATE_INCOMING ||
|
||||
oldState.callState == DOM_CALL_READYSTATE_CONNECTING) {
|
||||
// It's an incoming call, so tweak the audio now. If it was an
|
||||
// outgoing call, it would have been tweaked at dialing.
|
||||
this.worker.postMessage({type: "setMute", mute: false});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION,
|
||||
Ci.nsIAudioManager.FORCE_NONE);
|
||||
}
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_DISCONNECTED:
|
||||
this.worker.postMessage({type: "setMute", mute: true});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
/**
|
||||
* Handle call state changes by updating our current state and the audio
|
||||
* system.
|
||||
*/
|
||||
handleCallStateChange: function handleCallStateChange(call) {
|
||||
debug("handleCallStateChange: " + JSON.stringify(call));
|
||||
call.state = convertRILCallState(call.state);
|
||||
if (call.state == nsITelephone.CALL_STATE_INCOMING ||
|
||||
call.state == nsITelephone.CALL_STATE_DIALING ||
|
||||
call.state == nsITelephone.CALL_STATE_CONNECTED) {
|
||||
// This is now the active call.
|
||||
this.activeCall = call;
|
||||
}
|
||||
this._deliverCallback("callStateChanged",
|
||||
[call.callIndex, call.state, call.number]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call disconnects by updating our current state and the audio system.
|
||||
*/
|
||||
handleCallDisconnected: function handleCallStateChange(call) {
|
||||
debug("handleCallDisconnected: " + JSON.stringify(call));
|
||||
if (this.activeCall == call) {
|
||||
// No loner active.
|
||||
this.activeCall = null;
|
||||
}
|
||||
this._deliverCallback("callStateChanged",
|
||||
[call.callIndex, nsITelephone.CALL_STATE_DISCONNECTED,
|
||||
call.number]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle calls delivered in response to a 'enumerateCalls' request.
|
||||
*/
|
||||
handleEnumerateCalls: function handleEnumerateCalls(calls) {
|
||||
debug("handleEnumerateCalls: " + JSON.stringify(calls));
|
||||
let callback = this._enumerationCallbacks.shift();
|
||||
let activeCallIndex = this.activeCall ? this.activeCall.callIndex : -1;
|
||||
for (let i in calls) {
|
||||
let call = calls[i];
|
||||
let state = convertRILCallState(call.state);
|
||||
let keepGoing;
|
||||
try {
|
||||
keepGoing =
|
||||
callback.enumerateCallState(call.callIndex, state, call.number,
|
||||
call.callIndex == activeCallIndex);
|
||||
} catch (e) {
|
||||
debug("callback handler for 'enumerateCallState' threw an " +
|
||||
" exception: " + e);
|
||||
keepGoing = true;
|
||||
}
|
||||
if (!keepGoing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -265,12 +312,12 @@ nsTelephonyWorker.prototype = {
|
|||
this.worker.postMessage({type: "stopTone"});
|
||||
},
|
||||
|
||||
answerCall: function answerCall() {
|
||||
this.worker.postMessage({type: "answerCall"});
|
||||
answerCall: function answerCall(callIndex) {
|
||||
this.worker.postMessage({type: "answerCall", callIndex: callIndex});
|
||||
},
|
||||
|
||||
rejectCall: function rejectCall() {
|
||||
this.worker.postMessage({type: "rejectCall"});
|
||||
rejectCall: function rejectCall(callIndex) {
|
||||
this.worker.postMessage({type: "rejectCall", callIndex: callIndex});
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
|
@ -281,23 +328,23 @@ nsTelephonyWorker.prototype = {
|
|||
return;
|
||||
}
|
||||
gAudioManager.phoneState = value ?
|
||||
Ci.nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
|
||||
Ci.nsIAudioManager.PHONE_STATE_IN_CALL; //XXX why is this needed?
|
||||
nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
|
||||
nsIAudioManager.PHONE_STATE_IN_CALL; //XXX why is this needed?
|
||||
gAudioManager.microphoneMuted = value;
|
||||
},
|
||||
|
||||
get speakerEnabled() {
|
||||
return (gAudioManager.getForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION)
|
||||
== Ci.nsIAudioManager.FORCE_SPEAKER);
|
||||
return (gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION) ==
|
||||
nsIAudioManager.FORCE_SPEAKER);
|
||||
},
|
||||
set speakerEnabled(value) {
|
||||
if (value == this.speakerEnabled) {
|
||||
return;
|
||||
}
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
|
||||
let force = value ? Ci.nsIAudioManager.FORCE_SPEAKER :
|
||||
Ci.nsIAudioManager.FORCE_NONE;
|
||||
gAudioManager.setForceUse(Ci.nsIAudioManager.USE_COMMUNICATION, force);
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
|
||||
let force = value ? nsIAudioManager.FORCE_SPEAKER :
|
||||
nsIAudioManager.FORCE_NONE;
|
||||
gAudioManager.setForceUse(nsIAudioManager.USE_COMMUNICATION, force);
|
||||
},
|
||||
|
||||
getNumberOfMessagesForText: function getNumberOfMessagesForText(text) {
|
||||
|
@ -314,19 +361,63 @@ nsTelephonyWorker.prototype = {
|
|||
},
|
||||
|
||||
_callbacks: null,
|
||||
_enumerationCallbacks: null,
|
||||
|
||||
registerCallback: function registerCallback(callback) {
|
||||
debug("Registering callback: " + callback);
|
||||
if (this._callbacks) {
|
||||
if (this._callbacks.indexOf(callback) != -1) {
|
||||
throw new Error("Already registered this callback!");
|
||||
}
|
||||
} else {
|
||||
this._callbacks = [];
|
||||
}
|
||||
this._callbacks.push(callback);
|
||||
},
|
||||
|
||||
unregisterCallback: function unregisterCallback(callback) {
|
||||
let index = this._callbacks.indexOf(callback);
|
||||
if (index == -1) {
|
||||
throw "Callback not registered!";
|
||||
debug("Unregistering callback: " + callback);
|
||||
let index;
|
||||
if (this._callbacks && (index = this._callbacks.indexOf(callback) != -1)) {
|
||||
this._callbacks.splice(index, 1);
|
||||
}
|
||||
this._callbacks.splice(index, 1);
|
||||
},
|
||||
|
||||
enumerateCalls: function enumerateCalls(callback) {
|
||||
debug("Requesting enumeration of calls for callback: " + callback);
|
||||
this.worker.postMessage({type: "enumerateCalls"});
|
||||
if (!this._enumerationCallbacks) {
|
||||
this._enumerationCallbacks = [];
|
||||
}
|
||||
this._enumerationCallbacks.push(callback);
|
||||
},
|
||||
|
||||
_deliverCallback: function _deliverCallback(name, args) {
|
||||
// We need to worry about callback registration state mutations during the
|
||||
// callback firing. The behaviour we want is to *not* call any callbacks
|
||||
// that are added during the firing and to *not* call any callbacks that are
|
||||
// removed during the firing. To address this, we make a copy of the
|
||||
// callback list before dispatching and then double-check that each callback
|
||||
// is still registered before calling it.
|
||||
if (!this._callbacks) {
|
||||
return;
|
||||
}
|
||||
let callbacks = this._callbacks.slice();
|
||||
for each (let callback in callbacks) {
|
||||
if (this._callbacks.indexOf(callback) == -1) {
|
||||
continue;
|
||||
}
|
||||
let handler = callback[name];
|
||||
if (typeof handler != "function") {
|
||||
throw new Error("No handler for " + name);
|
||||
}
|
||||
try {
|
||||
handler.apply(callback, args);
|
||||
} catch (e) {
|
||||
debug("callback handler for " + name + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsTelephonyWorker]);
|
||||
|
|
|
@ -225,26 +225,6 @@ const DOM_CARDSTATE_NETWORK_LOCKED = "network_locked";
|
|||
const DOM_CARDSTATE_NOT_READY = "not_ready";
|
||||
const DOM_CARDSTATE_READY = "ready";
|
||||
|
||||
const DOM_CALL_READYSTATE_DIALING = "dialing";
|
||||
const DOM_CALL_READYSTATE_RINGING = "ringing";
|
||||
const DOM_CALL_READYSTATE_BUSY = "busy";
|
||||
const DOM_CALL_READYSTATE_CONNECTING = "connecting";
|
||||
const DOM_CALL_READYSTATE_CONNECTED = "connected";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTING = "disconnecting";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTED = "disconnected";
|
||||
const DOM_CALL_READYSTATE_INCOMING = "incoming";
|
||||
const DOM_CALL_READYSTATE_HOLDING = "holding";
|
||||
const DOM_CALL_READYSTATE_HELD = "held";
|
||||
|
||||
const RIL_TO_DOM_CALL_STATE = [
|
||||
DOM_CALL_READYSTATE_CONNECTED, // CALL_READYSTATE_ACTIVE
|
||||
DOM_CALL_READYSTATE_HELD, // CALL_READYSTATE_HOLDING
|
||||
DOM_CALL_READYSTATE_DIALING, // CALL_READYSTATE_DIALING
|
||||
DOM_CALL_READYSTATE_RINGING, // CALL_READYSTATE_ALERTING
|
||||
DOM_CALL_READYSTATE_INCOMING, // CALL_READYSTATE_INCOMING
|
||||
DOM_CALL_READYSTATE_HELD // CALL_READYSTATE_WAITING (XXX is this right?)
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* GSM PDU constants
|
||||
|
@ -413,3 +393,7 @@ const PDU_ALPHABET_7BIT_DEFAULT = [
|
|||
"\xfc", // LATIN SMALL LETTER U WITH DIAERESIS
|
||||
"\xe0" // LATIN SMALL LETTER A WITH GRAVE
|
||||
];
|
||||
|
||||
|
||||
// Allow this file to be imported via Components.utils.import().
|
||||
const EXPORTED_SYMBOLS = Object.keys(this);
|
||||
|
|
|
@ -628,13 +628,13 @@ let RIL = {
|
|||
/**
|
||||
* Hang up the phone.
|
||||
*
|
||||
* @param index
|
||||
* @param callIndex
|
||||
* Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
|
||||
*/
|
||||
hangUp: function hangUp(index) {
|
||||
hangUp: function hangUp(callIndex) {
|
||||
Buf.newParcel(REQUEST_HANGUP);
|
||||
Buf.writeUint32(1);
|
||||
Buf.writeUint32(index);
|
||||
Buf.writeUint32(callIndex);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
|
@ -819,7 +819,7 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
|
|||
for (let i = 0; i < calls_length; i++) {
|
||||
let call = {
|
||||
state: Buf.readUint32(), // CALL_STATE_*
|
||||
index: Buf.readUint32(), // GSM index (1-based)
|
||||
callIndex: Buf.readUint32(), // GSM index (1-based)
|
||||
toa: Buf.readUint32(),
|
||||
isMpty: Boolean(Buf.readUint32()),
|
||||
isMT: Boolean(Buf.readUint32()),
|
||||
|
@ -841,7 +841,7 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
|
|||
userData: null //XXX TODO byte array?!?
|
||||
};
|
||||
}
|
||||
calls[call.index] = call;
|
||||
calls[call.callIndex] = call;
|
||||
}
|
||||
Phone.onCurrentCalls(calls);
|
||||
};
|
||||
|
@ -1122,6 +1122,38 @@ let Phone = {
|
|||
*/
|
||||
currentCalls: {},
|
||||
|
||||
/**
|
||||
* Mute or unmute the radio.
|
||||
*/
|
||||
_muted: true,
|
||||
|
||||
get muted() {
|
||||
return this._muted;
|
||||
},
|
||||
|
||||
set muted(val) {
|
||||
val = Boolean(val);
|
||||
if (this._muted != val) {
|
||||
RIL.setMute(val);
|
||||
this._muted = val;
|
||||
}
|
||||
},
|
||||
|
||||
_handleChangedCallState: function _handleChangedCallState(changedCall) {
|
||||
let message = {type: "callStateChange",
|
||||
call: {callIndex: changedCall.callIndex,
|
||||
state: changedCall.state,
|
||||
number: changedCall.number,
|
||||
name: changedCall.name}};
|
||||
this.sendDOMMessage(message);
|
||||
},
|
||||
|
||||
_handleDisconnectedCall: function _handleDisconnectedCall(disconnectedCall) {
|
||||
let message = {type: "callDisconnected",
|
||||
call: {callIndex: disconnectedCall.callIndex}};
|
||||
this.sendDOMMessage(message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handlers for messages from the RIL. They all begin with on* and are called
|
||||
* from RIL object.
|
||||
|
@ -1218,53 +1250,46 @@ let Phone = {
|
|||
// changed state. Remove them from the newCalls map as we deal with them
|
||||
// so that only new calls remain in the map after we're done.
|
||||
for each (let currentCall in this.currentCalls) {
|
||||
let callIndex = currentCall.index;
|
||||
let newCall;
|
||||
if (newCalls) {
|
||||
newCall = newCalls[callIndex];
|
||||
delete newCalls[callIndex];
|
||||
newCall = newCalls[currentCall.callIndex];
|
||||
delete newCalls[currentCall.callIndex];
|
||||
}
|
||||
|
||||
if (!newCall) {
|
||||
// Call is no longer reported by the radio. Send disconnected
|
||||
// state change.
|
||||
this.sendDOMMessage({type: "callstatechange",
|
||||
callState: DOM_CALL_READYSTATE_DISCONNECTED,
|
||||
callIndex: callIndex,
|
||||
number: currentCall.number,
|
||||
name: currentCall.name});
|
||||
delete this.currentCalls[callIndex];
|
||||
continue;
|
||||
if (newCall) {
|
||||
// Call is still valid.
|
||||
if (newCall.state != currentCall.state) {
|
||||
// State has changed.
|
||||
currentCall.state = newCall.state;
|
||||
this._handleChangedCallState(currentCall);
|
||||
}
|
||||
}
|
||||
|
||||
if (newCall.state == currentCall.state) {
|
||||
continue;
|
||||
else {
|
||||
// Call is no longer reported by the radio. Remove from our map and
|
||||
// send disconnected state change.
|
||||
delete this.currentCalls[currentCall.callIndex];
|
||||
this._handleDisconnectedCall(currentCall);
|
||||
}
|
||||
|
||||
this._handleChangedCallState(newCall);
|
||||
}
|
||||
|
||||
// Go through any remaining calls that are new to us.
|
||||
for each (let newCall in newCalls) {
|
||||
if (newCall.isVoice) {
|
||||
// Format international numbers appropriately.
|
||||
if (newCall.number &&
|
||||
newCall.toa == TOA_INTERNATIONAL &&
|
||||
newCall.number[0] != "+") {
|
||||
newCall.number = "+" + newCall.number;
|
||||
}
|
||||
// Add to our map.
|
||||
this.currentCalls[newCall.callIndex] = newCall;
|
||||
this._handleChangedCallState(newCall);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleChangedCallState: function handleChangedCallState(newCall) {
|
||||
// Format international numbers appropriately.
|
||||
if (newCall.number &&
|
||||
newCall.toa == TOA_INTERNATIONAL &&
|
||||
newCall.number[0] != "+") {
|
||||
newCall.number = "+" + newCall.number;
|
||||
}
|
||||
this.currentCalls[newCall.index] = newCall;
|
||||
this.sendDOMMessage({type: "callstatechange",
|
||||
callState: RIL_TO_DOM_CALL_STATE[newCall.state],
|
||||
callIndex: newCall.index,
|
||||
number: newCall.number,
|
||||
name: newCall.name});
|
||||
// Update our mute status. If there is anything in our currentCalls map then
|
||||
// we know it's a voice call and we should leave audio on.
|
||||
this.muted = Object.getOwnPropertyNames(this.currentCalls).length == 0;
|
||||
},
|
||||
|
||||
onCallStateChanged: function onCallStateChanged() {
|
||||
|
@ -1447,6 +1472,18 @@ let Phone = {
|
|||
RIL.getNetworkSelectionMode();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a list of current voice calls.
|
||||
*/
|
||||
enumerateCalls: function enumerateCalls() {
|
||||
if (DEBUG) debug("Sending all current calls");
|
||||
let calls = [];
|
||||
for each (let call in this.currentCalls) {
|
||||
calls.push(call);
|
||||
}
|
||||
this.sendDOMMessage({type: "enumerateCalls", calls: calls});
|
||||
},
|
||||
|
||||
/**
|
||||
* Dial the phone.
|
||||
*
|
||||
|
@ -1496,30 +1533,38 @@ let Phone = {
|
|||
RIL.hangUp(options.callIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Mute or unmute the radio.
|
||||
*
|
||||
* @param mute
|
||||
* Boolean to indicate whether to mute or unmute the radio.
|
||||
*/
|
||||
setMute: function setMute(options) {
|
||||
//TODO need to check whether call is holding/waiting/background
|
||||
// and then use REQUEST_HANGUP_WAITING_OR_BACKGROUND
|
||||
RIL.setMute(options.mute);
|
||||
},
|
||||
|
||||
/**
|
||||
* Answer an incoming call.
|
||||
*
|
||||
* @param callIndex
|
||||
* Call index of the call to answer.
|
||||
*/
|
||||
answerCall: function answerCall() {
|
||||
RIL.answerCall();
|
||||
answerCall: function answerCall(options) {
|
||||
// Check for races. Since we dispatched the incoming call notification the
|
||||
// incoming call may have changed. The main thread thinks that it is
|
||||
// answering the call with the given index, so only answer if that is still
|
||||
// incoming.
|
||||
let call = this.currentCalls[options.callIndex];
|
||||
if (call && call.state == CALL_STATE_INCOMING) {
|
||||
RIL.answerCall();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reject an incoming call.
|
||||
*
|
||||
* @param callIndex
|
||||
* Call index of the call to reject.
|
||||
*/
|
||||
rejectCall: function rejectCall() {
|
||||
RIL.rejectCall();
|
||||
rejectCall: function rejectCall(options) {
|
||||
// Check for races. Since we dispatched the incoming call notification the
|
||||
// incoming call may have changed. The main thread thinks that it is
|
||||
// rejecting the call with the given index, so only reject if that is still
|
||||
// incoming.
|
||||
let call = this.currentCalls[options.callIndex];
|
||||
if (call && call.state == CALL_STATE_INCOMING) {
|
||||
RIL.rejectCall();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -504,6 +504,8 @@ irregularFilenames = {
|
|||
|
||||
'nsIDOMTouch': 'nsIDOMTouchEvent',
|
||||
'nsIDOMTouchList': 'nsIDOMTouchEvent',
|
||||
|
||||
'nsITelephoneCallback': 'nsITelephone',
|
||||
}
|
||||
|
||||
customIncludes = [
|
||||
|
|
Загрузка…
Ссылка в новой задаче