mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 13:21:28 +00:00
Merge m-c to s-c.
This commit is contained in:
commit
ef1c4cc14f
@ -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);
|
||||
|
||||
@ -391,5 +394,8 @@ pref("layers.acceleration.force-enabled", true);
|
||||
pref("dom.screenEnabledProperty.enabled", true);
|
||||
pref("dom.screenBrightnessProperty.enabled", true);
|
||||
|
||||
// Temporary permission hack for WebSMS
|
||||
pref("dom.sms.enabled", true);
|
||||
pref("dom.sms.whitelist", "file://,http://localhost:6666");
|
||||
// Ignore X-Frame-Options headers.
|
||||
pref("b2g.ignoreXFrameOptions", true);
|
||||
|
@ -163,6 +163,7 @@
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_sidebar.xpt
|
||||
@BINPATH@/components/dom_sms.xpt
|
||||
@BINPATH@/components/dom_storage.xpt
|
||||
@BINPATH@/components/dom_stylesheets.xpt
|
||||
@BINPATH@/components/dom_threads.xpt
|
||||
|
@ -1,56 +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 Aero Peek
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2009
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Rob Arnold <tellrob@gmail.com>
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += test
|
||||
endif
|
||||
|
||||
MODULE = wintaskbar
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
WindowsPreviewPerTab.jsm \
|
||||
WindowsJumpLists.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -1,54 +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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2009
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Rob Arnold <robarnold@cmu.edu>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of 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 *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/components/wintaskbar/test
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = browser_taskbar_preview.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
||||
|
@ -208,8 +208,9 @@ Section "MaintenanceService"
|
||||
WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla"
|
||||
WriteRegStr HKLM "${MaintUninstallKey}" "Comments" \
|
||||
"${BrandFullName} ${AppVersion} (${ARCH} ${AB_CD})"
|
||||
WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1
|
||||
${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4
|
||||
WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
|
||||
WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
|
||||
|
||||
; Write out that a maintenance service was attempted.
|
||||
; We do this because on upgrades we will check this value and we only
|
||||
|
@ -56,7 +56,7 @@ CXXFLAGS="$_SAVE_CXXFLAGS"
|
||||
|
||||
AC_LANG_RESTORE
|
||||
|
||||
if test "$ac_have_gcc_pr49911" == "yes"; then
|
||||
if test "$ac_have_gcc_pr49911" = "yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CFLAGS="$CFLAGS -fno-tree-vrp"
|
||||
CXXFLAGS="$CXXFLAGS -fno-tree-vrp"
|
||||
|
@ -1858,7 +1858,7 @@ if test "$GNU_CC"; then
|
||||
# Don't allow undefined symbols in libraries
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
|
||||
fi
|
||||
WARNINGS_AS_ERRORS='-Werror'
|
||||
WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
|
||||
DSO_CFLAGS=''
|
||||
DSO_PIC_CFLAGS='-fPIC'
|
||||
ASFLAGS="$ASFLAGS -fPIC"
|
||||
|
@ -50,7 +50,7 @@ function start() {
|
||||
|
||||
var kIsWindowsVistaOrHigher = false;
|
||||
if (kIsWindows) {
|
||||
// code borrowed from browser/components/wintaskbar/test/browser_taskbar_preview.js
|
||||
// code borrowed from browser/modules/test/browser_taskbar_preview.js
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var version = Components.classes["@mozilla.org/system-info;1"]
|
||||
.getService(Components.interfaces.nsIPropertyBag2)
|
||||
@ -323,7 +323,7 @@ function start() {
|
||||
// due to various weird failures, including one making getRenderbufferParameter tests
|
||||
// on DEPTH_STENCIL fail
|
||||
if (kIsMac) {
|
||||
// code borrowed from browser/components/wintaskbar/test/browser_taskbar_preview.js
|
||||
// code borrowed from browser/modules/test/browser_taskbar_preview.js
|
||||
var is106orHigher = false;
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var version = Components.classes["@mozilla.org/system-info;1"]
|
||||
|
@ -391,8 +391,6 @@ while (testProps.length) {
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = content
|
||||
LIBRARY_NAME = gkconhtmlcon_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
|
@ -43,6 +43,8 @@ class nsHTMLMenuItemElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLMenuItemElement
|
||||
{
|
||||
public:
|
||||
using nsGenericElement::GetText;
|
||||
|
||||
nsHTMLMenuItemElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser);
|
||||
virtual ~nsHTMLMenuItemElement();
|
||||
|
@ -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
|
||||
|
@ -7,7 +7,6 @@ DOM_SRCDIRS = \
|
||||
dom/src/offline \
|
||||
dom/src/geolocation \
|
||||
dom/src/notification \
|
||||
dom/telephony \
|
||||
dom/workers \
|
||||
content/xbl/src \
|
||||
content/xul/document/src \
|
||||
@ -22,5 +21,13 @@ DOM_SRCDIRS = \
|
||||
layout/xul/base/src/tree/src \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
DOM_SRCDIRS += \
|
||||
dom/system/b2g \
|
||||
dom/telephony \
|
||||
dom/wifi \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES += $(DOM_SRCDIRS:%=-I$(topsrcdir)/%)
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
@ -37,10 +37,11 @@
|
||||
|
||||
#include "mozilla/dom/sms/SmsMessage.h"
|
||||
#include "SmsService.h"
|
||||
#include "RadioManager.h"
|
||||
#include "SystemWorkerManager.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
using mozilla::dom::telephony::RadioManager;
|
||||
using mozilla::dom::telephony::SystemWorkerManager;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -49,8 +50,14 @@ namespace sms {
|
||||
NS_IMPL_ISUPPORTS1(SmsService, nsISmsService)
|
||||
|
||||
SmsService::SmsService()
|
||||
: mRIL(RadioManager::GetTelephone())
|
||||
{
|
||||
nsIInterfaceRequestor* ireq = SystemWorkerManager::GetInterfaceRequestor();
|
||||
NS_WARN_IF_FALSE(ireq, "The SystemWorkerManager has not been created!");
|
||||
|
||||
if (ireq) {
|
||||
mRIL = do_GetInterface(ireq);
|
||||
NS_WARN_IF_FALSE(mRIL, "This shouldn't fail!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -508,36 +508,13 @@ NS_IMPL_THREADSAFE_RELEASE(nsGeolocationService)
|
||||
|
||||
static bool sGeoEnabled = true;
|
||||
static bool sGeoIgnoreLocationFilter = false;
|
||||
|
||||
static int
|
||||
GeoEnabledChangedCallback(const char *aPrefName, void *aClosure)
|
||||
{
|
||||
sGeoEnabled = Preferences::GetBool("geo.enabled", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
GeoIgnoreLocationFilterChangedCallback(const char *aPrefName, void *aClosure)
|
||||
{
|
||||
sGeoIgnoreLocationFilter =
|
||||
Preferences::GetBool("geo.ignore.location_filter", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PRInt32 sProviderTimeout = 6000; // Time, in milliseconds, to wait for the location provider to spin up.
|
||||
|
||||
nsresult nsGeolocationService::Init()
|
||||
{
|
||||
mTimeout = Preferences::GetInt("geo.timeout", 6000);
|
||||
|
||||
Preferences::RegisterCallback(GeoIgnoreLocationFilterChangedCallback,
|
||||
"geo.ignore.location_filter");
|
||||
|
||||
GeoIgnoreLocationFilterChangedCallback("geo.ignore.location_filter", nsnull);
|
||||
|
||||
|
||||
Preferences::RegisterCallback(GeoEnabledChangedCallback, "geo.enabled");
|
||||
|
||||
GeoEnabledChangedCallback("geo.enabled", nsnull);
|
||||
Preferences::AddIntVarCache(&sProviderTimeout, "geo.timeout", sProviderTimeout);
|
||||
Preferences::AddBoolVarCache(&sGeoEnabled, "geo.enabled", sGeoEnabled);
|
||||
Preferences::AddBoolVarCache(&sGeoIgnoreLocationFilter, "geo.ignore.location_filter", sGeoIgnoreLocationFilter);
|
||||
|
||||
if (!sGeoEnabled)
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -710,7 +687,7 @@ nsGeolocationService::SetDisconnectTimer()
|
||||
mDisconnectTimer->Cancel();
|
||||
|
||||
mDisconnectTimer->Init(this,
|
||||
mTimeout,
|
||||
sProviderTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
@ -881,7 +858,7 @@ nsGeolocation::HasActiveCallbacks()
|
||||
if (mWatchingCallbacks[i]->IsActive())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return mPendingCallbacks.Length() != 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
NS_DECL_NSIGEOLOCATIONUPDATE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsGeolocationService() {mTimeout = 6000;};
|
||||
nsGeolocationService() {}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
@ -163,9 +163,6 @@ private:
|
||||
// case, we disable the disconnect timer.
|
||||
nsCOMPtr<nsITimer> mDisconnectTimer;
|
||||
|
||||
// Time, in milliseconds, to wait for the location provider to spin up.
|
||||
PRInt32 mTimeout;
|
||||
|
||||
// The object providing geo location information to us.
|
||||
nsCOMArray<nsIGeolocationProvider> mProviders;
|
||||
|
||||
|
@ -61,9 +61,9 @@ ifneq (,$(filter android,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS = android
|
||||
endif
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
ifdef MOZ_B2G_RIL
|
||||
DIRS += b2g
|
||||
endif #}
|
||||
endif
|
||||
|
||||
CPPSRCS = \
|
||||
nsDeviceMotion.cpp \
|
||||
|
@ -51,7 +51,7 @@ FORCE_STATIC_LIB = 1
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
CPPSRCS = \
|
||||
RadioManager.cpp \
|
||||
SystemWorkerManager.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
@ -60,7 +60,7 @@ endif
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIAudioManager.idl \
|
||||
nsIRadioWorker.idl \
|
||||
nsIWorkerHolder.idl \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -37,46 +37,38 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "RadioManager.h"
|
||||
#include "nsIRadioWorker.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "SystemWorkerManager.h"
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#include "nsTelephonyWorker.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsITelephone.h"
|
||||
#include "nsWifiWorker.h"
|
||||
#include "nsIWifi.h"
|
||||
#include "nsIWorkerHolder.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "jstypedarray.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTelephonyWorker.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWifiWorker.h"
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
|
||||
#else
|
||||
#define LOG(args...) printf(args);
|
||||
#endif
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
USING_WORKERS_NAMESPACE
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
static NS_DEFINE_CID(kTelephonyWorkerCID, NS_TELEPHONYWORKER_CID);
|
||||
static NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
|
||||
|
||||
// Topic we listen to for shutdown.
|
||||
#define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
// Doesn't carry a reference, we're owned by services.
|
||||
RadioManager* gInstance = nsnull;
|
||||
NS_DEFINE_CID(kTelephonyWorkerCID, NS_TELEPHONYWORKER_CID);
|
||||
NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
|
||||
|
||||
class ConnectWorkerToRIL : public WorkerTask {
|
||||
// Doesn't carry a reference, we're owned by services.
|
||||
SystemWorkerManager *gInstance = nsnull;
|
||||
|
||||
class ConnectWorkerToRIL : public WorkerTask
|
||||
{
|
||||
public:
|
||||
virtual bool RunTask(JSContext *aCx);
|
||||
};
|
||||
@ -150,12 +142,14 @@ 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
|
||||
{
|
||||
class DispatchRILEvent : public WorkerTask {
|
||||
class DispatchRILEvent : public WorkerTask
|
||||
{
|
||||
public:
|
||||
DispatchRILEvent(RilRawData *aMessage)
|
||||
: mMessage(aMessage)
|
||||
@ -200,14 +194,14 @@ RILReceiver::DispatchRILEvent::RunTask(JSContext *aCx)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
RadioManager::RadioManager()
|
||||
SystemWorkerManager::SystemWorkerManager()
|
||||
: mShutdown(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gInstance, "There should only be one instance!");
|
||||
}
|
||||
|
||||
RadioManager::~RadioManager()
|
||||
SystemWorkerManager::~SystemWorkerManager()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gInstance || gInstance == this,
|
||||
@ -216,23 +210,15 @@ RadioManager::~RadioManager()
|
||||
}
|
||||
|
||||
nsresult
|
||||
RadioManager::Init()
|
||||
SystemWorkerManager::Init()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
if (!obs) {
|
||||
NS_WARNING("Failed to get observer service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = obs->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(!mShutdown, "Already shutdown!");
|
||||
|
||||
JSContext *cx;
|
||||
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
nsresult rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCxPusher pusher;
|
||||
if (!cx || !pusher.Push(cx, false)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -244,32 +230,50 @@ RadioManager::Init()
|
||||
rv = InitWifi(cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
if (!obs) {
|
||||
NS_WARNING("Failed to get observer service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RadioManager::Shutdown()
|
||||
SystemWorkerManager::Shutdown()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
StopRil();
|
||||
mTelephone = nsnull;
|
||||
mWifi = nsnull;
|
||||
|
||||
mShutdown = true;
|
||||
|
||||
StopRil();
|
||||
|
||||
mTelephoneWorker = nsnull;
|
||||
mWifiWorker = nsnull;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<RadioManager>
|
||||
RadioManager::FactoryCreate()
|
||||
already_AddRefed<SystemWorkerManager>
|
||||
SystemWorkerManager::FactoryCreate()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<RadioManager> instance(gInstance);
|
||||
nsRefPtr<SystemWorkerManager> instance(gInstance);
|
||||
|
||||
if (!instance) {
|
||||
instance = new RadioManager();
|
||||
instance = new SystemWorkerManager();
|
||||
if (NS_FAILED(instance->Init())) {
|
||||
instance->Shutdown();
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -280,41 +284,54 @@ RadioManager::FactoryCreate()
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsITelephone>
|
||||
RadioManager::GetTelephone()
|
||||
nsIInterfaceRequestor*
|
||||
SystemWorkerManager::GetInterfaceRequestor()
|
||||
{
|
||||
return gInstance;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gInstance) {
|
||||
nsCOMPtr<nsITelephone> retval = gInstance->mTelephone;
|
||||
return retval.forget();
|
||||
if (aIID.Equals(NS_GET_IID(nsITelephone))) {
|
||||
return CallQueryInterface(mTelephoneWorker,
|
||||
reinterpret_cast<nsITelephone**>(aResult));
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
if (aIID.Equals(NS_GET_IID(nsIWifi))) {
|
||||
return CallQueryInterface(mWifiWorker,
|
||||
reinterpret_cast<nsIWifi**>(aResult));
|
||||
}
|
||||
|
||||
NS_WARNING("Got nothing for the requested IID!");
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RadioManager::InitTelephone(JSContext *cx)
|
||||
SystemWorkerManager::InitTelephone(JSContext *cx)
|
||||
{
|
||||
// The telephony worker component is a hack that gives us a global object for
|
||||
// our own functions and makes creating the worker possible.
|
||||
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
|
||||
// We're keeping as much of this implementation as possible in JS, so the real
|
||||
// worker lives in nsTelephonyWorker.js. All we do here is hold it alive and
|
||||
// hook it up to the RIL thread.
|
||||
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kTelephonyWorkerCID);
|
||||
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
|
||||
|
||||
jsval workerval;
|
||||
nsresult rv = worker->GetWorker(&workerval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
|
||||
|
||||
JSObject *workerobj = JSVAL_TO_OBJECT(workerval);
|
||||
NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(workerval), NS_ERROR_UNEXPECTED);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(cx, workerobj)) {
|
||||
if (!ac.enter(cx, JSVAL_TO_OBJECT(workerval))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
|
||||
WorkerCrossThreadDispatcher *wctd =
|
||||
GetWorkerCrossThreadDispatcher(cx, workerval);
|
||||
if (!wctd) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -328,44 +345,28 @@ RadioManager::InitTelephone(JSContext *cx)
|
||||
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
|
||||
StartRil(receiver);
|
||||
|
||||
mTelephone = do_QueryInterface(worker);
|
||||
NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
|
||||
|
||||
mTelephoneWorker = worker;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RadioManager::InitWifi(JSContext *cx)
|
||||
SystemWorkerManager::InitWifi(JSContext *cx)
|
||||
{
|
||||
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kWifiWorkerCID));
|
||||
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
|
||||
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
|
||||
|
||||
mWifi = do_QueryInterface(worker);
|
||||
NS_ENSURE_TRUE(mWifi, NS_ERROR_FAILURE);
|
||||
|
||||
mWifiWorker = worker;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(RadioManager, nsIObserver)
|
||||
NS_IMPL_ISUPPORTS2(SystemWorkerManager, nsIObserver, nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
RadioManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC)) {
|
||||
if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) {
|
||||
Shutdown();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
if (obs) {
|
||||
if (NS_FAILED(obs->RemoveObserver(this, aTopic))) {
|
||||
NS_WARNING("Failed to remove observer!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Failed to get observer service!");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
84
dom/system/b2g/SystemWorkerManager.h
Normal file
84
dom/system/b2g/SystemWorkerManager.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -*- 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_system_b2g_systemworkermanager_h__
|
||||
#define mozilla_dom_system_b2g_systemworkermanager_h__
|
||||
|
||||
#include "TelephonyCommon.h"
|
||||
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsIWorkerHolder;
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class SystemWorkerManager : public nsIObserver,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
nsresult Init();
|
||||
void Shutdown();
|
||||
|
||||
static already_AddRefed<SystemWorkerManager>
|
||||
FactoryCreate();
|
||||
|
||||
static nsIInterfaceRequestor*
|
||||
GetInterfaceRequestor();
|
||||
|
||||
private:
|
||||
SystemWorkerManager();
|
||||
~SystemWorkerManager();
|
||||
|
||||
nsresult InitTelephone(JSContext *cx);
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
|
||||
nsCOMPtr<nsIWorkerHolder> mTelephoneWorker;
|
||||
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
|
||||
|
||||
bool mShutdown;
|
||||
};
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_system_b2g_systemworkermanager_h__
|
@ -37,7 +37,8 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(8f031451-ac25-4816-a09e-a075bb704e63)]
|
||||
interface nsIRadioWorker : nsISupports {
|
||||
readonly attribute jsval worker;
|
||||
[scriptable, uuid(c04f3102-1ce8-4d57-9c27-8aece9c2740a)]
|
||||
interface nsIWorkerHolder : nsISupports
|
||||
{
|
||||
readonly attribute jsval worker;
|
||||
};
|
91
dom/telephony/CallEvent.cpp
Normal file
91
dom/telephony/CallEvent.cpp
Normal file
@ -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.get();
|
||||
call.forget(aCall);
|
||||
return NS_OK;
|
||||
}
|
99
dom/telephony/CallEvent.h
Normal file
99
dom/telephony/CallEvent.h
Normal file
@ -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)
|
||||
|
469
dom/telephony/Telephony.cpp
Normal file
469
dom/telephony/Telephony.cpp
Normal file
@ -0,0 +1,469 @@
|
||||
/* -*- 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 "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "SystemWorkerManager.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())) {
|
||||
nsIInterfaceRequestor* ireq = SystemWorkerManager::GetInterfaceRequestor();
|
||||
NS_ENSURE_TRUE(ireq, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsITelephone> telephone = do_GetInterface(ireq);
|
||||
NS_ENSURE_TRUE(telephone, NS_ERROR_UNEXPECTED);
|
||||
|
||||
telephony = Telephony::Create(innerWindow, telephone);
|
||||
}
|
||||
telephony.forget(aTelephony);
|
||||
return NS_OK;
|
||||
}
|
158
dom/telephony/Telephony.h
Normal file
158
dom/telephony/Telephony.h
Normal file
@ -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
|
245
dom/telephony/TelephonyCall.cpp
Normal file
245
dom/telephony/TelephonyCall.cpp
Normal file
@ -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)
|
131
dom/telephony/TelephonyCall.h
Normal file
131
dom/telephony/TelephonyCall.h
Normal file
@ -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__
|
@ -37,20 +37,16 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_telephony_radio_h__
|
||||
#define mozilla_dom_telephony_radio_h__
|
||||
#ifndef mozilla_dom_telephony_telephonycommon_h__
|
||||
#define mozilla_dom_telephony_telephonycommon_h__
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
|
||||
#define TELEPHONYRADIO_CONTRACTID "@mozilla.org/telephony/radio;1"
|
||||
#define TELEPHONYRADIOINTERFACE_CONTRACTID "@mozilla.org/telephony/radio-interface;1"
|
||||
#include "nsDOMEventTargetWrapperCache.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define BEGIN_TELEPHONY_NAMESPACE \
|
||||
namespace mozilla { namespace dom { namespace telephony {
|
||||
@ -59,48 +55,14 @@
|
||||
#define USING_TELEPHONY_NAMESPACE \
|
||||
using namespace mozilla::dom::telephony;
|
||||
|
||||
// {a5c3a6de-84c4-4b15-8611-8aeb8d97f8ba}
|
||||
#define TELEPHONYRADIO_CID \
|
||||
{0xa5c3a6de, 0x84c4, 0x4b15, {0x86, 0x11, 0x8a, 0xeb, 0x8d, 0x97, 0xf8, 0xba}}
|
||||
|
||||
// {a688f191-8ffc-47f3-8740-94a312cf59cb}}
|
||||
#define TELEPHONYRADIOINTERFACE_CID \
|
||||
{0xd66e7ece, 0x41b1, 0x4608, {0x82, 0x80, 0x72, 0x50, 0xa6, 0x44, 0xe6, 0x6f}}
|
||||
|
||||
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
class nsITelephone;
|
||||
class nsIWifi;
|
||||
class nsIDOMTelephony;
|
||||
class nsIDOMTelephonyCall;
|
||||
|
||||
BEGIN_TELEPHONY_NAMESPACE
|
||||
|
||||
class RadioManager : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsresult Init();
|
||||
void Shutdown();
|
||||
|
||||
static already_AddRefed<RadioManager>
|
||||
FactoryCreate();
|
||||
|
||||
static already_AddRefed<nsITelephone>
|
||||
GetTelephone();
|
||||
|
||||
protected:
|
||||
RadioManager();
|
||||
~RadioManager();
|
||||
|
||||
nsresult InitTelephone(JSContext *cx);
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
|
||||
nsCOMPtr<nsITelephone> mTelephone;
|
||||
nsCOMPtr<nsIWifi> mWifi;
|
||||
bool mShutdown;
|
||||
};
|
||||
class Telephony;
|
||||
class TelephonyCall;
|
||||
|
||||
END_TELEPHONY_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_telephony_radio_h__
|
||||
#endif // mozilla_dom_telephony_telephonycommon_h__
|
51
dom/telephony/TelephonyFactory.h
Normal file
51
dom/telephony/TelephonyFactory.h
Normal file
@ -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__
|
48
dom/telephony/nsIDOMCallEvent.idl
Normal file
48
dom/telephony/nsIDOMCallEvent.idl
Normal file
@ -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;
|
||||
};
|
48
dom/telephony/nsIDOMNavigatorTelephony.idl
Normal file
48
dom/telephony/nsIDOMNavigatorTelephony.idl
Normal file
@ -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;
|
||||
};
|
68
dom/telephony/nsIDOMTelephony.idl
Normal file
68
dom/telephony/nsIDOMTelephony.idl
Normal file
@ -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;
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This must always match the CID given in nsTelephonyWorker.manifest!
|
||||
#define NS_TELEPHONYWORKER_CID \
|
||||
{ 0x2d831c8d, 0x6017, 0x435b, \
|
||||
{ 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
|
||||
|
@ -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 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,41 +114,29 @@ 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 = {
|
||||
|
||||
classID: TELEPHONYWORKER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: TELEPHONYWORKER_CID,
|
||||
contractID: TELEPHONYWORKER_CONTRACTID,
|
||||
classDescription: "TelephonyWorker",
|
||||
interfaces: [Ci.nsIRadioWorker,
|
||||
classDescription: "Telephone",
|
||||
interfaces: [Ci.nsIWorkerHolder,
|
||||
Ci.nsITelephone]}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioWorker,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
|
||||
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 +150,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 +175,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 +311,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 +327,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 +360,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();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -57,6 +57,7 @@ _TEST_FILES = \
|
||||
test_manyWatchSerial.html \
|
||||
test_manyWindows.html \
|
||||
test_optional_api_params.html \
|
||||
test_shutdown.html \
|
||||
test_windowClose.html \
|
||||
test_timerRestartWatch.html \
|
||||
test_worseAccuracyDoesNotBlockCallback.html \
|
||||
|
@ -64,6 +64,13 @@ function resume_geolocationProvider()
|
||||
prefs.setCharPref("geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
|
||||
}
|
||||
|
||||
function delay_geolocationProvider(delay)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.setCharPref("geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?delay=" + delay);
|
||||
}
|
||||
|
||||
function check_geolocation(location) {
|
||||
|
||||
ok(location, "Check to see if this location is non-null");
|
||||
|
@ -31,6 +31,7 @@ function getPosition(action)
|
||||
return JSON.stringify(response);
|
||||
}
|
||||
|
||||
var timer;
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var params = parseQueryString(request.queryString);
|
||||
@ -54,9 +55,19 @@ function handleRequest(request, response)
|
||||
}
|
||||
|
||||
var response;
|
||||
response.processAsync();
|
||||
response.setStatusLine("1.0", 200, "OK");
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "aplication/x-javascript", false);
|
||||
response.write(position);
|
||||
|
||||
var delay = 0;
|
||||
if ('delay' in params) {
|
||||
delay = params.delay;
|
||||
}
|
||||
timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback(function() {
|
||||
response.write(position);
|
||||
response.finish();
|
||||
}, delay, timer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
|
58
dom/tests/mochitest/geolocation/test_shutdown.html
Normal file
58
dom/tests/mochitest/geolocation/test_shutdown.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=716127
|
||||
-->
|
||||
<head>
|
||||
<title>Test for getCurrentPosition </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="geolocation_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=716127">Mozilla Bug 716127</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
resume_geolocationProvider();
|
||||
force_prompt(true);
|
||||
|
||||
function successCallback(position) {
|
||||
check_geolocation(position);
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['geo.timeout', 100]]}, function() {
|
||||
delay_geolocationProvider(1000);
|
||||
force_prompt(true);
|
||||
navigator.geolocation.getCurrentPosition(success2, handle_error, {maximumAge: 0});
|
||||
});
|
||||
}
|
||||
|
||||
function errorCallback() {
|
||||
ok(false, "unexpected error");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
|
||||
|
||||
function success2(position) {
|
||||
check_geolocation(position);
|
||||
reset_prompt();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function handle_error() {
|
||||
ok(false, "geolocation provider should not have timed out");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -820,10 +820,10 @@ nsWifiWorker.prototype = {
|
||||
classInfo: XPCOMUtils.generateCI({classID: WIFIWORKER_CID,
|
||||
contractID: WIFIWORKER_CONTRACTID,
|
||||
classDescription: "WifiWorker",
|
||||
interfaces: [Ci.nsIRadioWorker,
|
||||
interfaces: [Ci.nsIWorkerHolder,
|
||||
Ci.nsIWifi]}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioWorker,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
|
||||
Ci.nsIWifi]),
|
||||
|
||||
setWifiEnabled: function(enable) {
|
||||
|
@ -46,7 +46,6 @@ function testTab(prefix, callback) {
|
||||
|
||||
testTab("", function() {
|
||||
testTab("foo", function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
******* END LICENSE BLOCK *******
|
||||
|
||||
Hunspell Version: 1.3.2
|
||||
Additional Patches: 694002, 710967
|
||||
Additional Patches: 694002, 710967, 710940
|
||||
|
||||
Hunspell Author: László Németh
|
||||
MySpell Author: Kevin Hendricks & David Einstein
|
||||
|
@ -5523,7 +5523,14 @@ struct cs_info * get_current_cs(const char * es) {
|
||||
// conversion tables static in this file, create them when needed
|
||||
// with help the mozilla backend.
|
||||
struct cs_info * get_current_cs(const char * es) {
|
||||
struct cs_info *ccs;
|
||||
struct cs_info *ccs = new cs_info[256];
|
||||
// Initialze the array with dummy data so that we wouldn't need
|
||||
// to return null in case of failures.
|
||||
for (int i = 0; i <= 0xff; ++i) {
|
||||
ccs[i].ccase = false;
|
||||
ccs[i].clower = i;
|
||||
ccs[i].cupper = i;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
||||
nsCOMPtr<nsIUnicodeDecoder> decoder;
|
||||
@ -5531,21 +5538,19 @@ struct cs_info * get_current_cs(const char * es) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
return ccs;
|
||||
|
||||
rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
return ccs;
|
||||
encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?');
|
||||
rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
return ccs;
|
||||
decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
ccs = new cs_info[256];
|
||||
return ccs;
|
||||
|
||||
for (unsigned int i = 0; i <= 0xff; ++i) {
|
||||
bool success = false;
|
||||
|
@ -56,7 +56,7 @@ CXXFLAGS="$_SAVE_CXXFLAGS"
|
||||
|
||||
AC_LANG_RESTORE
|
||||
|
||||
if test "$ac_have_gcc_pr49911" == "yes"; then
|
||||
if test "$ac_have_gcc_pr49911" = "yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CFLAGS="$CFLAGS -fno-tree-vrp"
|
||||
CXXFLAGS="$CXXFLAGS -fno-tree-vrp"
|
||||
|
@ -1799,7 +1799,7 @@ if test "$GNU_CC"; then
|
||||
# Don't allow undefined symbols in libraries
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
|
||||
fi
|
||||
WARNINGS_AS_ERRORS='-Werror'
|
||||
WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
|
||||
DSO_CFLAGS=''
|
||||
DSO_PIC_CFLAGS='-fPIC'
|
||||
ASFLAGS="$ASFLAGS -fPIC"
|
||||
@ -2949,6 +2949,11 @@ if test "$ac_cv_header_endian_h" = yes; then
|
||||
AC_DEFINE(JS_HAVE_ENDIAN_H)
|
||||
fi
|
||||
|
||||
MOZ_CHECK_HEADERS([machine/endian.h],[],[],[#include <sys/types.h>])
|
||||
if test "$ac_cv_header_machine_endian_h" = yes; then
|
||||
AC_DEFINE(JS_HAVE_MACHINE_ENDIAN_H)
|
||||
fi
|
||||
|
||||
MOZ_CHECK_HEADERS(sys/isa_defs.h)
|
||||
if test "$ac_cv_header_sys_isa_defs_h" = yes; then
|
||||
AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -491,66 +491,6 @@ GenerateBlockId(TreeContext *tc, uint32_t &blockid);
|
||||
|
||||
} /* namespace frontend */
|
||||
|
||||
struct JumpTarget;
|
||||
|
||||
/*
|
||||
* Span-dependent instructions are jumps whose span (from the jump bytecode to
|
||||
* the jump target) may require 2 or 4 bytes of immediate operand.
|
||||
*/
|
||||
struct SpanDep {
|
||||
ptrdiff_t top; /* offset of first bytecode in an opcode */
|
||||
ptrdiff_t offset; /* offset - 1 within opcode of jump operand */
|
||||
ptrdiff_t before; /* original offset - 1 of jump operand */
|
||||
JumpTarget *target; /* tagged target pointer or backpatch delta */
|
||||
};
|
||||
|
||||
/*
|
||||
* Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
|
||||
* sorted by offset from left to right, so that targets after a span-dependent
|
||||
* instruction whose jump offset operand must be extended can be found quickly
|
||||
* and adjusted upward (toward higher offsets).
|
||||
*/
|
||||
struct JumpTarget {
|
||||
ptrdiff_t offset; /* offset of span-dependent jump target */
|
||||
int balance; /* AVL tree balance number */
|
||||
JumpTarget *kids[2]; /* left and right AVL tree child pointers */
|
||||
};
|
||||
|
||||
#define JT_LEFT 0
|
||||
#define JT_RIGHT 1
|
||||
#define JT_OTHER_DIR(dir) (1 - (dir))
|
||||
#define JT_IMBALANCE(dir) (((dir) << 1) - 1)
|
||||
#define JT_DIR(imbalance) (((imbalance) + 1) >> 1)
|
||||
|
||||
/*
|
||||
* Backpatch deltas are encoded in js::SpanDep::target if JT_TAG_BIT is clear,
|
||||
* so we can maintain backpatch chains when using span dependency records to
|
||||
* hold jump offsets that overflow 16 bits.
|
||||
*/
|
||||
#define JT_TAG_BIT ((jsword) 1)
|
||||
#define JT_UNTAG_SHIFT 1
|
||||
#define JT_SET_TAG(jt) ((JumpTarget *)((jsword)(jt) | JT_TAG_BIT))
|
||||
#define JT_CLR_TAG(jt) ((JumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
|
||||
#define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT)
|
||||
|
||||
#define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
|
||||
#define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
|
||||
#define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
|
||||
#define BPDELTA_TO_JT(bp) ((JumpTarget *)((bp) << JT_UNTAG_SHIFT))
|
||||
#define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
|
||||
|
||||
#define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt))
|
||||
#define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \
|
||||
JT_CLR_TAG((sd)->target))
|
||||
#define SD_SET_BPDELTA(sd,bp) ((sd)->target = BPDELTA_TO_JT(bp))
|
||||
#define SD_GET_BPDELTA(sd) (JS_ASSERT(!JT_HAS_TAG((sd)->target)), \
|
||||
JT_TO_BPDELTA((sd)->target))
|
||||
|
||||
/* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
|
||||
#define SD_SPAN(sd,pivot) (SD_GET_TARGET(sd) \
|
||||
? JT_CLR_TAG((sd)->target)->offset - (pivot) \
|
||||
: 0)
|
||||
|
||||
struct TryNode {
|
||||
JSTryNote note;
|
||||
TryNode *prev;
|
||||
@ -629,14 +569,6 @@ struct BytecodeEmitter : public TreeContext
|
||||
uintN ntrynotes; /* number of allocated so far try notes */
|
||||
TryNode *lastTryNode; /* the last allocated try node */
|
||||
|
||||
SpanDep *spanDeps; /* span dependent instruction records */
|
||||
JumpTarget *jumpTargets; /* AVL tree of jump target offsets */
|
||||
JumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */
|
||||
uintN numSpanDeps; /* number of span dependencies */
|
||||
uintN numJumpTargets; /* number of jump targets */
|
||||
ptrdiff_t spanDepTodo; /* offset from main.base of potentially
|
||||
unoptimized spandeps */
|
||||
|
||||
uintN arrayCompDepth; /* stack depth of array in comprehension */
|
||||
|
||||
uintN emitLevel; /* js::frontend::EmitTree recursion level */
|
||||
@ -801,29 +733,6 @@ Emit3(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1, jsbytecode o
|
||||
ptrdiff_t
|
||||
EmitN(JSContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra);
|
||||
|
||||
/*
|
||||
* Unsafe macro to call SetJumpOffset and return false if it does.
|
||||
*/
|
||||
#define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,bce,pc,off,BAD_EXIT) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!SetJumpOffset(cx, bce, pc, off)) { \
|
||||
BAD_EXIT; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define CHECK_AND_SET_JUMP_OFFSET(cx,bce,pc,off) \
|
||||
CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,bce,pc,off,return JS_FALSE)
|
||||
|
||||
#define CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx,bce,off,BAD_EXIT) \
|
||||
CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx, bce, (bce)->code(off), \
|
||||
bce->offset() - (off), BAD_EXIT)
|
||||
|
||||
#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,bce,off) \
|
||||
CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, bce, off, return JS_FALSE)
|
||||
|
||||
JSBool
|
||||
SetJumpOffset(JSContext *cx, BytecodeEmitter *bce, jsbytecode *pc, ptrdiff_t off);
|
||||
|
||||
/*
|
||||
* Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
|
||||
*/
|
||||
@ -921,10 +830,8 @@ EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body);
|
||||
* Note on adding new source notes: every pair of bytecodes (A, B) where A and
|
||||
* B have disjoint sets of source notes that could apply to each bytecode may
|
||||
* reuse the same note type value for two notes (snA, snB) that have the same
|
||||
* arity, offsetBias, and isSpanDep initializers in JSSrcNoteSpec. This is
|
||||
* why SRC_IF and SRC_INITPROP have the same value below. For bad historical
|
||||
* reasons, some bytecodes below that could be overlayed have not been, but
|
||||
* before using SRC_EXTENDED, consider compressing the existing note types.
|
||||
* arity in JSSrcNoteSpec. This is why SRC_IF and SRC_INITPROP have the same
|
||||
* value below.
|
||||
*
|
||||
* Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
|
||||
* incompatible source note or other bytecode changes.
|
||||
@ -976,18 +883,14 @@ enum SrcNoteType {
|
||||
SRC_SWITCHBREAK = 18, /* JSOP_GOTO is a break in a switch */
|
||||
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
|
||||
SRC_CATCH = 20, /* catch block has guard */
|
||||
SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */
|
||||
/* 21 is unused */
|
||||
SRC_NEWLINE = 22, /* bytecode follows a source newline */
|
||||
SRC_SETLINE = 23, /* a file-absolute source line number note */
|
||||
SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants for the SRC_DECL source note. Note that span-dependent bytecode
|
||||
* selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
|
||||
* to be adjusted, but these "offsets" are too small to span a span-dependent
|
||||
* instruction, so can be used to denote distinct declaration syntaxes to the
|
||||
* decompiler.
|
||||
* Constants for the SRC_DECL source note.
|
||||
*
|
||||
* NB: the var_prefix array in jsopcode.c depends on these dense indexes from
|
||||
* SRC_DECL_VAR through SRC_DECL_LET.
|
||||
@ -1137,9 +1040,6 @@ inline bool LetDataToGroupAssign(ptrdiff_t w)
|
||||
struct JSSrcNoteSpec {
|
||||
const char *name; /* name for disassembly/debugging output */
|
||||
int8_t arity; /* number of offset operands */
|
||||
uint8_t offsetBias; /* bias of offset(s) from annotated pc */
|
||||
int8_t isSpanDep; /* 1 or -1 if offsets could span extended ops,
|
||||
0 otherwise; sign tells span direction */
|
||||
};
|
||||
|
||||
extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
|
||||
|
@ -1,4 +1,4 @@
|
||||
// |jit-test| error: SyntaxError
|
||||
// |jit-test| error: TypeError
|
||||
Function("\n\
|
||||
for (a = 0; a < 3; a++) {\n\
|
||||
if (a == 0) {} else {\n\
|
||||
|
@ -7,14 +7,14 @@ function doNothing() { }
|
||||
function myparent(nested) {
|
||||
if (nested) {
|
||||
/* JSOP_CALL to doNothing in myparent with nested = true. */
|
||||
trap(myparent, 26, "success()");
|
||||
trap(myparent, 28, "success()");
|
||||
doNothing();
|
||||
} else {
|
||||
doNothing();
|
||||
}
|
||||
}
|
||||
/* JSOP_CALL to doNothing in myparent with nested = false. */
|
||||
trap(myparent, 37, "myparent(true)");
|
||||
trap(myparent, 41, "myparent(true)");
|
||||
|
||||
function success() {
|
||||
x = "success";
|
||||
|
@ -59,6 +59,10 @@
|
||||
useable. See jscpucfg.h. */
|
||||
#undef JS_HAVE_ENDIAN_H
|
||||
|
||||
/* Define to 1 if the <machine/endian.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
#undef JS_HAVE_MACHINE_ENDIAN_H
|
||||
|
||||
/* Define to 1 if the <sys/isa_defs.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
#undef JS_HAVE_SYS_ISA_DEFS_H
|
||||
|
@ -234,7 +234,7 @@ MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught excep
|
||||
MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference")
|
||||
MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses")
|
||||
MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range")
|
||||
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_SYNTAXERR, "invalid {0} usage")
|
||||
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_TYPEERR, "invalid {0} usage")
|
||||
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length")
|
||||
MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}")
|
||||
MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array")
|
||||
|
@ -141,21 +141,16 @@ BytecodeNoFallThrough(JSOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case JSOP_GOTO:
|
||||
case JSOP_GOTOX:
|
||||
case JSOP_DEFAULT:
|
||||
case JSOP_DEFAULTX:
|
||||
case JSOP_RETURN:
|
||||
case JSOP_STOP:
|
||||
case JSOP_RETRVAL:
|
||||
case JSOP_THROW:
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
case JSOP_FILTER:
|
||||
return true;
|
||||
case JSOP_GOSUB:
|
||||
case JSOP_GOSUBX:
|
||||
// these fall through indirectly, after executing a 'finally'.
|
||||
return false;
|
||||
default:
|
||||
@ -407,13 +402,10 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
hasFunctionCalls_ = true;
|
||||
break;
|
||||
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX: {
|
||||
case JSOP_TABLESWITCH: {
|
||||
isInlineable = false;
|
||||
jsbytecode *pc2 = pc;
|
||||
unsigned jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
unsigned defaultOffset = offset + GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
jsint low = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
jsint high = GET_JUMP_OFFSET(pc2);
|
||||
@ -425,25 +417,22 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
getCode(defaultOffset).safePoint = true;
|
||||
|
||||
for (jsint i = low; i <= high; i++) {
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc2);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
|
||||
if (targetOffset != offset) {
|
||||
if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, stackDepth))
|
||||
return;
|
||||
}
|
||||
getCode(targetOffset).switchTarget = true;
|
||||
getCode(targetOffset).safePoint = true;
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX: {
|
||||
case JSOP_LOOKUPSWITCH: {
|
||||
isInlineable = false;
|
||||
jsbytecode *pc2 = pc;
|
||||
unsigned jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
unsigned defaultOffset = offset + GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
unsigned npairs = GET_UINT16(pc2);
|
||||
pc2 += UINT16_LEN;
|
||||
|
||||
@ -454,12 +443,12 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
|
||||
while (npairs) {
|
||||
pc2 += INDEX_LEN;
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc2);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
|
||||
if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, stackDepth))
|
||||
return;
|
||||
getCode(targetOffset).switchTarget = true;
|
||||
getCode(targetOffset).safePoint = true;
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
npairs--;
|
||||
}
|
||||
break;
|
||||
@ -558,13 +547,12 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
uint32_t type = JOF_TYPE(js_CodeSpec[op].format);
|
||||
|
||||
/* Check basic jump opcodes, which may or may not have a fallthrough. */
|
||||
if (type == JOF_JUMP || type == JOF_JUMPX) {
|
||||
if (type == JOF_JUMP) {
|
||||
/* Some opcodes behave differently on their branching path. */
|
||||
unsigned newStackDepth = stackDepth;
|
||||
|
||||
switch (op) {
|
||||
case JSOP_CASE:
|
||||
case JSOP_CASEX:
|
||||
/* Case instructions do not push the lvalue back when branching. */
|
||||
newStackDepth--;
|
||||
break;
|
||||
@ -572,7 +560,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
default:;
|
||||
}
|
||||
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, newStackDepth))
|
||||
return;
|
||||
}
|
||||
@ -593,11 +581,11 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
}
|
||||
JS_ASSERT(nextcode->stackDepth == stackDepth);
|
||||
|
||||
if (type == JOF_JUMP || type == JOF_JUMPX)
|
||||
if (type == JOF_JUMP)
|
||||
nextcode->jumpFallthrough = true;
|
||||
|
||||
/* Treat the fallthrough of a branch instruction as a jump target. */
|
||||
if (type == JOF_JUMP || type == JOF_JUMPX)
|
||||
if (type == JOF_JUMP)
|
||||
nextcode->jumpTarget = true;
|
||||
else
|
||||
nextcode->fallthrough = true;
|
||||
@ -748,9 +736,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
||||
}
|
||||
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
/* Restore all saved variables. :FIXME: maybe do this precisely. */
|
||||
for (unsigned i = 0; i < savedCount; i++) {
|
||||
LifetimeVariable &var = *saved[i];
|
||||
@ -790,7 +776,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
||||
}
|
||||
|
||||
uint32_t type = JOF_TYPE(js_CodeSpec[op].format);
|
||||
if (type == JOF_JUMP || type == JOF_JUMPX) {
|
||||
if (type == JOF_JUMP) {
|
||||
/*
|
||||
* Forward jumps need to pull in all variables which are live at
|
||||
* their target offset --- the variables live before the jump are
|
||||
@ -852,8 +838,8 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
||||
|
||||
jsbytecode *entrypc = script->code + entry;
|
||||
|
||||
if (JSOp(*entrypc) == JSOP_GOTO || JSOp(*entrypc) == JSOP_GOTOX)
|
||||
loop->entry = entry + GetJumpOffset(entrypc, entrypc);
|
||||
if (JSOp(*entrypc) == JSOP_GOTO)
|
||||
loop->entry = entry + GET_JUMP_OFFSET(entrypc);
|
||||
else
|
||||
loop->entry = targetOffset;
|
||||
} else {
|
||||
@ -1431,12 +1417,9 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
||||
* and all case statements or exception/finally handlers.
|
||||
*/
|
||||
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX: {
|
||||
jsbytecode *pc2 = pc;
|
||||
unsigned jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
unsigned defaultOffset = offset + GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
case JSOP_TABLESWITCH: {
|
||||
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
jsint low = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
jsint high = GET_JUMP_OFFSET(pc2);
|
||||
@ -1445,20 +1428,17 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
||||
checkBranchTarget(cx, defaultOffset, branchTargets, values, stackDepth);
|
||||
|
||||
for (jsint i = low; i <= high; i++) {
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc2);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
|
||||
if (targetOffset != offset)
|
||||
checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth);
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX: {
|
||||
jsbytecode *pc2 = pc;
|
||||
unsigned jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
unsigned defaultOffset = offset + GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
case JSOP_LOOKUPSWITCH: {
|
||||
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
unsigned npairs = GET_UINT16(pc2);
|
||||
pc2 += UINT16_LEN;
|
||||
|
||||
@ -1466,9 +1446,9 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
||||
|
||||
while (npairs) {
|
||||
pc2 += INDEX_LEN;
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc2);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
|
||||
checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth);
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
npairs--;
|
||||
}
|
||||
break;
|
||||
@ -1495,7 +1475,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
||||
}
|
||||
|
||||
uint32_t type = JOF_TYPE(js_CodeSpec[op].format);
|
||||
if (type == JOF_JUMP || type == JOF_JUMPX) {
|
||||
if (type == JOF_JUMP) {
|
||||
unsigned targetOffset = FollowBranch(cx, script, offset);
|
||||
checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth);
|
||||
|
||||
|
@ -209,9 +209,7 @@ GetDefCount(JSScript *script, unsigned offset)
|
||||
*/
|
||||
switch (JSOp(*pc)) {
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
return 1;
|
||||
case JSOP_FILTER:
|
||||
return 2;
|
||||
@ -288,15 +286,6 @@ ExtendedUse(jsbytecode *pc)
|
||||
}
|
||||
}
|
||||
|
||||
static inline ptrdiff_t
|
||||
GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
|
||||
{
|
||||
uint32_t type = JOF_OPTYPE(*pc);
|
||||
if (JOF_TYPE_IS_EXTENDED_JUMP(type))
|
||||
return GET_JUMPX_OFFSET(pc2);
|
||||
return GET_JUMP_OFFSET(pc2);
|
||||
}
|
||||
|
||||
static inline JSOp
|
||||
ReverseCompareOp(JSOp op)
|
||||
{
|
||||
@ -324,12 +313,12 @@ FollowBranch(JSContext *cx, JSScript *script, unsigned offset)
|
||||
* inserted by the emitter.
|
||||
*/
|
||||
jsbytecode *pc = script->code + offset;
|
||||
unsigned targetOffset = offset + GetJumpOffset(pc, pc);
|
||||
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
if (targetOffset < offset) {
|
||||
jsbytecode *target = script->code + targetOffset;
|
||||
JSOp nop = JSOp(*target);
|
||||
if (nop == JSOP_GOTO || nop == JSOP_GOTOX)
|
||||
return targetOffset + GetJumpOffset(target, target);
|
||||
if (nop == JSOP_GOTO)
|
||||
return targetOffset + GET_JUMP_OFFSET(target);
|
||||
}
|
||||
return targetOffset;
|
||||
}
|
||||
|
@ -92,6 +92,23 @@
|
||||
# error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
|
||||
# endif
|
||||
|
||||
/* BSDs */
|
||||
#elif defined(JS_HAVE_MACHINE_ENDIAN_H)
|
||||
# include <sys/types.h>
|
||||
# include <machine/endian.h>
|
||||
|
||||
# if defined(_BYTE_ORDER)
|
||||
# if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# elif _BYTE_ORDER == _BIG_ENDIAN
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# endif
|
||||
# else /* !defined(_BYTE_ORDER) */
|
||||
# error "machine/endian.h does not define _BYTE_ORDER. Cannot determine endianness."
|
||||
# endif
|
||||
|
||||
#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
# include <sys/isa_defs.h>
|
||||
|
||||
|
@ -290,6 +290,7 @@ struct JSFunction : public JSObject
|
||||
inline JSAtom *methodAtom() const;
|
||||
inline void setMethodAtom(JSAtom *atom);
|
||||
|
||||
private:
|
||||
/*
|
||||
* These member functions are inherited from JSObject, but should never be applied to
|
||||
* a value statically known to be a JSFunction.
|
||||
|
@ -3207,9 +3207,7 @@ CheckNextTest(jsbytecode *pc)
|
||||
case JSOP_IFNE:
|
||||
case JSOP_NOT:
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
case JSOP_TYPEOF:
|
||||
case JSOP_TYPEOFEXPR:
|
||||
return true;
|
||||
@ -3402,11 +3400,8 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_NOP:
|
||||
case JSOP_LOOPHEAD:
|
||||
case JSOP_GOTO:
|
||||
case JSOP_GOTOX:
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFEQX:
|
||||
case JSOP_IFNE:
|
||||
case JSOP_IFNEX:
|
||||
case JSOP_LINENO:
|
||||
case JSOP_DEFCONST:
|
||||
case JSOP_LEAVEWITH:
|
||||
@ -3415,11 +3410,9 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_ENDITER:
|
||||
case JSOP_THROWING:
|
||||
case JSOP_GOSUB:
|
||||
case JSOP_GOSUBX:
|
||||
case JSOP_RETSUB:
|
||||
case JSOP_CONDSWITCH:
|
||||
case JSOP_DEFAULT:
|
||||
case JSOP_DEFAULTX:
|
||||
case JSOP_POPN:
|
||||
case JSOP_STARTXML:
|
||||
case JSOP_STARTXMLEXPR:
|
||||
@ -3435,12 +3428,9 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_DEBUGGER:
|
||||
case JSOP_SETCALL:
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
case JSOP_TRY:
|
||||
case JSOP_LABEL:
|
||||
case JSOP_LABELX:
|
||||
break;
|
||||
|
||||
/* Bytecodes pushing values of known type. */
|
||||
@ -3521,9 +3511,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
/* OR/AND push whichever operand determined the result. */
|
||||
poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
|
||||
break;
|
||||
@ -4053,7 +4041,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_CASE:
|
||||
case JSOP_CASEX:
|
||||
poppedTypes(pc, 1)->addSubset(cx, &pushed[0]);
|
||||
break;
|
||||
|
||||
@ -5440,9 +5427,7 @@ IgnorePushed(const jsbytecode *pc, unsigned index)
|
||||
|
||||
/* Value not determining result is not pushed by OR/AND. */
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
return (index == 0);
|
||||
|
||||
/* Holes tracked separately. */
|
||||
|
@ -1794,6 +1794,17 @@ ADD_EMPTY_CASE(JSOP_NOP)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED0)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED1)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED2)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED3)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED4)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED5)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED6)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED7)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED8)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED9)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED10)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED11)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED12)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED13)
|
||||
ADD_EMPTY_CASE(JSOP_CONDSWITCH)
|
||||
ADD_EMPTY_CASE(JSOP_TRY)
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
@ -1806,9 +1817,6 @@ END_EMPTY_CASES
|
||||
BEGIN_CASE(JSOP_LABEL)
|
||||
END_CASE(JSOP_LABEL)
|
||||
|
||||
BEGIN_CASE(JSOP_LABELX)
|
||||
END_CASE(JSOP_LABELX)
|
||||
|
||||
check_backedge:
|
||||
{
|
||||
CHECK_BRANCH();
|
||||
@ -2024,64 +2032,6 @@ BEGIN_CASE(JSOP_AND)
|
||||
}
|
||||
END_CASE(JSOP_AND)
|
||||
|
||||
BEGIN_CASE(JSOP_DEFAULTX)
|
||||
regs.sp--;
|
||||
/* FALL THROUGH */
|
||||
BEGIN_CASE(JSOP_GOTOX)
|
||||
{
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
BRANCH(len);
|
||||
}
|
||||
END_CASE(JSOP_GOTOX);
|
||||
|
||||
BEGIN_CASE(JSOP_IFEQX)
|
||||
{
|
||||
bool cond;
|
||||
Value *_;
|
||||
POP_BOOLEAN(cx, _, cond);
|
||||
if (cond == false) {
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
BRANCH(len);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_IFEQX)
|
||||
|
||||
BEGIN_CASE(JSOP_IFNEX)
|
||||
{
|
||||
bool cond;
|
||||
Value *_;
|
||||
POP_BOOLEAN(cx, _, cond);
|
||||
if (cond != false) {
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
BRANCH(len);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_IFNEX)
|
||||
|
||||
BEGIN_CASE(JSOP_ORX)
|
||||
{
|
||||
bool cond;
|
||||
Value *_;
|
||||
VALUE_TO_BOOLEAN(cx, _, cond);
|
||||
if (cond == true) {
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_ORX)
|
||||
|
||||
BEGIN_CASE(JSOP_ANDX)
|
||||
{
|
||||
bool cond;
|
||||
Value *_;
|
||||
VALUE_TO_BOOLEAN(cx, _, cond);
|
||||
if (cond == JS_FALSE) {
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_ANDX)
|
||||
|
||||
/*
|
||||
* If the index value at sp[n] is not an int that fits in a jsval, it could
|
||||
* be an object (an XML QName, AttributeName, or AnyName), but only if we are
|
||||
@ -2378,18 +2328,6 @@ BEGIN_CASE(JSOP_CASE)
|
||||
}
|
||||
END_CASE(JSOP_CASE)
|
||||
|
||||
BEGIN_CASE(JSOP_CASEX)
|
||||
{
|
||||
bool cond;
|
||||
STRICT_EQUALITY_OP(==, cond);
|
||||
if (cond) {
|
||||
regs.sp--;
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
BRANCH(len);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_CASEX)
|
||||
|
||||
#undef STRICT_EQUALITY_OP
|
||||
|
||||
#define RELATIONAL_OP(OP) \
|
||||
@ -3316,57 +3254,14 @@ END_VARLEN_CASE
|
||||
}
|
||||
|
||||
{
|
||||
BEGIN_CASE(JSOP_TABLESWITCHX)
|
||||
{
|
||||
jsbytecode *pc2 = regs.pc;
|
||||
len = GET_JUMPX_OFFSET(pc2);
|
||||
|
||||
/*
|
||||
* ECMAv2+ forbids conversion of discriminant, so we will skip to the
|
||||
* default case if the discriminant isn't already an int jsval. (This
|
||||
* opcode is emitted only for dense jsint-domain switches.)
|
||||
*/
|
||||
const Value &rref = *--regs.sp;
|
||||
int32_t i;
|
||||
if (rref.isInt32()) {
|
||||
i = rref.toInt32();
|
||||
} else if (rref.isDouble() && rref.toDouble() == 0) {
|
||||
/* Treat -0 (double) as 0. */
|
||||
i = 0;
|
||||
} else {
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
|
||||
pc2 += JUMPX_OFFSET_LEN;
|
||||
jsint low = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
jsint high = GET_JUMP_OFFSET(pc2);
|
||||
|
||||
i -= low;
|
||||
if ((jsuint)i < (jsuint)(high - low + 1)) {
|
||||
pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i;
|
||||
jsint off = (jsint) GET_JUMPX_OFFSET(pc2);
|
||||
if (off)
|
||||
len = off;
|
||||
}
|
||||
}
|
||||
END_VARLEN_CASE
|
||||
}
|
||||
|
||||
{
|
||||
BEGIN_CASE(JSOP_LOOKUPSWITCHX)
|
||||
BEGIN_CASE(JSOP_LOOKUPSWITCH)
|
||||
{
|
||||
jsint off;
|
||||
off = JUMPX_OFFSET_LEN;
|
||||
goto do_lookup_switch;
|
||||
|
||||
BEGIN_CASE(JSOP_LOOKUPSWITCH)
|
||||
off = JUMP_OFFSET_LEN;
|
||||
|
||||
do_lookup_switch:
|
||||
/*
|
||||
* JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if any atom
|
||||
* index in it would exceed 64K limit.
|
||||
* JSOP_LOOKUPSWITCH are never used if any atom index in it would exceed
|
||||
* 64K limit.
|
||||
*/
|
||||
JS_ASSERT(atoms == script->atoms);
|
||||
jsbytecode *pc2 = regs.pc;
|
||||
@ -3421,9 +3316,7 @@ BEGIN_CASE(JSOP_LOOKUPSWITCH)
|
||||
#undef SEARCH_PAIRS
|
||||
|
||||
end_lookup_switch:
|
||||
len = (op == JSOP_LOOKUPSWITCH)
|
||||
? GET_JUMP_OFFSET(pc2)
|
||||
: GET_JUMPX_OFFSET(pc2);
|
||||
len = GET_JUMP_OFFSET(pc2);
|
||||
}
|
||||
END_VARLEN_CASE
|
||||
}
|
||||
@ -4199,16 +4092,7 @@ END_CASE(JSOP_SHARPINIT)
|
||||
BEGIN_CASE(JSOP_GOSUB)
|
||||
PUSH_BOOLEAN(false);
|
||||
jsint i = (regs.pc - script->code) + JSOP_GOSUB_LENGTH;
|
||||
PUSH_INT32(i);
|
||||
len = GET_JUMP_OFFSET(regs.pc);
|
||||
END_VARLEN_CASE
|
||||
}
|
||||
|
||||
{
|
||||
BEGIN_CASE(JSOP_GOSUBX)
|
||||
PUSH_BOOLEAN(false);
|
||||
jsint i = (regs.pc - script->code) + JSOP_GOSUBX_LENGTH;
|
||||
len = GET_JUMPX_OFFSET(regs.pc);
|
||||
PUSH_INT32(i);
|
||||
END_VARLEN_CASE
|
||||
}
|
||||
|
@ -1589,72 +1589,62 @@ const char js_defineSetter_str[] = "__defineSetter__";
|
||||
const char js_lookupGetter_str[] = "__lookupGetter__";
|
||||
const char js_lookupSetter_str[] = "__lookupSetter__";
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js::obj_defineGetter(JSContext *cx, uintN argc, Value *vp)
|
||||
enum DefineType { Getter, Setter };
|
||||
|
||||
template<DefineType Type>
|
||||
static bool
|
||||
DefineAccessor(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!BoxNonStrictThis(cx, args))
|
||||
return false;
|
||||
JSObject *obj = &args.thisv().toObject();
|
||||
|
||||
if (args.length() <= 1 || !js_IsCallable(args[1])) {
|
||||
if (args.length() < 2 || !js_IsCallable(args[1])) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_GETTER_OR_SETTER,
|
||||
js_getter_str);
|
||||
return JS_FALSE;
|
||||
Type == Getter ? js_getter_str : js_setter_str);
|
||||
return false;
|
||||
}
|
||||
PropertyOp getter = CastAsPropertyOp(&args[1].toObject());
|
||||
|
||||
jsid id;
|
||||
if (!ValueToId(cx, args[0], &id))
|
||||
return JS_FALSE;
|
||||
if (!CheckRedeclaration(cx, obj, id, JSPROP_GETTER))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
* Getters and setters are just like watchpoints from an access
|
||||
* control point of view.
|
||||
*/
|
||||
Value junk;
|
||||
uintN attrs;
|
||||
if (!CheckAccess(cx, obj, id, JSACC_WATCH, &junk, &attrs))
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
JSObject *descObj = NewBuiltinClassInstance(cx, &ObjectClass);
|
||||
if (!descObj)
|
||||
return false;
|
||||
|
||||
JSAtomState &state = cx->runtime->atomState;
|
||||
/* enumerable: true */
|
||||
if (!descObj->defineProperty(cx, state.enumerableAtom, BooleanValue(true)))
|
||||
return false;
|
||||
|
||||
/* configurable: true */
|
||||
if (!descObj->defineProperty(cx, state.configurableAtom, BooleanValue(true)))
|
||||
return false;
|
||||
|
||||
/* enumerable: true */
|
||||
PropertyName *acc = (Type == Getter) ? state.getAtom : state.setAtom;
|
||||
if (!descObj->defineProperty(cx, acc, args[1]))
|
||||
return false;
|
||||
|
||||
JSBool dummy;
|
||||
if (!js_DefineOwnProperty(cx, &args.thisv().toObject(), id, ObjectValue(*descObj), &dummy))
|
||||
return false;
|
||||
args.rval().setUndefined();
|
||||
return obj->defineGeneric(cx, id, UndefinedValue(), getter, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js::obj_defineGetter(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return DefineAccessor<Getter>(cx, argc, vp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js::obj_defineSetter(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!BoxNonStrictThis(cx, args))
|
||||
return false;
|
||||
JSObject *obj = &args.thisv().toObject();
|
||||
|
||||
if (args.length() <= 1 || !js_IsCallable(args[1])) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_GETTER_OR_SETTER,
|
||||
js_setter_str);
|
||||
return JS_FALSE;
|
||||
}
|
||||
StrictPropertyOp setter = CastAsStrictPropertyOp(&args[1].toObject());
|
||||
|
||||
jsid id;
|
||||
if (!ValueToId(cx, args[0], &id))
|
||||
return JS_FALSE;
|
||||
if (!CheckRedeclaration(cx, obj, id, JSPROP_SETTER))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
* Getters and setters are just like watchpoints from an access
|
||||
* control point of view.
|
||||
*/
|
||||
Value junk;
|
||||
uintN attrs;
|
||||
if (!CheckAccess(cx, obj, id, JSACC_WATCH, &junk, &attrs))
|
||||
return JS_FALSE;
|
||||
args.rval().setUndefined();
|
||||
return obj->defineGeneric(cx, id, UndefinedValue(), JS_PropertyStub, setter,
|
||||
JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED);
|
||||
return DefineAccessor<Setter>(cx, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -145,17 +145,6 @@ Dup(const char *chars, DupBuffer *cb)
|
||||
return cb->append(chars, strlen(chars) + 1);
|
||||
}
|
||||
|
||||
static ptrdiff_t
|
||||
GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
|
||||
{
|
||||
uint32_t type;
|
||||
|
||||
type = JOF_OPTYPE(*pc);
|
||||
if (JOF_TYPE_IS_EXTENDED_JUMP(type))
|
||||
return GET_JUMPX_OFFSET(pc2);
|
||||
return GET_JUMP_OFFSET(pc2);
|
||||
}
|
||||
|
||||
uintN
|
||||
js_GetIndexFromBytecode(JSScript *script, jsbytecode *pc, ptrdiff_t pcoff)
|
||||
{
|
||||
@ -185,37 +174,27 @@ js_GetIndexFromBytecode(JSScript *script, jsbytecode *pc, ptrdiff_t pcoff)
|
||||
size_t
|
||||
js_GetVariableBytecodeLength(jsbytecode *pc)
|
||||
{
|
||||
uintN jmplen, ncases;
|
||||
uintN ncases;
|
||||
jsint low, high;
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
JS_ASSERT(js_CodeSpec[op].length == -1);
|
||||
switch (op) {
|
||||
case JSOP_TABLESWITCHX:
|
||||
jmplen = JUMPX_OFFSET_LEN;
|
||||
goto do_table;
|
||||
case JSOP_TABLESWITCH:
|
||||
jmplen = JUMP_OFFSET_LEN;
|
||||
do_table:
|
||||
/* Structure: default-jump case-low case-high case1-jump ... */
|
||||
pc += jmplen;
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
low = GET_JUMP_OFFSET(pc);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
high = GET_JUMP_OFFSET(pc);
|
||||
ncases = (uintN)(high - low + 1);
|
||||
return 1 + jmplen + INDEX_LEN + INDEX_LEN + ncases * jmplen;
|
||||
return 1 + 3 * JUMP_OFFSET_LEN + ncases * JUMP_OFFSET_LEN;
|
||||
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
jmplen = JUMPX_OFFSET_LEN;
|
||||
goto do_lookup;
|
||||
default:
|
||||
JS_ASSERT(op == JSOP_LOOKUPSWITCH);
|
||||
jmplen = JUMP_OFFSET_LEN;
|
||||
do_lookup:
|
||||
/* Structure: default-jump case-count (case1-value case1-jump) ... */
|
||||
pc += jmplen;
|
||||
JS_ASSERT(op == JSOP_LOOKUPSWITCH);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
ncases = GET_UINT16(pc);
|
||||
return 1 + jmplen + INDEX_LEN + ncases * (INDEX_LEN + jmplen);
|
||||
return 1 + JUMP_OFFSET_LEN + INDEX_LEN + ncases * (INDEX_LEN + JUMP_OFFSET_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,9 +564,8 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
}
|
||||
break;
|
||||
|
||||
case JOF_JUMP:
|
||||
case JOF_JUMPX: {
|
||||
ptrdiff_t off = GetJumpOffset(pc, pc);
|
||||
case JOF_JUMP: {
|
||||
ptrdiff_t off = GET_JUMP_OFFSET(pc);
|
||||
Sprint(sp, " %u (%+d)", loc + (intN) off, (intN) off);
|
||||
break;
|
||||
}
|
||||
@ -628,47 +606,39 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
}
|
||||
|
||||
case JOF_TABLESWITCH:
|
||||
case JOF_TABLESWITCHX:
|
||||
{
|
||||
jsbytecode *pc2;
|
||||
jsint i, low, high;
|
||||
|
||||
ptrdiff_t jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
pc2 = pc;
|
||||
ptrdiff_t off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
ptrdiff_t off = GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
low = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
high = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
Sprint(sp, " defaultOffset %d low %d high %d", intN(off), low, high);
|
||||
for (i = low; i <= high; i++) {
|
||||
off = GetJumpOffset(pc, pc2);
|
||||
off = GET_JUMP_OFFSET(pc2);
|
||||
Sprint(sp, "\n\t%d: %d", i, intN(off));
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
}
|
||||
len = 1 + pc2 - pc;
|
||||
break;
|
||||
}
|
||||
|
||||
case JOF_LOOKUPSWITCH:
|
||||
case JOF_LOOKUPSWITCHX:
|
||||
{
|
||||
jsbytecode *pc2;
|
||||
jsatomid npairs;
|
||||
|
||||
ptrdiff_t jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
pc2 = pc;
|
||||
ptrdiff_t off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
ptrdiff_t off = GET_JUMP_OFFSET(pc);
|
||||
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
|
||||
npairs = GET_UINT16(pc2);
|
||||
pc2 += UINT16_LEN;
|
||||
Sprint(sp, " offset %d npairs %u", intN(off), uintN(npairs));
|
||||
while (npairs) {
|
||||
uint16_t constIndex = GET_INDEX(pc2);
|
||||
pc2 += INDEX_LEN;
|
||||
off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
off = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
|
||||
JSAutoByteString bytes;
|
||||
if (!ToDisassemblySource(cx, script->getConst(constIndex), &bytes))
|
||||
@ -2386,10 +2356,10 @@ SprintNormalFor(JSContext *cx, JSPrinter *jp, SprintStack *ss, const char *initP
|
||||
*/
|
||||
jsbytecode *pc2 = pc;
|
||||
if (cond != tail) {
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
||||
pc2 += (*pc == JSOP_GOTO) ? JSOP_GOTO_LENGTH : JSOP_GOTOX_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO);
|
||||
pc2 += JSOP_GOTO_LENGTH;
|
||||
}
|
||||
LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == pc2 - pc);
|
||||
LOCAL_ASSERT(tail + GET_JUMP_OFFSET(pc + tail) == pc2 - pc);
|
||||
|
||||
if (cond != tail) {
|
||||
/* Decompile the loop condition. */
|
||||
@ -2823,8 +2793,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
/* Second instruction (TRACE) contains offset to JSOP_IFNE */
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
tail = js_GetSrcNoteOffset(sn, 0);
|
||||
LOCAL_ASSERT(pc[tail] == JSOP_IFNE ||
|
||||
pc[tail] == JSOP_IFNEX);
|
||||
LOCAL_ASSERT(pc[tail] == JSOP_IFNE);
|
||||
js_printf(jp, "\tdo {\n");
|
||||
jp->indent += 4;
|
||||
DECOMPILE_CODE(pc, tail);
|
||||
@ -2880,7 +2849,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
break;
|
||||
|
||||
case JSOP_LABEL:
|
||||
case JSOP_LABELX:
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
todo = -2;
|
||||
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
||||
@ -2947,11 +2915,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
break;
|
||||
|
||||
case JSOP_GOSUB:
|
||||
case JSOP_GOSUBX:
|
||||
/*
|
||||
* JSOP_GOSUB and GOSUBX have no effect on the decompiler's
|
||||
* string stack because the next op in bytecode order finds
|
||||
* the stack balanced by a JSOP_RETSUB executed elsewhere.
|
||||
* JSOP_GOSUB has no effect on the decompiler's string stack
|
||||
* because the next op in bytecode order finds the stack
|
||||
* balanced by a JSOP_RETSUB executed elsewhere.
|
||||
*/
|
||||
todo = -2;
|
||||
break;
|
||||
@ -3276,7 +3243,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
return NULL;
|
||||
js_printf(jp, "%s", POP_STR());
|
||||
pc += len;
|
||||
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
|
||||
LOCAL_ASSERT(*pc == JSOP_IFEQ);
|
||||
pc += js_CodeSpec[*pc].length;
|
||||
}
|
||||
|
||||
@ -3466,12 +3433,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
LOCAL_ASSERT(js_GetSrcNote(jp->script, pc) == NULL);
|
||||
LOCAL_ASSERT(ss->top - 1 == blockObj.stackDepth() + blockObj.slotCount());
|
||||
jsbytecode *nextpc = pc + JSOP_ENTERLET1_LENGTH;
|
||||
if (*nextpc == JSOP_GOTO || *nextpc == JSOP_GOTOX) {
|
||||
if (*nextpc == JSOP_GOTO) {
|
||||
LOCAL_ASSERT(SN_TYPE(js_GetSrcNote(jp->script, nextpc)) == SRC_FOR_IN);
|
||||
} else {
|
||||
LOCAL_ASSERT(*nextpc == JSOP_CONDSWITCH ||
|
||||
*nextpc == JSOP_TABLESWITCH || *nextpc == JSOP_TABLESWITCHX ||
|
||||
*nextpc == JSOP_LOOKUPSWITCH || *nextpc == JSOP_LOOKUPSWITCHX);
|
||||
*nextpc == JSOP_TABLESWITCH ||
|
||||
*nextpc == JSOP_LOOKUPSWITCH);
|
||||
}
|
||||
|
||||
DupBuffer rhs(cx);
|
||||
@ -3781,7 +3748,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
break;
|
||||
|
||||
case JSOP_GOTO:
|
||||
case JSOP_GOTOX:
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
||||
case SRC_FOR_IN:
|
||||
@ -3813,7 +3779,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
* JSOP_MOREITER or JSOP_IFNE, though we do quick asserts
|
||||
* to check that they are there.
|
||||
*/
|
||||
cond = GetJumpOffset(pc, pc);
|
||||
cond = GET_JUMP_OFFSET(pc);
|
||||
next = js_GetSrcNoteOffset(sn, 0);
|
||||
tail = js_GetSrcNoteOffset(sn, 1);
|
||||
JS_ASSERT(pc[next] == JSOP_POP);
|
||||
@ -3871,12 +3837,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
}
|
||||
|
||||
pc += tail;
|
||||
LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
|
||||
LOCAL_ASSERT(*pc == JSOP_IFNE);
|
||||
len = js_CodeSpec[*pc].length;
|
||||
break;
|
||||
|
||||
case SRC_WHILE:
|
||||
cond = GetJumpOffset(pc, pc);
|
||||
cond = GET_JUMP_OFFSET(pc);
|
||||
tail = js_GetSrcNoteOffset(sn, 0);
|
||||
DECOMPILE_CODE(pc + cond, tail - cond);
|
||||
js_printf(jp, "\twhile (");
|
||||
@ -3888,7 +3854,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}\n");
|
||||
pc += tail;
|
||||
LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
|
||||
LOCAL_ASSERT(*pc == JSOP_IFNE);
|
||||
len = js_CodeSpec[*pc].length;
|
||||
todo = -2;
|
||||
break;
|
||||
@ -3926,12 +3892,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
break;
|
||||
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFEQX:
|
||||
{
|
||||
JSBool elseif = JS_FALSE;
|
||||
|
||||
if_again:
|
||||
len = GetJumpOffset(pc, pc);
|
||||
len = GET_JUMP_OFFSET(pc);
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
|
||||
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
||||
@ -3959,9 +3924,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
||||
jp->indent -= 4;
|
||||
pc += tail;
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO);
|
||||
oplen = js_CodeSpec[*pc].length;
|
||||
len = GetJumpOffset(pc, pc);
|
||||
len = GET_JUMP_OFFSET(pc);
|
||||
js_printf(jp, "\t} else");
|
||||
|
||||
/*
|
||||
@ -4001,9 +3966,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
lval = PopStrDupe(ss, op, &lvalpc);
|
||||
pushpc = pc;
|
||||
pc += len;
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO);
|
||||
oplen = js_CodeSpec[*pc].length;
|
||||
len = GetJumpOffset(pc, pc);
|
||||
len = GET_JUMP_OFFSET(pc);
|
||||
DECOMPILE_CODE(pc + oplen, len - oplen);
|
||||
rval = PopStrDupe(ss, op, &rvalpc);
|
||||
todo = ss->sprinter.offset;
|
||||
@ -4021,18 +3986,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
}
|
||||
|
||||
case JSOP_IFNE:
|
||||
case JSOP_IFNEX:
|
||||
LOCAL_ASSERT(0);
|
||||
break;
|
||||
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
xval = "||";
|
||||
|
||||
do_logical_connective:
|
||||
/* Top of stack is the first clause in a disjunction (||). */
|
||||
lval = PopStrDupe(ss, op, &lvalpc);
|
||||
done = pc + GetJumpOffset(pc, pc);
|
||||
done = pc + GET_JUMP_OFFSET(pc);
|
||||
pushpc = pc;
|
||||
pc += len;
|
||||
JS_ASSERT(*pc == JSOP_POP);
|
||||
@ -4056,7 +4019,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
break;
|
||||
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
xval = "&&";
|
||||
goto do_logical_connective;
|
||||
|
||||
@ -4847,19 +4809,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
goto sprint_string;
|
||||
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
{
|
||||
ptrdiff_t jmplen, off, off2;
|
||||
ptrdiff_t off, off2;
|
||||
jsint j, n, low, high;
|
||||
TableEntry *table, *tmp;
|
||||
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
|
||||
len = js_GetSrcNoteOffset(sn, 0);
|
||||
jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN;
|
||||
pc2 = pc;
|
||||
off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
off = GET_JUMP_OFFSET(pc);
|
||||
pc2 = pc + JUMP_OFFSET_LEN;
|
||||
low = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
high = GET_JUMP_OFFSET(pc2);
|
||||
@ -4877,7 +4836,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
return NULL;
|
||||
for (i = j = 0; i < n; i++) {
|
||||
table[j].label = NULL;
|
||||
off2 = GetJumpOffset(pc, pc2);
|
||||
off2 = GET_JUMP_OFFSET(pc2);
|
||||
if (off2) {
|
||||
sn = js_GetSrcNote(jp->script, pc2);
|
||||
if (sn) {
|
||||
@ -4889,7 +4848,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
table[j].order = j;
|
||||
j++;
|
||||
}
|
||||
pc2 += jmplen;
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
}
|
||||
tmp = (TableEntry *)
|
||||
cx->malloc_((size_t)j * sizeof *table);
|
||||
@ -4912,20 +4871,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
}
|
||||
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
{
|
||||
ptrdiff_t jmplen, off, off2;
|
||||
ptrdiff_t off, off2;
|
||||
jsatomid npairs, k;
|
||||
TableEntry *table;
|
||||
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
|
||||
len = js_GetSrcNoteOffset(sn, 0);
|
||||
jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
|
||||
: JUMPX_OFFSET_LEN;
|
||||
pc2 = pc;
|
||||
off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
off = GET_JUMP_OFFSET(pc);
|
||||
pc2 = pc + JUMP_OFFSET_LEN;
|
||||
npairs = GET_UINT16(pc2);
|
||||
pc2 += UINT16_LEN;
|
||||
|
||||
@ -4943,8 +4898,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
}
|
||||
uint16_t constIndex = GET_INDEX(pc2);
|
||||
pc2 += INDEX_LEN;
|
||||
off2 = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
off2 = GET_JUMP_OFFSET(pc2);
|
||||
pc2 += JUMP_OFFSET_LEN;
|
||||
table[k].key = jp->script->getConst(constIndex);
|
||||
table[k].offset = off2;
|
||||
}
|
||||
@ -4977,9 +4932,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
off2 = off;
|
||||
for (ncases = 0; off2 != 0; ncases++) {
|
||||
pc2 += off2;
|
||||
LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
|
||||
*pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
|
||||
if (*pc2 == JSOP_DEFAULT || *pc2 == JSOP_DEFAULTX) {
|
||||
LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);
|
||||
if (*pc2 == JSOP_DEFAULT) {
|
||||
/* End of cases, but count default as a case. */
|
||||
off2 = 0;
|
||||
} else {
|
||||
@ -5002,12 +4956,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
off2 = off;
|
||||
for (i = 0; i < ncases; i++) {
|
||||
pc2 += off2;
|
||||
LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
|
||||
*pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
|
||||
LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);
|
||||
caseOff = pc2 - pc;
|
||||
table[i].key = INT_TO_JSVAL((jsint) caseOff);
|
||||
table[i].offset = caseOff + GetJumpOffset(pc2, pc2);
|
||||
if (*pc2 == JSOP_CASE || *pc2 == JSOP_CASEX) {
|
||||
table[i].offset = caseOff + GET_JUMP_OFFSET(pc2);
|
||||
if (*pc2 == JSOP_CASE) {
|
||||
sn = js_GetSrcNote(jp->script, pc2);
|
||||
LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
|
||||
off2 = js_GetSrcNoteOffset(sn, 0);
|
||||
@ -5021,7 +4974,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
*/
|
||||
off = JSVAL_TO_INT(table[ncases-1].key);
|
||||
pc2 = pc + off;
|
||||
off += GetJumpOffset(pc2, pc2);
|
||||
off += GET_JUMP_OFFSET(pc2);
|
||||
|
||||
ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
|
||||
JS_TRUE);
|
||||
@ -5033,7 +4986,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
}
|
||||
|
||||
case JSOP_CASE:
|
||||
case JSOP_CASEX:
|
||||
{
|
||||
lval = PopStr(ss, op, &lvalpc);
|
||||
if (!lval)
|
||||
@ -5773,8 +5725,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
||||
JSOp op = (JSOp) *pc;
|
||||
|
||||
/* None of these stack-writing ops generates novel values. */
|
||||
JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
|
||||
op != JSOP_DUP && op != JSOP_DUP2);
|
||||
JS_ASSERT(op != JSOP_CASE && op != JSOP_DUP && op != JSOP_DUP2);
|
||||
|
||||
/*
|
||||
* |this| could convert to a very long object initialiser, so cite it by
|
||||
@ -5897,7 +5848,6 @@ SimulateOp(JSContext *cx, JSScript *script, JSOp op, const JSCodeSpec *cs,
|
||||
break;
|
||||
|
||||
case JSOP_CASE:
|
||||
case JSOP_CASEX:
|
||||
/* Keep the switch value. */
|
||||
JS_ASSERT(ndefs == 1);
|
||||
break;
|
||||
@ -5961,9 +5911,9 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||
/*
|
||||
* A (C ? T : E) expression requires skipping either T (if target is in
|
||||
* E) or both T and E (if target is after the whole expression) before
|
||||
* adjusting pcdepth based on the JSOP_IFEQ or JSOP_IFEQX at pc that
|
||||
* tests condition C. We know that the stack depth can't change from
|
||||
* what it was with C on top of stack.
|
||||
* adjusting pcdepth based on the JSOP_IFEQ at pc that tests condition
|
||||
* C. We know that the stack depth can't change from what it was with
|
||||
* C on top of stack.
|
||||
*/
|
||||
jssrcnote *sn = js_GetSrcNote(script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_COND) {
|
||||
@ -5971,11 +5921,11 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||
if (pc + jmpoff < target) {
|
||||
pc += jmpoff;
|
||||
op = JSOp(*pc);
|
||||
JS_ASSERT(op == JSOP_GOTO || op == JSOP_GOTOX);
|
||||
JS_ASSERT(op == JSOP_GOTO);
|
||||
cs = &js_CodeSpec[op];
|
||||
oplen = cs->length;
|
||||
JS_ASSERT(oplen > 0);
|
||||
ptrdiff_t jmplen = GetJumpOffset(pc, pc);
|
||||
ptrdiff_t jmplen = GET_JUMP_OFFSET(pc);
|
||||
if (pc + jmplen < target) {
|
||||
oplen = (uintN) jmplen;
|
||||
continue;
|
||||
|
@ -83,9 +83,6 @@ typedef enum JSOp {
|
||||
#define JOF_QARG 6 /* quickened get/set function argument ops */
|
||||
#define JOF_LOCAL 7 /* var or block-local variable */
|
||||
#define JOF_SLOTATOM 8 /* uint16_t slot + constant index */
|
||||
#define JOF_JUMPX 9 /* signed 32-bit jump offset immediate */
|
||||
#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
|
||||
#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
|
||||
#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */
|
||||
#define JOF_UINT8 13 /* uint8_t immediate, e.g. top 8 bits of 24-bit
|
||||
atom index */
|
||||
@ -148,7 +145,7 @@ typedef enum JSOp {
|
||||
#define JOF_OPMODE(op) JOF_MODE(js_CodeSpec[op].format)
|
||||
|
||||
#define JOF_TYPE_IS_EXTENDED_JUMP(t) \
|
||||
((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
|
||||
((unsigned)((t) - JOF_JUMP) <= (unsigned)(JOF_LOOKUPSWITCH - JOF_JUMP))
|
||||
|
||||
/*
|
||||
* Immediate operand getters, setters, and bounds.
|
||||
@ -162,48 +159,25 @@ typedef enum JSOp {
|
||||
#define SET_UINT16(pc,i) ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
|
||||
#define UINT16_LIMIT ((uintN)1 << 16)
|
||||
|
||||
/* Short (2-byte signed offset) relative jump macros. */
|
||||
#define JUMP_OFFSET_LEN 2
|
||||
#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8))
|
||||
#define JUMP_OFFSET_LO(off) ((jsbytecode)(off))
|
||||
#define GET_JUMP_OFFSET(pc) (int16_t(GET_UINT16(pc)))
|
||||
#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \
|
||||
(pc)[2] = JUMP_OFFSET_LO(off))
|
||||
#define JUMP_OFFSET_MIN ((int16_t)0x8000)
|
||||
#define JUMP_OFFSET_MAX ((int16_t)0x7fff)
|
||||
/* Helpers for accessing the offsets of jump opcodes. */
|
||||
#define JUMP_OFFSET_LEN 4
|
||||
#define JUMP_OFFSET_MIN INT32_MIN
|
||||
#define JUMP_OFFSET_MAX INT32_MAX
|
||||
|
||||
/*
|
||||
* When a short jump won't hold a relative offset, its 2-byte immediate offset
|
||||
* operand is an unsigned index of a span-dependency record, maintained until
|
||||
* code generation finishes -- after which some (but we hope not nearly all)
|
||||
* span-dependent jumps must be extended (see js::frontend::OptimizeSpanDeps in
|
||||
* frontend/BytecodeEmitter.cpp).
|
||||
*
|
||||
* If the span-dependency record index overflows SPANDEP_INDEX_MAX, the jump
|
||||
* offset will contain SPANDEP_INDEX_HUGE, indicating that the record must be
|
||||
* found (via binary search) by its "before span-dependency optimization" pc
|
||||
* offset (from script main entry point).
|
||||
*/
|
||||
#define GET_SPANDEP_INDEX(pc) (uint16_t(GET_UINT16(pc)))
|
||||
#define SET_SPANDEP_INDEX(pc,i) ((pc)[1] = JUMP_OFFSET_HI(i), \
|
||||
(pc)[2] = JUMP_OFFSET_LO(i))
|
||||
#define SPANDEP_INDEX_MAX ((uint16_t)0xfffe)
|
||||
#define SPANDEP_INDEX_HUGE ((uint16_t)0xffff)
|
||||
static JS_ALWAYS_INLINE int32_t
|
||||
GET_JUMP_OFFSET(jsbytecode *pc)
|
||||
{
|
||||
return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
|
||||
}
|
||||
|
||||
/* Ultimately, if short jumps won't do, emit long (4-byte signed) offsets. */
|
||||
#define JUMPX_OFFSET_LEN 4
|
||||
#define JUMPX_OFFSET_B3(off) ((jsbytecode)((off) >> 24))
|
||||
#define JUMPX_OFFSET_B2(off) ((jsbytecode)((off) >> 16))
|
||||
#define JUMPX_OFFSET_B1(off) ((jsbytecode)((off) >> 8))
|
||||
#define JUMPX_OFFSET_B0(off) ((jsbytecode)(off))
|
||||
#define GET_JUMPX_OFFSET(pc) (int32_t(((pc)[1] << 24) | ((pc)[2] << 16) \
|
||||
| ((pc)[3] << 8) | (pc)[4]))
|
||||
#define SET_JUMPX_OFFSET(pc,off)((pc)[1] = JUMPX_OFFSET_B3(off), \
|
||||
(pc)[2] = JUMPX_OFFSET_B2(off), \
|
||||
(pc)[3] = JUMPX_OFFSET_B1(off), \
|
||||
(pc)[4] = JUMPX_OFFSET_B0(off))
|
||||
#define JUMPX_OFFSET_MIN (int32_t(0x80000000))
|
||||
#define JUMPX_OFFSET_MAX (int32_t(0x7fffffff))
|
||||
static JS_ALWAYS_INLINE void
|
||||
SET_JUMP_OFFSET(jsbytecode *pc, int32_t off)
|
||||
{
|
||||
pc[1] = (jsbytecode)(off >> 24);
|
||||
pc[2] = (jsbytecode)(off >> 16);
|
||||
pc[3] = (jsbytecode)(off >> 8);
|
||||
pc[4] = (jsbytecode)off;
|
||||
}
|
||||
|
||||
/*
|
||||
* A literal is indexed by a per-script atom or object maps. Most scripts
|
||||
@ -532,7 +506,7 @@ FlowsIntoNext(JSOp op)
|
||||
{
|
||||
/* JSOP_YIELD is considered to flow into the next instruction, like JSOP_CALL. */
|
||||
return op != JSOP_STOP && op != JSOP_RETURN && op != JSOP_RETRVAL && op != JSOP_THROW &&
|
||||
op != JSOP_GOTO && op != JSOP_GOTOX && op != JSOP_RETSUB;
|
||||
op != JSOP_GOTO && op != JSOP_RETSUB;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -658,7 +632,7 @@ class OpcodeCounts
|
||||
return counts[which];
|
||||
}
|
||||
|
||||
// Boolean conversion, for 'if (counters) ...'
|
||||
/* Boolean conversion, for 'if (counters) ...' */
|
||||
operator void*() const {
|
||||
return counts;
|
||||
}
|
||||
|
@ -70,9 +70,9 @@
|
||||
* 2 , JSOP_POP with SRC_PCDELTA, JSOP_RETURN
|
||||
* 3 =, +=, etc. JSOP_SETNAME, etc. (all JOF_SET);
|
||||
* let (...) ... and JSOP_LEAVEBLOCKEXPR
|
||||
* 4 ?: JSOP_IFEQ, JSOP_IFEQX
|
||||
* 5 || JSOP_OR, JSOP_ORX
|
||||
* 6 && JSOP_AND, JSOP_ANDX
|
||||
* 4 ?: JSOP_IFEQ
|
||||
* 5 || JSOP_OR
|
||||
* 6 && JSOP_AND
|
||||
* 7 | JSOP_BITOR
|
||||
* 8 ^ JSOP_BITXOR
|
||||
* 9 & JSOP_BITAND
|
||||
@ -118,9 +118,9 @@ OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_GOTO, 6, "goto", NULL, 3, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 3, 1, 0, 4, JOF_JUMP|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_GOTO, 6, "goto", NULL, 5, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 5, 1, 0, 4, JOF_JUMP|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFNE, 8, "ifne", NULL, 5, 1, 0, 0, JOF_JUMP|JOF_PARENHEAD)
|
||||
|
||||
/* Get the arguments object for the current, lightweight function activation. */
|
||||
OPDEF(JSOP_ARGUMENTS, 9, js_arguments_str, js_arguments_str, 1, 0, 1, 18, JOF_BYTE)
|
||||
@ -187,11 +187,11 @@ OPDEF(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_THIS, 65, js_this_str, js_this_str, 1, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_OR, 68, "or", NULL, 3, 1, 1, 5, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
|
||||
OPDEF(JSOP_AND, 69, "and", NULL, 3, 1, 1, 6, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
|
||||
OPDEF(JSOP_OR, 68, "or", NULL, 5, 1, 1, 5, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
|
||||
OPDEF(JSOP_AND, 69, "and", NULL, 5, 1, 1, 6, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
|
||||
|
||||
/* The switch bytecodes have variable length. */
|
||||
OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH|JOF_DETECTING|JOF_PARENHEAD)
|
||||
|
||||
/* New, infallible/transitive identity ops. */
|
||||
@ -211,7 +211,7 @@ OPDEF(JSOP_SETCALL, 74, "setcall", NULL, 1, 1, 2, 18, JOF_BYTE)
|
||||
*
|
||||
* JSOP_MOREITER stores the next iterated value into cx->iterValue and pushes
|
||||
* true if another value is available, and false otherwise. It is followed
|
||||
* immediately by JSOP_IFNE{,X}.
|
||||
* immediately by JSOP_IFNE.
|
||||
*
|
||||
* JSOP_ENDITER cleans up after the loop. It uses the slot above the iterator
|
||||
* for temporary GC rooting.
|
||||
@ -275,8 +275,8 @@ OPDEF(JSOP_LOCALDEC, 104,"localdec", NULL, 3, 0, 1, 15, JOF_LOCAL|
|
||||
OPDEF(JSOP_LEAVEFORLETIN, 105,"leaveforletin",NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* The argument is the offset to the next statement and is used by IonMonkey. */
|
||||
OPDEF(JSOP_LABEL, 106,"label", NULL, 3, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_LABELX, 107,"labelx", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_LABEL, 106,"label", NULL, 5, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_UNUSED3, 107,"unused3", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */
|
||||
OPDEF(JSOP_FUNCALL, 108,"funcall", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
|
||||
@ -299,7 +299,7 @@ OPDEF(JSOP_INSTANCEOF,114,js_instanceof_str,js_instanceof_str,1,2,1,11,JOF_BYTE|
|
||||
OPDEF(JSOP_DEBUGGER, 115,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* gosub/retsub for finally handling */
|
||||
OPDEF(JSOP_GOSUB, 116,"gosub", NULL, 3, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_GOSUB, 116,"gosub", NULL, 5, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_RETSUB, 117,"retsub", NULL, 1, 2, 0, 0, JOF_BYTE)
|
||||
|
||||
/* More exception handling ops. */
|
||||
@ -314,8 +314,8 @@ OPDEF(JSOP_LINENO, 119,"lineno", NULL, 3, 0, 0, 0, JOF_UINT16
|
||||
* lval if false; and DEFAULT is POP lval and GOTO.
|
||||
*/
|
||||
OPDEF(JSOP_CONDSWITCH,120,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_CASE, 121,"case", NULL, 3, 2, 1, 0, JOF_JUMP|JOF_TMPSLOT2)
|
||||
OPDEF(JSOP_DEFAULT, 122,"default", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_CASE, 121,"case", NULL, 5, 2, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_DEFAULT, 122,"default", NULL, 5, 1, 0, 0, JOF_JUMP)
|
||||
|
||||
/*
|
||||
* ECMA-compliant call to eval op
|
||||
@ -380,20 +380,20 @@ OPDEF(JSOP_CALLFCSLOT, 137,"callfcslot", NULL, 3, 0, 1, 19, JOF_UINT16
|
||||
OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
|
||||
|
||||
/* Extended jumps. */
|
||||
OPDEF(JSOP_GOTOX, 139,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_IFEQX, 140,"ifeqx", NULL, 5, 1, 0, 4, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFNEX, 141,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_ORX, 142,"orx", NULL, 5, 1, 1, 5, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_ANDX, 143,"andx", NULL, 5, 1, 1, 6, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_GOSUBX, 144,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_CASEX, 145,"casex", NULL, 5, 2, 1, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_DEFAULTX, 146,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_TABLESWITCHX, 147,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LOOKUPSWITCHX, 148,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_UNUSED4, 139,"unused4", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED5, 140,"unused5", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED6, 141,"unused6", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED7, 142,"unused7", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED8, 143,"unused8", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED9, 144,"unused9", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED10, 145,"unused10", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED11, 146,"unused11", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED12, 147,"unused12", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED13, 148,"unused13", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Placeholders for a real jump opcode set during backpatch chain fixup. */
|
||||
OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 5, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 5, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
|
||||
/* Set pending exception from the stack, to trigger rethrow. */
|
||||
OPDEF(JSOP_THROWING, 151,"throwing", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
@ -427,8 +427,8 @@ OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|J
|
||||
OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE)
|
||||
OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 3, 2, 1, 18, JOF_JUMP)
|
||||
OPDEF(JSOP_FILTER, 174,"filter", NULL, 5, 1, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 5, 2, 1, 18, JOF_JUMP)
|
||||
OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
|
@ -341,6 +341,8 @@ class BaseShape : public js::gc::Cell
|
||||
/* Not defined: BaseShapes must not be stack allocated. */
|
||||
~BaseShape();
|
||||
|
||||
inline BaseShape &operator=(const BaseShape &other);
|
||||
|
||||
bool isOwned() const { return !!(flags & OWNED_SHAPE); }
|
||||
|
||||
inline bool matchesGetterSetter(PropertyOp rawGetter,
|
||||
|
@ -112,6 +112,28 @@ BaseShape::BaseShape(const StackBaseShape &base)
|
||||
}
|
||||
}
|
||||
|
||||
inline BaseShape &
|
||||
BaseShape::operator=(const BaseShape &other)
|
||||
{
|
||||
clasp = other.clasp;
|
||||
parent = other.parent;
|
||||
flags = other.flags;
|
||||
slotSpan_ = other.slotSpan_;
|
||||
if (flags & HAS_GETTER_OBJECT) {
|
||||
getterObj = other.getterObj;
|
||||
JSObject::writeBarrierPost(getterObj, &getterObj);
|
||||
} else {
|
||||
rawGetter = other.rawGetter;
|
||||
}
|
||||
if (flags & HAS_SETTER_OBJECT) {
|
||||
setterObj = other.setterObj;
|
||||
JSObject::writeBarrierPost(setterObj, &setterObj);
|
||||
} else {
|
||||
rawSetter = other.rawSetter;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool
|
||||
BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter) const
|
||||
{
|
||||
|
@ -1646,7 +1646,6 @@ mjit::Compiler::generateMethod()
|
||||
END_CASE(JSOP_RETURN)
|
||||
|
||||
BEGIN_CASE(JSOP_GOTO)
|
||||
BEGIN_CASE(JSOP_GOTOX)
|
||||
BEGIN_CASE(JSOP_DEFAULT)
|
||||
{
|
||||
unsigned targetOffset = FollowBranch(cx, script, PC - script->code);
|
||||
@ -1681,10 +1680,8 @@ mjit::Compiler::generateMethod()
|
||||
|
||||
BEGIN_CASE(JSOP_IFEQ)
|
||||
BEGIN_CASE(JSOP_IFNE)
|
||||
BEGIN_CASE(JSOP_IFEQX)
|
||||
BEGIN_CASE(JSOP_IFNEX)
|
||||
{
|
||||
jsbytecode *target = PC + GetJumpOffset(PC, PC);
|
||||
jsbytecode *target = PC + GET_JUMP_OFFSET(PC);
|
||||
fixDoubleTypes(target);
|
||||
if (!jsop_ifneq(op, target))
|
||||
return Compile_Error;
|
||||
@ -2148,7 +2145,6 @@ mjit::Compiler::generateMethod()
|
||||
END_CASE(JSOP_AND)
|
||||
|
||||
BEGIN_CASE(JSOP_TABLESWITCH)
|
||||
BEGIN_CASE(JSOP_TABLESWITCHX)
|
||||
/*
|
||||
* Note: there is no need to syncForBranch for the various targets of
|
||||
* switch statement. The liveness analysis has already marked these as
|
||||
@ -2224,11 +2220,9 @@ mjit::Compiler::generateMethod()
|
||||
updatePCCounters(PC, &codeStart, &countersUpdated);
|
||||
jsbytecode *target = &PC[JSOP_MOREITER_LENGTH];
|
||||
JSOp next = JSOp(*target);
|
||||
JS_ASSERT(next == JSOP_IFNE || next == JSOP_IFNEX);
|
||||
JS_ASSERT(next == JSOP_IFNE);
|
||||
|
||||
target += (next == JSOP_IFNE)
|
||||
? GET_JUMP_OFFSET(target)
|
||||
: GET_JUMPX_OFFSET(target);
|
||||
target += GET_JUMP_OFFSET(target);
|
||||
|
||||
fixDoubleTypes(target);
|
||||
if (!iterMore(target))
|
||||
@ -2487,9 +2481,6 @@ mjit::Compiler::generateMethod()
|
||||
BEGIN_CASE(JSOP_LABEL)
|
||||
END_CASE(JSOP_LABEL)
|
||||
|
||||
BEGIN_CASE(JSOP_LABELX)
|
||||
END_CASE(JSOP_LABELX)
|
||||
|
||||
BEGIN_CASE(JSOP_DEFFUN)
|
||||
{
|
||||
uint32_t index = fullAtomIndex(PC);
|
||||
@ -6795,11 +6786,10 @@ mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
|
||||
#else
|
||||
jsbytecode *originalPC = pc;
|
||||
JSOp op = JSOp(*originalPC);
|
||||
JS_ASSERT(op == JSOP_TABLESWITCH || op == JSOP_TABLESWITCHX);
|
||||
JS_ASSERT(op == JSOP_TABLESWITCH);
|
||||
|
||||
uint32_t defaultTarget = GetJumpOffset(pc, pc);
|
||||
unsigned jumpLength = (op == JSOP_TABLESWITCHX) ? JUMPX_OFFSET_LEN : JUMP_OFFSET_LEN;
|
||||
pc += jumpLength;
|
||||
uint32_t defaultTarget = GET_JUMP_OFFSET(pc);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
|
||||
jsint low = GET_JUMP_OFFSET(pc);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
@ -6851,12 +6841,12 @@ mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
|
||||
jumpTables.append(jt);
|
||||
|
||||
for (int i = 0; i < numJumps; i++) {
|
||||
uint32_t target = GetJumpOffset(originalPC, pc);
|
||||
uint32_t target = GET_JUMP_OFFSET(pc);
|
||||
if (!target)
|
||||
target = defaultTarget;
|
||||
uint32_t offset = (originalPC + target) - script->code;
|
||||
jumpTableOffsets.append(offset);
|
||||
pc += jumpLength;
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
}
|
||||
if (low != 0)
|
||||
masm.sub32(Imm32(low), dataReg);
|
||||
|
@ -729,7 +729,7 @@ private:
|
||||
static inline Assembler::Condition
|
||||
GetStubCompareCondition(JSOp fused)
|
||||
{
|
||||
return (fused == JSOP_IFEQ) ? Assembler::Zero : Assembler::NonZero;
|
||||
return fused == JSOP_IFEQ ? Assembler::Zero : Assembler::NonZero;
|
||||
}
|
||||
|
||||
/* Fast builtins. */
|
||||
|
@ -789,13 +789,12 @@ mjit::Compiler::booleanJumpScript(JSOp op, jsbytecode *target)
|
||||
if (op == JSOP_AND || op == JSOP_OR) {
|
||||
frame.syncForBranch(target, Uses(0));
|
||||
} else {
|
||||
JS_ASSERT(op == JSOP_IFEQ || op == JSOP_IFEQX ||
|
||||
op == JSOP_IFNE || op == JSOP_IFNEX);
|
||||
JS_ASSERT(op == JSOP_IFEQ || op == JSOP_IFNE);
|
||||
frame.syncForBranch(target, Uses(1));
|
||||
}
|
||||
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
Assembler::Condition cond = (op == JSOP_IFNE || op == JSOP_IFNEX || op == JSOP_OR)
|
||||
Assembler::Condition cond = (op == JSOP_IFNE || op == JSOP_OR)
|
||||
? Assembler::NonZero
|
||||
: Assembler::Zero;
|
||||
|
||||
@ -859,7 +858,7 @@ mjit::Compiler::jsop_ifneq(JSOp op, jsbytecode *target)
|
||||
|
||||
frame.pop();
|
||||
|
||||
if (op == JSOP_IFEQ || op == JSOP_IFEQX)
|
||||
if (op == JSOP_IFEQ)
|
||||
b = !b;
|
||||
if (b) {
|
||||
if (!frame.syncForBranch(target, Uses(0)))
|
||||
|
@ -1054,18 +1054,16 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
bool takeBranch = false;
|
||||
switch (JSOp(*nextpc)) {
|
||||
case JSOP_IFNE:
|
||||
case JSOP_IFNEX:
|
||||
takeBranch = returnReg != NULL;
|
||||
break;
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFEQX:
|
||||
takeBranch = returnReg == NULL;
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Bad branch op");
|
||||
}
|
||||
if (takeBranch)
|
||||
f.regs.pc = nextpc + analyze::GetJumpOffset(nextpc, nextpc);
|
||||
f.regs.pc = nextpc + GET_JUMP_OFFSET(nextpc);
|
||||
else
|
||||
f.regs.pc = nextpc + GetBytecodeLength(nextpc);
|
||||
break;
|
||||
|
@ -1921,15 +1921,10 @@ LoopState::analyzeLoopBody(unsigned frame)
|
||||
case JSOP_LOCALINC:
|
||||
case JSOP_LOCALDEC:
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFEQX:
|
||||
case JSOP_IFNE:
|
||||
case JSOP_IFNEX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_GOTO:
|
||||
case JSOP_GOTOX:
|
||||
break;
|
||||
|
||||
case JSOP_ADD:
|
||||
|
@ -1555,15 +1555,13 @@ void * JS_FASTCALL
|
||||
stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
|
||||
{
|
||||
jsbytecode * const originalPC = origPc;
|
||||
jsbytecode *pc = originalPC;
|
||||
|
||||
JSOp op = JSOp(*originalPC);
|
||||
JS_ASSERT(op == JSOP_TABLESWITCH || op == JSOP_TABLESWITCHX);
|
||||
|
||||
uint32_t jumpOffset = js::analyze::GetJumpOffset(originalPC, pc);
|
||||
unsigned jumpLength = (op == JSOP_TABLESWITCHX) ? JUMPX_OFFSET_LEN : JUMP_OFFSET_LEN;
|
||||
pc += jumpLength;
|
||||
JS_ASSERT(op == JSOP_TABLESWITCH);
|
||||
|
||||
uint32_t jumpOffset = GET_JUMP_OFFSET(originalPC);
|
||||
jsbytecode *pc = originalPC + JUMP_OFFSET_LEN;
|
||||
|
||||
/* Note: compiler adjusts the stack beforehand. */
|
||||
Value rval = f.regs.sp[-1];
|
||||
|
||||
@ -1590,9 +1588,8 @@ stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
|
||||
|
||||
tableIdx -= low;
|
||||
if ((jsuint) tableIdx < (jsuint)(high - low + 1)) {
|
||||
pc += jumpLength * tableIdx;
|
||||
uint32_t candidateOffset = js::analyze::GetJumpOffset(originalPC, pc);
|
||||
if (candidateOffset)
|
||||
pc += JUMP_OFFSET_LEN * tableIdx;
|
||||
if (uint32_t candidateOffset = GET_JUMP_OFFSET(pc))
|
||||
jumpOffset = candidateOffset;
|
||||
}
|
||||
}
|
||||
|
@ -1827,12 +1827,8 @@ UpdateSwitchTableBounds(JSContext *cx, JSScript *script, uintN offset,
|
||||
pc = script->code + offset;
|
||||
op = JSOp(*pc);
|
||||
switch (op) {
|
||||
case JSOP_TABLESWITCHX:
|
||||
jmplen = JUMPX_OFFSET_LEN;
|
||||
goto jump_table;
|
||||
case JSOP_TABLESWITCH:
|
||||
jmplen = JUMP_OFFSET_LEN;
|
||||
jump_table:
|
||||
pc += jmplen;
|
||||
low = GET_JUMP_OFFSET(pc);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
@ -1841,12 +1837,8 @@ UpdateSwitchTableBounds(JSContext *cx, JSScript *script, uintN offset,
|
||||
n = high - low + 1;
|
||||
break;
|
||||
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
jmplen = JUMPX_OFFSET_LEN;
|
||||
goto lookup_table;
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
jmplen = JUMP_OFFSET_LEN;
|
||||
lookup_table:
|
||||
pc += jmplen;
|
||||
n = GET_INDEX(pc);
|
||||
pc += INDEX_LEN;
|
||||
@ -1885,7 +1877,7 @@ SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp)
|
||||
name = "case";
|
||||
} else {
|
||||
JSOp op = JSOp(script->code[offset]);
|
||||
JS_ASSERT(op == JSOP_LABEL || op == JSOP_LABELX);
|
||||
JS_ASSERT(op == JSOP_LABEL);
|
||||
}
|
||||
}
|
||||
Sprint(sp, "%3u: %4u %5u [%4u] %-8s", uintN(sn - notes), lineno, offset, delta, name);
|
||||
@ -1944,7 +1936,7 @@ SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp)
|
||||
}
|
||||
case SRC_SWITCH: {
|
||||
JSOp op = JSOp(script->code[offset]);
|
||||
if (op == JSOP_GOTO || op == JSOP_GOTOX)
|
||||
if (op == JSOP_GOTO)
|
||||
break;
|
||||
Sprint(sp, " length %u", uintN(js_GetSrcNoteOffset(sn, 0)));
|
||||
uintN caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
|
||||
|
@ -98,7 +98,7 @@ function test()
|
||||
|
||||
try
|
||||
{
|
||||
expect = 'TypeError: redeclaration of const 5';
|
||||
expect = "TypeError: can't redefine non-configurable property '5'";
|
||||
"012345".__defineSetter__(5, function(){});
|
||||
}
|
||||
catch(ex)
|
||||
|
@ -111,7 +111,6 @@ script regress-646820-1.js
|
||||
script regress-646820-2.js
|
||||
script regress-646820-3.js
|
||||
script regress-665355.js
|
||||
script regress-666599.js
|
||||
script regress-667047.js
|
||||
script regress-672892.js
|
||||
script regress-672893.js
|
||||
|
@ -1,15 +0,0 @@
|
||||
var o1 = {};
|
||||
var o2 = new ArrayBuffer();
|
||||
o2.__defineGetter__('x', function() {return 42;})
|
||||
o1.__proto__ = o2
|
||||
assertEq(o1['x'], 42);
|
||||
|
||||
var t1 = {};
|
||||
var t2 = new ArrayBuffer();
|
||||
var t3 = new ArrayBuffer();
|
||||
t3.__defineGetter__('x', function() {return 42;})
|
||||
t2.__proto__ = t3;
|
||||
t1.__proto__ = t2;
|
||||
assertEq(t1['x'], 42);
|
||||
|
||||
reportCompare(true, true);
|
@ -2129,22 +2129,16 @@ class FlowGraphSummary : public Vector<size_t> {
|
||||
|
||||
if (js_CodeSpec[op].type() == JOF_JUMP) {
|
||||
addEdge(lineno, r.frontOffset() + GET_JUMP_OFFSET(r.frontPC()));
|
||||
} else if (js_CodeSpec[op].type() == JOF_JUMPX) {
|
||||
addEdge(lineno, r.frontOffset() + GET_JUMPX_OFFSET(r.frontPC()));
|
||||
} else if (op == JSOP_TABLESWITCH || op == JSOP_TABLESWITCHX ||
|
||||
op == JSOP_LOOKUPSWITCH || op == JSOP_LOOKUPSWITCHX) {
|
||||
bool table = op == JSOP_TABLESWITCH || op == JSOP_TABLESWITCHX;
|
||||
bool big = op == JSOP_TABLESWITCHX || op == JSOP_LOOKUPSWITCHX;
|
||||
|
||||
} else if (op == JSOP_TABLESWITCH || op == JSOP_LOOKUPSWITCH) {
|
||||
jsbytecode *pc = r.frontPC();
|
||||
size_t offset = r.frontOffset();
|
||||
ptrdiff_t step = big ? JUMPX_OFFSET_LEN : JUMP_OFFSET_LEN;
|
||||
size_t defaultOffset = offset + (big ? GET_JUMPX_OFFSET(pc) : GET_JUMP_OFFSET(pc));
|
||||
ptrdiff_t step = JUMP_OFFSET_LEN;
|
||||
size_t defaultOffset = offset + GET_JUMP_OFFSET(pc);
|
||||
pc += step;
|
||||
addEdge(lineno, defaultOffset);
|
||||
|
||||
jsint ncases;
|
||||
if (table) {
|
||||
if (op == JSOP_TABLESWITCH) {
|
||||
jsint low = GET_JUMP_OFFSET(pc);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
ncases = GET_JUMP_OFFSET(pc) - low + 1;
|
||||
@ -2156,9 +2150,9 @@ class FlowGraphSummary : public Vector<size_t> {
|
||||
}
|
||||
|
||||
for (jsint i = 0; i < ncases; i++) {
|
||||
if (!table)
|
||||
if (op == JSOP_LOOKUPSWITCH)
|
||||
pc += INDEX_LEN;
|
||||
size_t target = offset + (big ? GET_JUMPX_OFFSET(pc) : GET_JUMP_OFFSET(pc));
|
||||
size_t target = offset + GET_JUMP_OFFSET(pc);
|
||||
addEdge(lineno, target);
|
||||
pc += step;
|
||||
}
|
||||
|
@ -504,6 +504,8 @@ irregularFilenames = {
|
||||
|
||||
'nsIDOMTouch': 'nsIDOMTouchEvent',
|
||||
'nsIDOMTouchList': 'nsIDOMTouchEvent',
|
||||
|
||||
'nsITelephoneCallback': 'nsITelephone',
|
||||
}
|
||||
|
||||
customIncludes = [
|
||||
|
@ -129,10 +129,14 @@
|
||||
using mozilla::dom::indexedDB::IndexedDatabaseManager;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "RadioManager.h"
|
||||
using mozilla::dom::telephony::RadioManager;
|
||||
#include "nsITelephone.h"
|
||||
#include "SystemWorkerManager.h"
|
||||
using mozilla::dom::telephony::SystemWorkerManager;
|
||||
#define SYSTEMWORKERMANAGER_CID \
|
||||
{0xd53b6524, 0x6ac3, 0x42b0, {0xae, 0xca, 0x62, 0xb3, 0xc4, 0xe5, 0x2b, 0x04}}
|
||||
#define SYSTEMWORKERMANAGER_CONTRACTID \
|
||||
"@mozilla.org/telephony/system-worker-manager;1"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "AudioManager.h"
|
||||
using mozilla::dom::telephony::AudioManager;
|
||||
@ -279,29 +283,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsChannelPolicy)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(IndexedDatabaseManager,
|
||||
IndexedDatabaseManager::FactoryCreate)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(RadioManager, RadioManager::FactoryCreate)
|
||||
|
||||
// The 'RadioManager' class controls the lifetime of the nsITelephonyWorker
|
||||
// object which is also an nsITelephone, so we don't want to register it
|
||||
// as a global service on app-startup. Instead, we'll (ab)use createInstance()
|
||||
// to always return the one singleton that 'RadioManager' holds on to.
|
||||
static nsresult
|
||||
RadioInterfaceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
if (NULL != aOuter) {
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITelephone> inst = RadioManager::GetTelephone();
|
||||
if (NULL == inst) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*aResult = inst.get();
|
||||
inst.forget();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SystemWorkerManager,
|
||||
SystemWorkerManager::FactoryCreate)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -771,8 +754,7 @@ NS_DEFINE_NAMED_CID(NS_DOMJSON_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
|
||||
NS_DEFINE_NAMED_CID(INDEXEDDB_MANAGER_CID);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DEFINE_NAMED_CID(TELEPHONYRADIO_CID);
|
||||
NS_DEFINE_NAMED_CID(TELEPHONYRADIOINTERFACE_CID);
|
||||
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_DEFINE_NAMED_CID(NS_AUDIOMANAGER_CID);
|
||||
@ -1044,8 +1026,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
{ &kNS_TEXTEDITOR_CID, false, NULL, nsPlaintextEditorConstructor },
|
||||
{ &kINDEXEDDB_MANAGER_CID, false, NULL, IndexedDatabaseManagerConstructor },
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{ &kTELEPHONYRADIO_CID, true, NULL, RadioManagerConstructor },
|
||||
{ &kTELEPHONYRADIOINTERFACE_CID, true, NULL, RadioInterfaceConstructor },
|
||||
{ &kSYSTEMWORKERMANAGER_CID, true, NULL, SystemWorkerManagerConstructor },
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ &kNS_AUDIOMANAGER_CID, true, NULL, AudioManagerConstructor },
|
||||
@ -1182,8 +1163,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID },
|
||||
{ INDEXEDDB_MANAGER_CONTRACTID, &kINDEXEDDB_MANAGER_CID },
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{ TELEPHONYRADIO_CONTRACTID, &kTELEPHONYRADIO_CID },
|
||||
{ TELEPHONYRADIOINTERFACE_CONTRACTID, &kTELEPHONYRADIOINTERFACE_CID },
|
||||
{ SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID },
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ NS_AUDIOMANAGER_CONTRACTID, &kNS_AUDIOMANAGER_CID },
|
||||
@ -1245,11 +1225,8 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
|
||||
{ JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY, "PrivilegeManager", NS_SECURITYNAMESET_CONTRACTID },
|
||||
{ "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID },
|
||||
CONTENTDLF_CATEGORIES
|
||||
|
||||
// This probably should be "app-startup" but we want our testing extension to
|
||||
// be able to override the contractid so we wait until "profile-after-change"
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{ "profile-after-change", "Telephony Radio", TELEPHONYRADIO_CONTRACTID },
|
||||
{ "profile-after-change", "Telephony System Worker Manager", SYSTEMWORKERMANAGER_CONTRACTID },
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
|
21
layout/reftests/columns/columnfill-overflow-style-ref.html
Normal file
21
layout/reftests/columns/columnfill-overflow-style-ref.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 715203: Multicolumn support in scrolled columns</title>
|
||||
<style>
|
||||
.columns {
|
||||
font-size: 12pt;
|
||||
line-height: 1.1;
|
||||
-moz-column-width: 40em;
|
||||
-moz-column-fill: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="columns">
|
||||
<li>one
|
||||
<li>two
|
||||
<li>three
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
22
layout/reftests/columns/columnfill-overflow-style.html
Normal file
22
layout/reftests/columns/columnfill-overflow-style.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 715203: Multicolumn support in scrolled columns</title>
|
||||
<style>
|
||||
.columns {
|
||||
font-size: 12pt;
|
||||
line-height: 1.1;
|
||||
-moz-column-width: 40em;
|
||||
-overflow-x:auto;
|
||||
-moz-column-fill: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="columns">
|
||||
<li>one
|
||||
<li>two
|
||||
<li>three
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -16,10 +16,15 @@
|
||||
== column-balancing-002.html column-balancing-002.ref.html
|
||||
== column-balancing-003.html column-balancing-000.ref.html
|
||||
== column-balancing-004.html column-balancing-004.ref.html
|
||||
|
||||
# These next tests need to be a http tests because they use the ahem font,
|
||||
# located in layout/reftests/fonts.
|
||||
HTTP(..) == columnfill-balance.html columnfill-balance-ref.html
|
||||
HTTP(..) == columnfill-auto.html columnfill-auto-ref.html
|
||||
HTTP(..) == columnfill-change.html columnfill-change-ref.html
|
||||
|
||||
== columnrule-basic.html columnrule-basic-ref.html
|
||||
== columnrule-complex.html columnrule-complex-ref.html
|
||||
!= columnrule-linestyles.html columnrule-linestyles-notref.html
|
||||
== columnrule-padding.html columnrule-padding-ref.html
|
||||
== columnfill-overflow-style.html columnfill-overflow-style-ref.html
|
||||
|
@ -162,6 +162,7 @@
|
||||
-moz-column-width: inherit;
|
||||
-moz-column-gap: inherit;
|
||||
-moz-column-rule: inherit;
|
||||
-moz-column-fill: inherit;
|
||||
/* Do not change these. nsCSSFrameConstructor depends on them to create a good
|
||||
frame tree. */
|
||||
position: static !important;
|
||||
|
@ -44,6 +44,7 @@ import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
import android.database.sqlite.SQLiteConstraintException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
@ -51,8 +52,10 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.Browser;
|
||||
import android.provider.Browser.BookmarkColumns;
|
||||
import android.util.Log;
|
||||
|
||||
public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
private static final String LOGTAG = "AndroidBrowserDB";
|
||||
private static final String URL_COLUMN_ID = "_id";
|
||||
private static final String URL_COLUMN_THUMBNAIL = "thumbnail";
|
||||
|
||||
@ -286,8 +289,19 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
Browser.BookmarkColumns.URL + " = ?",
|
||||
new String[] { uri });
|
||||
|
||||
if (updated == 0)
|
||||
cr.insert(Browser.BOOKMARKS_URI, values);
|
||||
if (updated == 0) {
|
||||
try {
|
||||
cr.insert(Browser.BOOKMARKS_URI, values);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
// insert() mysteriously and intermittently fails with "error
|
||||
// code 19: constraint failed" on some Honeycomb and ICS
|
||||
// devices. Bookmark favicons are not a critical feature, so
|
||||
// we can ignore this error for now. bug 711977; bug 712791
|
||||
Log.e(LOGTAG,
|
||||
String.format("Inserting favicon for \"%s\" failed with SQLiteConstraintException: %s",
|
||||
uri, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateThumbnailForUrl(ContentResolver cr, String uri,
|
||||
|
@ -37,7 +37,10 @@
|
||||
<!ENTITY sync.subtitle.success.label 'Your data is now being downloaded in the background. You can go to Settings to manage your account.'>
|
||||
<!ENTITY sync.settings.label 'Settings'>
|
||||
<!ENTITY sync.subtitle.manage.label 'Your &syncBrand.fullName.label; account is already set up. Go to Settings to manage your account.'>
|
||||
|
||||
|
||||
<!-- Pair Device -->
|
||||
<!ENTITY sync.pair.tryagain.label 'Please try again.'>
|
||||
|
||||
<!-- Common text -->
|
||||
<!ENTITY sync.button.cancel.label 'Cancel'>
|
||||
<!ENTITY sync.button.connect.label 'Connect'>
|
||||
|
@ -3713,6 +3713,8 @@ var PermissionsHelper = {
|
||||
Services.logins.setLoginSavingEnabled(aURI.prePath, true);
|
||||
} else {
|
||||
Services.perms.remove(aURI.host, aType);
|
||||
// Clear content prefs set in ContentPermissionPrompt.js
|
||||
Services.contentPrefs.removePref(aURI, aType + ".request.remember");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,7 @@ Sanitizer.prototype = {
|
||||
cookies: {
|
||||
clear: function ()
|
||||
{
|
||||
var cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
|
||||
cookieMgr.removeAll();
|
||||
Services.cookies.removeAll();
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -130,9 +129,6 @@ Sanitizer.prototype = {
|
||||
try {
|
||||
var branch = Services.prefs.getBranch("geo.wifi.access_token.");
|
||||
branch.deleteBranch("");
|
||||
|
||||
branch = Services.prefs.getBranch("geo.request.remember.");
|
||||
branch.deleteBranch("");
|
||||
} catch (e) {dump(e);}
|
||||
},
|
||||
|
||||
@ -149,15 +145,13 @@ Sanitizer.prototype = {
|
||||
Services.perms.removeAll();
|
||||
|
||||
// Clear site-specific settings like page-zoom level
|
||||
var cps = Cc["@mozilla.org/content-pref/service;1"].getService(Ci.nsIContentPrefService);
|
||||
cps.removeGroupedPrefs();
|
||||
Services.contentPrefs.removeGroupedPrefs();
|
||||
|
||||
// Clear "Never remember passwords for this site", which is not handled by
|
||||
// the permission manager
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
var hosts = pwmgr.getAllDisabledHosts({})
|
||||
var hosts = Services.logins.getAllDisabledHosts({})
|
||||
for each (var host in hosts) {
|
||||
pwmgr.setLoginSavingEnabled(host, true);
|
||||
Services.logins.setLoginSavingEnabled(host, true);
|
||||
}
|
||||
},
|
||||
|
||||
@ -252,14 +246,12 @@ Sanitizer.prototype = {
|
||||
passwords: {
|
||||
clear: function ()
|
||||
{
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
pwmgr.removeAllLogins();
|
||||
Services.logins.removeAllLogins();
|
||||
},
|
||||
|
||||
get canClear()
|
||||
{
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
var count = pwmgr.countLogins("", "", ""); // count all logins
|
||||
Services.logins.countLogins("", "", ""); // count all logins
|
||||
return (count > 0);
|
||||
}
|
||||
},
|
||||
|
@ -33,6 +33,9 @@
|
||||
<string name="sync_settings">&sync.settings.label;</string>
|
||||
<string name="sync_subtitle_manage">&sync.subtitle.manage.label;</string>
|
||||
|
||||
<!-- Pair Device -->
|
||||
<string name="sync_pair_tryagain">&sync.pair.tryagain.label;</string>
|
||||
|
||||
<!-- Common text -->
|
||||
<string name="sync_button_cancel">&sync.button.cancel.label;</string>
|
||||
<string name="sync_button_connect">&sync.button.connect.label;</string>
|
||||
|
@ -895,6 +895,7 @@ nsDownloadManager::Init()
|
||||
(void)mObserverService->AddObserver(this, "offline-requested", false);
|
||||
(void)mObserverService->AddObserver(this, "sleep_notification", false);
|
||||
(void)mObserverService->AddObserver(this, "wake_notification", false);
|
||||
(void)mObserverService->AddObserver(this, "profile-before-change", false);
|
||||
(void)mObserverService->AddObserver(this, NS_IOSERVICE_GOING_OFFLINE_TOPIC, false);
|
||||
(void)mObserverService->AddObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC, false);
|
||||
(void)mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_REQUEST_TOPIC, false);
|
||||
@ -1686,6 +1687,9 @@ nsDownloadManager::CleanUp()
|
||||
NS_IMETHODIMP
|
||||
nsDownloadManager::GetCanCleanUp(bool *aResult)
|
||||
{
|
||||
// This method should never return anything but NS_OK for the benefit of
|
||||
// unwitting consumers.
|
||||
|
||||
*aResult = false;
|
||||
|
||||
DownloadState states[] = { nsIDownloadManager::DOWNLOAD_FINISHED,
|
||||
@ -1705,23 +1709,24 @@ nsDownloadManager::GetCanCleanUp(bool *aResult)
|
||||
"OR state = ? "
|
||||
"OR state = ? "
|
||||
"OR state = ?"), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
for (PRUint32 i = 0; i < ArrayLength(states); ++i) {
|
||||
rv = stmt->BindInt32ByIndex(i, states[i]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
}
|
||||
|
||||
bool moreResults; // We don't really care...
|
||||
rv = stmt->ExecuteStep(&moreResults);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
PRInt32 count;
|
||||
rv = stmt->GetInt32(0, &count);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
if (count > 0)
|
||||
*aResult = true;
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1937,6 +1942,12 @@ nsDownloadManager::Observe(nsISupports *aSubject,
|
||||
nsDownload *dl2 = FindDownload(id);
|
||||
if (dl2)
|
||||
return CancelDownload(id);
|
||||
} else if (strcmp(aTopic, "profile-before-change") == 0) {
|
||||
// Null statements to finalize them.
|
||||
mGetIdsForURIStatement = nsnull;
|
||||
mUpdateDownloadStatement = nsnull;
|
||||
mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
} else if (strcmp(aTopic, "quit-application") == 0) {
|
||||
// Try to pause all downloads and, if appropriate, mark them as auto-resume
|
||||
// unless user has specified that downloads should be canceled
|
||||
@ -1951,12 +1962,6 @@ nsDownloadManager::Observe(nsISupports *aSubject,
|
||||
// aborted downloads if the user's retention policy specifies it.
|
||||
if (GetRetentionBehavior() == 1)
|
||||
CleanUp();
|
||||
|
||||
// Null statements to finalize them.
|
||||
mGetIdsForURIStatement = nsnull;
|
||||
mUpdateDownloadStatement = nsnull;
|
||||
mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
} else if (strcmp(aTopic, "quit-application-requested") == 0 &&
|
||||
currDownloadCount) {
|
||||
nsCOMPtr<nsISupportsPRBool> cancelDownloads =
|
||||
|
@ -73,7 +73,7 @@ ssh -2 ${SYMBOL_SERVER_PORT:+-p $SYMBOL_SERVER_PORT} \
|
||||
"set -e;
|
||||
umask 0022;
|
||||
cd ${SYMBOL_SERVER_PATH};
|
||||
unzip -o '$archive';
|
||||
unzip -n '$archive';
|
||||
rm -v '$archive';"
|
||||
if test -n "$POST_SYMBOL_UPLOAD_CMD"; then
|
||||
echo "${POST_SYMBOL_UPLOAD_CMD} \"${SYMBOL_SERVER_PATH}/${SYMBOL_INDEX_NAME}\""
|
||||
|
@ -34,6 +34,9 @@ let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
let dm = Cc["@mozilla.org/download-manager;1"]
|
||||
.getService(Ci.nsIDownloadManager);
|
||||
|
||||
let os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
let checkDestination = false,
|
||||
@ -63,6 +66,32 @@ let annoObserver = {
|
||||
onItemAnnotationRemoved: function() {}
|
||||
}
|
||||
|
||||
let TestFinisher = {
|
||||
_dmuiDone: false,
|
||||
_callback: null,
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
os.removeObserver(TestFinisher, "download-manager-ui-done");
|
||||
|
||||
if (this._callback) {
|
||||
SimpleTest.executeSoon(this._callback);
|
||||
this._callback = null;
|
||||
} else {
|
||||
this._dmuiDone = true;
|
||||
}
|
||||
},
|
||||
|
||||
waitForDMUIDone: function(callback) {
|
||||
if (this._dmuiDone) {
|
||||
SimpleTest.executeSoon(callback);
|
||||
} else {
|
||||
this._callback = callback;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
os.addObserver(TestFinisher, "download-manager-ui-done", false);
|
||||
|
||||
let downloadListener = {
|
||||
|
||||
onDownloadStateChange: function(aState, aDownload) {
|
||||
@ -74,20 +103,8 @@ let downloadListener = {
|
||||
aDownload.targetFile.remove(false);
|
||||
} catch (ex) {}
|
||||
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
TestFinisher.waitForDMUIDone(endTest);
|
||||
|
||||
let testObs = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic != "download-manager-ui-done") {
|
||||
return;
|
||||
}
|
||||
os.removeObserver(testObs, "download-manager-ui-done");
|
||||
SimpleTest.executeSoon(endTest);
|
||||
}
|
||||
};
|
||||
|
||||
os.addObserver(testObs, "download-manager-ui-done", false);
|
||||
}
|
||||
},
|
||||
|
||||
@ -117,6 +134,7 @@ let windowObserver = {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
|
||||
if (win.location == UCT_URI) {
|
||||
ww.unregisterNotification(windowObserver);
|
||||
SimpleTest.executeSoon(function() {
|
||||
win.document.documentElement._fireButtonEvent("accept");
|
||||
win.close();
|
||||
@ -131,13 +149,13 @@ function endTest() {
|
||||
ok(checkDestination, "file destination was set");
|
||||
ok(checkFileName, "file name was set");
|
||||
|
||||
ww.unregisterNotification(windowObserver);
|
||||
PlacesUtils.annotations.removeObserver(annoObserver);
|
||||
dm.removeListener(downloadListener);
|
||||
|
||||
ww = null;
|
||||
PlacesUtils = null;
|
||||
dm = null;
|
||||
os = null;
|
||||
|
||||
Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
|
@ -93,6 +93,7 @@ PKG_PATH =
|
||||
PKG_INST_BASENAME = $(PKG_BASENAME).installer
|
||||
PKG_INST_PATH = install/sea/
|
||||
PKG_UPDATE_BASENAME = $(PKG_BASENAME)
|
||||
CHECKSUMS_FILE_BASENAME = $(PKG_BASENAME)
|
||||
PKG_UPDATE_PATH = update/
|
||||
COMPLETE_MAR = $(PKG_UPDATE_PATH)$(PKG_UPDATE_BASENAME).complete.mar
|
||||
# PARTIAL_MAR needs to be processed by $(wildcard) before you use it.
|
||||
@ -134,6 +135,7 @@ PKG_BASENAME = $(MOZ_APP_NAME)-$(MOZ_PKG_VERSION).$(AB_CD).$(MOZ_PKG_PLATFORM)
|
||||
endif
|
||||
PKG_INST_PATH = $(PKG_PATH)
|
||||
PKG_UPDATE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION)
|
||||
CHECKSUMS_FILE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION)
|
||||
PKG_UPDATE_PATH = update/$(PKG_PATH)
|
||||
COMPLETE_MAR = $(PKG_UPDATE_PATH)$(PKG_UPDATE_BASENAME).complete.mar
|
||||
# PARTIAL_MAR needs to be processed by $(wildcard) before you use it.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user