Merge m-c to s-c.

This commit is contained in:
Richard Newman 2012-01-10 09:03:52 -08:00
commit ef1c4cc14f
102 changed files with 2704 additions and 2695 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -391,8 +391,6 @@ while (testProps.length) {
}
}
SimpleTest.finish();
</script>
</pre>
</body>

View File

@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = content
LIBRARY_NAME = gkconhtmlcon_s
LIBXUL_LIBRARY = 1
FAIL_ON_WARNINGS = 1
EXPORTS = \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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__

View File

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

View 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
View 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__

View File

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

View File

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

View File

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

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

View 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__

View File

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

View 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__

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
}
},
/**

View File

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

View File

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

View File

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

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

View File

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

View File

@ -46,7 +46,6 @@ function testTab(prefix, callback) {
testTab("", function() {
testTab("foo", function() {
SimpleTest.finish();
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -504,6 +504,8 @@ irregularFilenames = {
'nsIDOMTouch': 'nsIDOMTouchEvent',
'nsIDOMTouchList': 'nsIDOMTouchEvent',
'nsITelephoneCallback': 'nsITelephone',
}
customIncludes = [

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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}\""

View File

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

View File

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