diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index 7400a67873c..8459611668d 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -157,6 +157,16 @@ SettingsListener.observe('language.current', 'en-US', function(value) { function(value) { Services.prefs.setCharPref('wap.UAProf.tagname', value); }); + + // DSDS default service IDs + ['mms', 'sms', 'telephony', 'voicemail'].forEach(function(key) { + SettingsListener.observe('ril.' + key + '.defaultServiceId', 0, + function(value) { + if (value != null) { + Services.prefs.setIntPref('dom.' + key + '.defaultServiceId', value); + } + }); + }); })(); //=================== DeviceInfo ==================== diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index f44cff8ad20..610e2fea5bf 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -1327,16 +1327,6 @@ window.addEventListener('ContentStart', function update_onContentStart() { }, 'volume-state-changed', false); })(); -Services.obs.addObserver(function(aSubject, aTopic, aData) { - let data = JSON.parse(aData); - shell.sendChromeEvent({ - type: "activity-done", - success: data.success, - manifestURL: data.manifestURL, - pageURL: data.pageURL - }); -}, "activity-done", false); - #ifdef MOZ_WIDGET_GONK // Devices don't have all the same partition size for /cache where we // store the http cache. diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a7d81255fa0..953c86b4ff0 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "20e3f42ccb6073c6d9bc9741de3a19a939a8a7d8", + "revision": "e3564b8656fcd189d4a83379e94bef1ab7d657b5", "repo_path": "/integration/gaia-central" } diff --git a/dom/activities/src/ActivitiesService.jsm b/dom/activities/src/ActivitiesService.jsm index 246eb7c86d0..dabaa972d2e 100644 --- a/dom/activities/src/ActivitiesService.jsm +++ b/dom/activities/src/ActivitiesService.jsm @@ -301,12 +301,10 @@ let Activities = { case "Activity:PostResult": caller.mm.sendAsyncMessage("Activity:FireSuccess", msg); - Services.obs.notifyObservers(null, "activity-done", obsData); delete this.callers[msg.id]; break; case "Activity:PostError": caller.mm.sendAsyncMessage("Activity:FireError", msg); - Services.obs.notifyObservers(null, "activity-done", obsData); delete this.callers[msg.id]; break; diff --git a/dom/activities/src/ActivityRequestHandler.js b/dom/activities/src/ActivityRequestHandler.js index 3bc1436249d..08d081d314a 100644 --- a/dom/activities/src/ActivityRequestHandler.js +++ b/dom/activities/src/ActivityRequestHandler.js @@ -9,6 +9,7 @@ const Ci = Components.interfaces; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "cpmm", "@mozilla.org/childprocessmessagemanager;1", @@ -53,6 +54,7 @@ ActivityRequestHandler.prototype = { "id": this._id, "result": aResult }); + Services.obs.notifyObservers(null, "activity-success", this._id); }, postError: function arh_postError(aError) { @@ -60,6 +62,7 @@ ActivityRequestHandler.prototype = { "id": this._id, "error": aError }); + Services.obs.notifyObservers(null, "activity-error", this._id); }, classID: Components.ID("{9326952a-dbe3-4d81-a51f-d9c160d96d6b}"), diff --git a/dom/activities/src/ActivityWrapper.js b/dom/activities/src/ActivityWrapper.js index c724baf190f..74b5304feec 100644 --- a/dom/activities/src/ActivityWrapper.js +++ b/dom/activities/src/ActivityWrapper.js @@ -50,21 +50,36 @@ ActivityWrapper.prototype = { let observer = { observe: function(aSubject, aTopic, aData) { - if (aTopic !== "inner-window-destroyed") { - return; - } - let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; - if (wId == innerWindowID) { - debug("Closing activity window " + innerWindowID); - Services.obs.removeObserver(observer, "inner-window-destroyed"); - cpmm.sendAsyncMessage("Activity:PostError", - { id: aMessage.id, - error: "ActivityCanceled" }); + switch (aTopic) { + case 'inner-window-destroyed': + let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; + if (wId == innerWindowID) { + debug("Closing activity window " + innerWindowID); + Services.obs.removeObserver(observer, "inner-window-destroyed"); + cpmm.sendAsyncMessage("Activity:PostError", + { id: aMessage.id, + error: "ActivityCanceled" + }); + } + break; + case 'activity-error': + case 'activity-success': + if (aData !== aMessage.id) { + return; + } + Services.obs.removeObserver(observer, "activity-error"); + Services.obs.removeObserver(observer, "activity-success"); + let docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + Services.obs.notifyObservers(docshell, "activity-done", aTopic); + break; } } } + Services.obs.addObserver(observer, "activity-error", false); + Services.obs.addObserver(observer, "activity-success", false); Services.obs.addObserver(observer, "inner-window-destroyed", false); return handler; }, diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index b7b57c8f3a9..7da867a90c4 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -265,12 +265,18 @@ BrowserElementChild.prototype = { Services.obs.addObserver(this, 'xpcom-shutdown', /* ownsWeak = */ true); + + Services.obs.addObserver(this, + 'activity-done', + /* ownsWeak = */ true); }, observe: function(subject, topic, data) { // Ignore notifications not about our document. (Note that |content| /can/ // be null; see bug 874900.) - if (!content || subject != content.document) + if (topic !== 'activity-done' && (!content || subject != content.document)) + return; + if (topic == 'activity-done' && docShell !== subject) return; switch (topic) { case 'fullscreen-origin-change': @@ -282,6 +288,9 @@ BrowserElementChild.prototype = { case 'ask-parent-to-rollback-fullscreen': sendAsyncMsg('rollback-fullscreen'); break; + case 'activity-done': + sendAsyncMsg('activitydone', { success: (data == 'activity-success') }); + break; case 'xpcom-shutdown': this._shuttingDown = true; break; diff --git a/dom/browser-element/BrowserElementParent.jsm b/dom/browser-element/BrowserElementParent.jsm index 2dd4d25aded..7a26cec7e19 100644 --- a/dom/browser-element/BrowserElementParent.jsm +++ b/dom/browser-element/BrowserElementParent.jsm @@ -127,6 +127,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) { "iconchange": this._fireEventFromMsg, "close": this._fireEventFromMsg, "resize": this._fireEventFromMsg, + "activitydone": this._fireEventFromMsg, "opensearch": this._fireEventFromMsg, "securitychange": this._fireEventFromMsg, "error": this._fireEventFromMsg, diff --git a/dom/mobilemessage/interfaces/nsIMmsService.idl b/dom/mobilemessage/interfaces/nsIMmsService.idl index aca7eaaa4e5..59f9e366c0c 100644 --- a/dom/mobilemessage/interfaces/nsIMmsService.idl +++ b/dom/mobilemessage/interfaces/nsIMmsService.idl @@ -12,9 +12,11 @@ interface nsIDOMBlob; #define MMS_SERVICE_CONTRACTID "@mozilla.org/mms/mmsservice;1" %} -[scriptable, uuid(e5ef630a-eab7-425a-ac42-650ef5c4fcef)] +[scriptable, uuid(5dc8b3bc-c3a9-45ea-8ee0-7562b0e57257)] interface nsIMmsService : nsISupports { + readonly attribute unsigned long mmsDefaultServiceId; + void send(in jsval parameters /* MmsParameters */, in nsIMobileMessageCallback request); diff --git a/dom/mobilemessage/interfaces/nsISmsService.idl b/dom/mobilemessage/interfaces/nsISmsService.idl index e3cde07aeb3..4d05bee6b17 100644 --- a/dom/mobilemessage/interfaces/nsISmsService.idl +++ b/dom/mobilemessage/interfaces/nsISmsService.idl @@ -13,9 +13,11 @@ interface nsIMobileMessageCallback; #define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1" %} -[scriptable, builtinclass, uuid(0f3f75ec-00dd-11e3-87ac-0b1d5c79afdf)] +[scriptable, builtinclass, uuid(ec3221fb-2d4a-4ccd-ac64-65c1b2dee5dd)] interface nsISmsService : nsISupports { + readonly attribute unsigned long smsDefaultServiceId; + boolean hasSupport(); void getSegmentInfoForText(in DOMString text, diff --git a/dom/mobilemessage/src/android/MmsService.cpp b/dom/mobilemessage/src/android/MmsService.cpp index fba2a2e358d..06df6effb37 100644 --- a/dom/mobilemessage/src/android/MmsService.cpp +++ b/dom/mobilemessage/src/android/MmsService.cpp @@ -14,6 +14,13 @@ namespace mobilemessage { NS_IMPL_ISUPPORTS1(MmsService, nsIMmsService) +NS_IMETHODIMP +MmsService::GetMmsDefaultServiceId(uint32_t* aServiceId) +{ + NS_NOTYETIMPLEMENTED("Implement me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP MmsService::Send(const JS::Value& aParameters, nsIMobileMessageCallback *aRequest) diff --git a/dom/mobilemessage/src/android/SmsService.cpp b/dom/mobilemessage/src/android/SmsService.cpp index 1da4b0a7ead..f3a455fb6bc 100644 --- a/dom/mobilemessage/src/android/SmsService.cpp +++ b/dom/mobilemessage/src/android/SmsService.cpp @@ -15,6 +15,14 @@ namespace mobilemessage { NS_IMPL_ISUPPORTS1(SmsService, nsISmsService) +NS_IMETHODIMP +SmsService::GetSmsDefaultServiceId(uint32_t* aServiceId) +{ + // Android has no official DSDS support. + *aServiceId = 0; + return NS_OK; +} + NS_IMETHODIMP SmsService::HasSupport(bool* aHasSupport) { diff --git a/dom/mobilemessage/src/fallback/MmsService.cpp b/dom/mobilemessage/src/fallback/MmsService.cpp index f49151aa04b..11d5bcebed4 100644 --- a/dom/mobilemessage/src/fallback/MmsService.cpp +++ b/dom/mobilemessage/src/fallback/MmsService.cpp @@ -13,6 +13,13 @@ namespace mobilemessage { NS_IMPL_ISUPPORTS1(MmsService, nsIMmsService) +NS_IMETHODIMP +MmsService::GetMmsDefaultServiceId(uint32_t* aServiceId) +{ + NS_NOTYETIMPLEMENTED("Implement me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP MmsService::Send(const JS::Value& aParameters, nsIMobileMessageCallback *aRequest) diff --git a/dom/mobilemessage/src/fallback/SmsService.cpp b/dom/mobilemessage/src/fallback/SmsService.cpp index a04a4676549..b4595a5e800 100644 --- a/dom/mobilemessage/src/fallback/SmsService.cpp +++ b/dom/mobilemessage/src/fallback/SmsService.cpp @@ -14,6 +14,13 @@ namespace mobilemessage { NS_IMPL_ISUPPORTS1(SmsService, nsISmsService) +NS_IMETHODIMP +SmsService::GetSmsDefaultServiceId(uint32_t* aServiceId) +{ + NS_ERROR("We should not be here!"); + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP SmsService::HasSupport(bool* aHasSupport) { diff --git a/dom/mobilemessage/src/gonk/MmsService.js b/dom/mobilemessage/src/gonk/MmsService.js index 42a806f0bc5..c619043e97e 100644 --- a/dom/mobilemessage/src/gonk/MmsService.js +++ b/dom/mobilemessage/src/gonk/MmsService.js @@ -33,9 +33,8 @@ const kSmsRetrievingObserverTopic = "sms-retrieving"; const kSmsDeliverySuccessObserverTopic = "sms-delivery-success"; const kSmsDeliveryErrorObserverTopic = "sms-delivery-error"; +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed"; -const kXpcomShutdownObserverTopic = "xpcom-shutdown"; -const kPrefenceChangedObserverTopic = "nsPref:changed"; const kMobileMessageDeletedObserverTopic = "mobile-message-deleted"; // HTTP status codes: @@ -59,17 +58,18 @@ const CONFIG_SEND_REPORT_DEFAULT_NO = 1; const CONFIG_SEND_REPORT_DEFAULT_YES = 2; const CONFIG_SEND_REPORT_ALWAYS = 3; +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; + const TIME_TO_BUFFER_MMS_REQUESTS = 30000; const PREF_TIME_TO_RELEASE_MMS_CONNECTION = Services.prefs.getIntPref("network.gonk.ms-release-mms-connection"); -const PREF_RETRIEVAL_MODE = 'dom.mms.retrieval_mode'; +const kPrefRetrievalMode = 'dom.mms.retrieval_mode'; const RETRIEVAL_MODE_MANUAL = "manual"; const RETRIEVAL_MODE_AUTOMATIC = "automatic"; const RETRIEVAL_MODE_AUTOMATIC_HOME = "automatic-home"; const RETRIEVAL_MODE_NEVER = "never"; - //Internal const values. const DELIVERY_RECEIVED = "received"; const DELIVERY_NOT_DOWNLOADED = "not-downloaded"; @@ -108,6 +108,9 @@ const PREF_RETRIEVAL_RETRY_INTERVALS = (function () { return intervals; })(); +const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +const kPrefDefaultServiceId = "dom.mms.defaultServiceId"; + XPCOMUtils.defineLazyServiceGetter(this, "gpps", "@mozilla.org/network/protocol-proxy-service;1", "nsIProtocolProxyService"); @@ -197,7 +200,7 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () { init: function init() { Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false); - Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false); + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); this.settings.forEach(function(name) { Services.prefs.addObserver(name, this, false); }, this); @@ -341,10 +344,9 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () { }, shutdown: function shutdown() { + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); Services.obs.removeObserver(this, kNetworkInterfaceStateChangedTopic); - this.settings.forEach(function(name) { - Services.prefs.removeObserver(name, this); - }, this); + this.connectTimer.cancel(); this.flushPendingCallbacks(_HTTP_STATUS_RADIO_DISABLED); this.disconnectTimer.cancel(); @@ -370,7 +372,7 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () { this.flushPendingCallbacks(_HTTP_STATUS_ACQUIRE_CONNECTION_SUCCESS) break; } - case kPrefenceChangedObserverTopic: { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: { if (data == "ril.radio.disabled") { try { this.radioDisabled = Services.prefs.getBoolPref("ril.radio.disabled"); @@ -404,8 +406,7 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () { } break; } - case kXpcomShutdownObserverTopic: { - Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: { this.shutdown(); } } @@ -757,7 +758,7 @@ CancellableTransaction.prototype = { registerRunCallback: function registerRunCallback(callback) { if (!this.isObserversAdded) { - Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false); + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.obs.addObserver(this, kMobileMessageDeletedObserverTopic, false); this.isObserversAdded = true; } @@ -768,7 +769,7 @@ CancellableTransaction.prototype = { removeObservers: function removeObservers() { if (this.isObserversAdded) { - Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); Services.obs.removeObserver(this, kMobileMessageDeletedObserverTopic); this.isObserversAdded = false; } @@ -811,7 +812,7 @@ CancellableTransaction.prototype = { observe: function observe(subject, topic, data) { switch (topic) { - case kXpcomShutdownObserverTopic: { + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: { this.cancelRunning(); break; } @@ -1191,6 +1192,17 @@ AcknowledgeTransaction.prototype = { } }; +function getDefaultServiceId() { + let id = Services.prefs.getIntPref(kPrefDefaultServiceId); + let numRil = Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); + + if (id >= numRil || id < 0) { + id = 0; + } + + return id; +} + /** * MmsService */ @@ -1201,13 +1213,17 @@ function MmsService() { debug("Running protocol version: " + macro + "." + minor); } + Services.prefs.addObserver(kPrefDefaultServiceId, this, false); + this.mmsDefaultServiceId = getDefaultServiceId(); + // TODO: bug 810084 - support application identifier } MmsService.prototype = { classID: RIL_MMSSERVICE_CID, QueryInterface: XPCOMUtils.generateQI([Ci.nsIMmsService, - Ci.nsIWapPushApplication]), + Ci.nsIWapPushApplication, + Ci.nsIObserver]), /* * Whether or not should we enable X-Mms-Report-Allowed in M-NotifyResp.ind * and M-Acknowledge.ind PDU. @@ -1584,7 +1600,7 @@ MmsService.prototype = { let retrievalMode = RETRIEVAL_MODE_MANUAL; try { - retrievalMode = Services.prefs.getCharPref(PREF_RETRIEVAL_MODE); + retrievalMode = Services.prefs.getCharPref(kPrefRetrievalMode); } catch (e) {} let savableMessage = this.convertIntermediateToSavable(notification, retrievalMode); @@ -1803,6 +1819,8 @@ MmsService.prototype = { // nsIMmsService + mmsDefaultServiceId: 0, + send: function send(aParams, aRequest) { if (DEBUG) debug("send: aParams: " + JSON.stringify(aParams)); @@ -2113,6 +2131,18 @@ MmsService.prototype = { break; } }, + + // nsIObserver + + observe: function observe(aSubject, aTopic, aData) { + switch (aTopic) { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (aData === kPrefDefaultServiceId) { + this.mmsDefaultServiceId = getDefaultServiceId(); + } + break; + } + } }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MmsService]); diff --git a/dom/mobilemessage/src/gonk/SmsService.cpp b/dom/mobilemessage/src/gonk/SmsService.cpp index a6138235688..4b25015f60f 100644 --- a/dom/mobilemessage/src/gonk/SmsService.cpp +++ b/dom/mobilemessage/src/gonk/SmsService.cpp @@ -7,13 +7,40 @@ #include "SmsService.h" #include "jsapi.h" #include "SmsSegmentInfo.h" +#include "mozilla/Preferences.h" #include "nsServiceManagerUtils.h" +namespace { + +const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +#define kPrefDefaultServiceId "dom.sms.defaultServiceId" +const char* kObservedPrefs[] = { + kPrefDefaultServiceId, + nullptr +}; + +uint32_t +getDefaultServiceId() +{ + int32_t id = mozilla::Preferences::GetInt(kPrefDefaultServiceId, 0); + int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1); + + if (id >= numRil || id < 0) { + id = 0; + } + + return id; +} + +} // Anonymous namespace + namespace mozilla { namespace dom { namespace mobilemessage { -NS_IMPL_ISUPPORTS1(SmsService, nsISmsService) +NS_IMPL_ISUPPORTS2(SmsService, + nsISmsService, + nsIObserver) SmsService::SmsService() { @@ -22,6 +49,42 @@ SmsService::SmsService() ril->GetRadioInterface(0, getter_AddRefs(mRadioInterface)); } NS_WARN_IF_FALSE(mRadioInterface, "This shouldn't fail!"); + + // Initialize observer. + Preferences::AddStrongObservers(this, kObservedPrefs); + mDefaultServiceId = getDefaultServiceId(); +} + +/* + * Implementation of nsIObserver. + */ + +NS_IMETHODIMP +SmsService::Observe(nsISupports* aSubject, + const char* aTopic, + const PRUnichar* aData) +{ + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + nsDependentString data(aData); + if (data.EqualsLiteral(kPrefDefaultServiceId)) { + mDefaultServiceId = getDefaultServiceId(); + } + return NS_OK; + } + + MOZ_ASSERT(false, "SmsService got unexpected topic!"); + return NS_ERROR_UNEXPECTED; +} + +/* + * Implementation of nsISmsService. + */ + +NS_IMETHODIMP +SmsService::GetSmsDefaultServiceId(uint32_t* aServiceId) +{ + *aServiceId = mDefaultServiceId; + return NS_OK; } NS_IMETHODIMP diff --git a/dom/mobilemessage/src/gonk/SmsService.h b/dom/mobilemessage/src/gonk/SmsService.h index a75512dbb86..8b3620be707 100644 --- a/dom/mobilemessage/src/gonk/SmsService.h +++ b/dom/mobilemessage/src/gonk/SmsService.h @@ -7,6 +7,7 @@ #include "nsISmsService.h" #include "nsCOMPtr.h" +#include "nsIObserver.h" #include "nsIRadioInterfaceLayer.h" #include "nsTArray.h" #include "nsString.h" @@ -17,16 +18,20 @@ namespace dom { namespace mobilemessage { class SmsService MOZ_FINAL : public nsISmsService + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSISMSSERVICE + NS_DECL_NSIOBSERVER + SmsService(); protected: // TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS nsCOMPtr mRadioInterface; nsTArray mSilentNumbers; + uint32_t mDefaultServiceId; }; } // namespace mobilemessage diff --git a/dom/mobilemessage/src/ipc/SmsIPCService.cpp b/dom/mobilemessage/src/ipc/SmsIPCService.cpp index 876bb2a2f4f..9180dccc1d5 100644 --- a/dom/mobilemessage/src/ipc/SmsIPCService.cpp +++ b/dom/mobilemessage/src/ipc/SmsIPCService.cpp @@ -17,12 +17,23 @@ #include "mozilla/dom/MobileMessageManagerBinding.h" #include "mozilla/dom/MozMmsMessageBinding.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/Preferences.h" +#include "nsString.h" using namespace mozilla::dom; using namespace mozilla::dom::mobilemessage; namespace { +const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +#define kPrefMmsDefaultServiceId "dom.mms.defaultServiceId" +#define kPrefSmsDefaultServiceId "dom.sms.defaultServiceId" +const char* kObservedPrefs[] = { + kPrefMmsDefaultServiceId, + kPrefSmsDefaultServiceId, + nullptr +}; + // TODO: Bug 767082 - WebSMS: sSmsChild leaks at shutdown PSmsChild* gSmsChild; @@ -74,16 +85,69 @@ SendCursorRequest(const IPCMobileMessageCursor& aRequest, actor.forget(aResult); return NS_OK; } + +uint32_t +getDefaultServiceId(const char* aPrefKey) +{ + int32_t id = mozilla::Preferences::GetInt(aPrefKey, 0); + int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1); + + if (id >= numRil || id < 0) { + id = 0; + } + + return id; +} + } // anonymous namespace -NS_IMPL_ISUPPORTS3(SmsIPCService, +NS_IMPL_ISUPPORTS4(SmsIPCService, nsISmsService, nsIMmsService, - nsIMobileMessageDatabaseService) + nsIMobileMessageDatabaseService, + nsIObserver) + +SmsIPCService::SmsIPCService() +{ + Preferences::AddStrongObservers(this, kObservedPrefs); + mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId); + mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); +} + +/* + * Implementation of nsIObserver. + */ + +NS_IMETHODIMP +SmsIPCService::Observe(nsISupports* aSubject, + const char* aTopic, + const PRUnichar* aData) +{ + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + nsDependentString data(aData); + if (data.EqualsLiteral(kPrefMmsDefaultServiceId)) { + mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId); + } else if (data.EqualsLiteral(kPrefSmsDefaultServiceId)) { + mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); + } + return NS_OK; + } + + MOZ_ASSERT(false, "SmsIPCService got unexpected topic!"); + return NS_ERROR_UNEXPECTED; +} /* * Implementation of nsISmsService. */ + +NS_IMETHODIMP +SmsIPCService::GetSmsDefaultServiceId(uint32_t* aServiceId) +{ + *aServiceId = mSmsDefaultServiceId; + return NS_OK; +} + NS_IMETHODIMP SmsIPCService::HasSupport(bool* aHasSupport) { @@ -236,6 +300,17 @@ GetSendMmsMessageRequestFromParams(const JS::Value& aParam, return true; } +/* + * Implementation of nsIMmsService. + */ + +NS_IMETHODIMP +SmsIPCService::GetMmsDefaultServiceId(uint32_t* aServiceId) +{ + *aServiceId = mMmsDefaultServiceId; + return NS_OK; +} + NS_IMETHODIMP SmsIPCService::Send(const JS::Value& aParameters, nsIMobileMessageCallback *aRequest) diff --git a/dom/mobilemessage/src/ipc/SmsIPCService.h b/dom/mobilemessage/src/ipc/SmsIPCService.h index 98b9a7737ef..8fbc12c7660 100644 --- a/dom/mobilemessage/src/ipc/SmsIPCService.h +++ b/dom/mobilemessage/src/ipc/SmsIPCService.h @@ -9,6 +9,7 @@ #include "nsISmsService.h" #include "nsIMmsService.h" #include "nsIMobileMessageDatabaseService.h" +#include "nsIObserver.h" #include "mozilla/Attributes.h" namespace mozilla { @@ -20,12 +21,20 @@ class PSmsChild; class SmsIPCService MOZ_FINAL : public nsISmsService , public nsIMmsService , public nsIMobileMessageDatabaseService + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSISMSSERVICE NS_DECL_NSIMMSSERVICE NS_DECL_NSIMOBILEMESSAGEDATABASESERVICE + NS_DECL_NSIOBSERVER + + SmsIPCService(); + +private: + uint32_t mMmsDefaultServiceId; + uint32_t mSmsDefaultServiceId; }; } // namespace mobilemessage diff --git a/dom/mobilemessage/tests/marionette/manifest.ini b/dom/mobilemessage/tests/marionette/manifest.ini index 17457a84940..d6e0b5bc5d9 100644 --- a/dom/mobilemessage/tests/marionette/manifest.ini +++ b/dom/mobilemessage/tests/marionette/manifest.ini @@ -36,3 +36,4 @@ qemu = true [test_invalid_address.js] [test_mmsmessage_attachments.js] [test_getthreads.js] +[test_dsds_default_service_id.js] diff --git a/dom/mobilemessage/tests/marionette/test_dsds_default_service_id.js b/dom/mobilemessage/tests/marionette/test_dsds_default_service_id.js new file mode 100644 index 00000000000..9e7c30af138 --- /dev/null +++ b/dom/mobilemessage/tests/marionette/test_dsds_default_service_id.js @@ -0,0 +1,130 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; +MARIONETTE_CONTEXT = "chrome"; + +Cu.import("resource://gre/modules/Promise.jsm"); + +const MMS_SERVICE_CONTRACTID = "@mozilla.org/mms/mmsservice;1"; +const SMS_SERVICE_CONTRACTID = "@mozilla.org/sms/smsservice;1"; + +const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces"; +const PREF_MMS_DEFAULT_SERVICE_ID = "dom.mms.defaultServiceId"; +const PREF_SMS_DEFAULT_SERVICE_ID = "dom.sms.defaultServiceId"; + +function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) { + log(" Set '" + prefKey + "' to " + setVal); + Services.prefs.setIntPref(prefKey, setVal); + let prefVal = Services.prefs.getIntPref(prefKey); + is(prefVal, setVal, "'" + prefKey + "' set to " + setVal); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, expectedVal, attrName); + + deferred.resolve(service); + }, 0); +} + +function getNumRadioInterfaces() { + let deferred = Promise.defer(); + + window.setTimeout(function () { + let numRil = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES); + log("numRil = " + numRil); + + deferred.resolve(numRil); + }, 0); + + return deferred.promise; +} + +function getService(contractId, ifaceName) { + let deferred = Promise.defer(); + + window.setTimeout(function () { + log("Getting service for " + ifaceName); + let service = Cc[contractId].getService(Ci[ifaceName]); + ok(service, "service.constructor is " + service.constructor); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkInitialEquality(attrName, prefKey, service) { + let deferred = Promise.defer(); + + log(" Checking initial value for '" + prefKey + "'"); + let origPrefVal = Services.prefs.getIntPref(prefKey); + ok(isFinite(origPrefVal), "default '" + prefKey + "' value"); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, origPrefVal, attrName); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkSetToNegtiveValue(attrName, prefKey, service) { + let deferred = Promise.defer(); + + // Set to -1 and verify defaultVal == 0. + setPrefAndVerify(prefKey, -1, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkSetToOverflowedValue(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + // Set to larger-equal than numRil and verify defaultVal == 0. + setPrefAndVerify(prefKey, numRil, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkValueChange(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + if (numRil > 1) { + // Set to (numRil - 1) and verify defaultVal equals. + setPrefAndVerify(prefKey, numRil - 1, service, attrName, numRil - 1, deferred); + } else { + window.setTimeout(function () { + deferred.resolve(service); + }, 0); + } + + return deferred.promise; +} + +function verify(contractId, ifaceName, attrName, prefKey, numRil) { + let deferred = Promise.defer(); + + getService(contractId, ifaceName) + .then(checkInitialEquality.bind(null, attrName, prefKey)) + .then(checkSetToNegtiveValue.bind(null, attrName, prefKey)) + .then(checkSetToOverflowedValue.bind(null, attrName, prefKey, numRil)) + .then(checkValueChange.bind(null, attrName, prefKey, numRil)) + .then(function () { + // Reset. + Services.prefs.clearUserPref(prefKey); + + deferred.resolve(numRil); + }); + + return deferred.promise; +} + +getNumRadioInterfaces() + .then(verify.bind(null, MMS_SERVICE_CONTRACTID, "nsIMmsService", + "mmsDefaultServiceId", PREF_MMS_DEFAULT_SERVICE_ID)) + .then(verify.bind(null, SMS_SERVICE_CONTRACTID, "nsISmsService", + "smsDefaultServiceId", PREF_SMS_DEFAULT_SERVICE_ID)) + .then(finish); diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js index d945eb124dd..fd60d57a95e 100644 --- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -25,22 +25,17 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var RIL = {}; Cu.import("resource://gre/modules/ril_consts.js", RIL); -// set to true to in ril_consts.js to see debug messages -var DEBUG = RIL.DEBUG_CONTENT_HELPER; +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; -// Read debug setting from pref -try { - let debugPref = Services.prefs.getBoolPref("ril.debugging.enabled"); - DEBUG = RIL.DEBUG_CONTENT_HELPER || debugPref; -} catch (e) {} +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; -let debug; -if (DEBUG) { - debug = function (s) { - dump("-*- RILContentHelper: " + s + "\n"); - }; -} else { - debug = function (s) {}; +const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; +const kPrefVoicemailDefaultServiceId = "dom.voicemail.defaultServiceId"; + +let DEBUG; +function debug(s) { + dump("-*- RILContentHelper: " + s + "\n"); } const RILCONTENTHELPER_CID = @@ -126,8 +121,7 @@ XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function () { return ril.numRadioInterfaces; } - let num = cpmm.sendSyncMessage("RIL:GetNumRadioInterfaces")[0]; - return num; + return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); }); function MobileIccCardLockResult(options) { @@ -449,6 +443,8 @@ IccCardLockError.prototype = { }; function RILContentHelper() { + this.updateDebugFlag(); + this.rilContext = { cardState: RIL.GECKO_CARDSTATE_UNKNOWN, networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN, @@ -457,10 +453,15 @@ function RILContentHelper() { dataConnectionInfo: new MobileConnectionInfo() }; this.voicemailInfo = new VoicemailInfo(); + this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId(); this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES); this._windowsMap = []; - Services.obs.addObserver(this, "xpcom-shutdown", false); + + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + + Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); + Services.prefs.addObserver(kPrefVoicemailDefaultServiceId, this, false); } RILContentHelper.prototype = { @@ -480,6 +481,13 @@ RILContentHelper.prototype = { Ci.nsIVoicemailProvider, Ci.nsIIccProvider]}), + updateDebugFlag: function updateDebugFlag() { + try { + DEBUG = RIL.DEBUG_CONTENT_HELPER || + Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); + } catch (e) {} + }, + // An utility function to copy objects. updateInfo: function updateInfo(srcInfo, destInfo) { for (let key in srcInfo) { @@ -1313,6 +1321,17 @@ RILContentHelper.prototype = { voicemailStatus: null, + voicemailDefaultServiceId: 0, + getVoicemailDefaultServiceId: function getVoicemailDefaultServiceId() { + let id = Services.prefs.getIntPref(kPrefVoicemailDefaultServiceId); + + if (id >= gNumRadioInterfaces || id < 0) { + id = 0; + } + + return id; + }, + getVoicemailInfo: function getVoicemailInfo() { // Get voicemail infomation by IPC only on first time. this.getVoicemailInfo = function getVoicemailInfo() { @@ -1327,9 +1346,11 @@ RILContentHelper.prototype = { return this.voicemailInfo; }, + get voicemailNumber() { return this.getVoicemailInfo().number; }, + get voicemailDisplayName() { return this.getVoicemailInfo().displayName; }, @@ -1404,9 +1425,19 @@ RILContentHelper.prototype = { // nsIObserver observe: function observe(subject, topic, data) { - if (topic == "xpcom-shutdown") { - this.destroyDOMRequestHelper(); - Services.obs.removeObserver(this, "xpcom-shutdown"); + switch (topic) { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (data == kPrefRilDebuggingEnabled) { + this.updateDebugFlag(); + } else if (data == kPrefVoicemailDefaultServiceId) { + this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId(); + } + break; + + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: + this.destroyDOMRequestHelper(); + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + break; } }, diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index e021226ec8b..ead6f59abe5 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -52,6 +52,7 @@ const GSMICCINFO_CID = const CDMAICCINFO_CID = Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}"); +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed"; const kSmsReceivedObserverTopic = "sms-received"; const kSilentSmsReceivedObserverTopic = "silent-sms-received"; @@ -64,14 +65,18 @@ const kMozSettingsChangedObserverTopic = "mozsettings-changed"; const kSysMsgListenerReadyObserverTopic = "system-message-listener-ready"; const kSysClockChangeObserverTopic = "system-clock-change"; const kScreenStateChangedTopic = "screen-state-changed"; -const kClockAutoUpdateEnabled = "time.clock.automatic-update.enabled"; -const kClockAutoUpdateAvailable = "time.clock.automatic-update.available"; -const kTimezoneAutoUpdateEnabled = "time.timezone.automatic-update.enabled"; -const kTimezoneAutoUpdateAvailable = "time.timezone.automatic-update.available"; -const kCellBroadcastSearchList = "ril.cellbroadcast.searchlist"; -const kCellBroadcastDisabled = "ril.cellbroadcast.disabled"; -const kPrefenceChangedObserverTopic = "nsPref:changed"; -const kClirModePreference = "ril.clirMode"; + +const kSettingsCellBroadcastSearchList = "ril.cellbroadcast.searchlist"; +const kSettingsClockAutoUpdateEnabled = "time.clock.automatic-update.enabled"; +const kSettingsClockAutoUpdateAvailable = "time.clock.automatic-update.available"; +const kSettingsTimezoneAutoUpdateEnabled = "time.timezone.automatic-update.enabled"; +const kSettingsTimezoneAutoUpdateAvailable = "time.timezone.automatic-update.available"; + +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; + +const kPrefCellBroadcastDisabled = "ril.cellbroadcast.disabled"; +const kPrefClirModePreference = "ril.clirMode"; +const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; const DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED = "received"; const DOM_MOBILE_MESSAGE_DELIVERY_SENDING = "sending"; @@ -82,7 +87,6 @@ const RADIO_POWER_OFF_TIMEOUT = 30000; const SMS_HANDLED_WAKELOCK_TIMEOUT = 5000; const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [ - "RIL:GetNumRadioInterfaces", "RIL:GetRilContext", "RIL:GetAvailableNetworks", "RIL:SelectNetwork", @@ -107,7 +111,6 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [ ]; const RIL_IPC_ICCMANAGER_MSG_NAMES = [ - "RIL:GetNumRadioInterfaces", "RIL:SendStkResponse", "RIL:SendStkMenuSelection", "RIL:SendStkTimerExpiration", @@ -125,13 +128,11 @@ const RIL_IPC_ICCMANAGER_MSG_NAMES = [ ]; const RIL_IPC_VOICEMAIL_MSG_NAMES = [ - "RIL:GetNumRadioInterfaces", "RIL:RegisterVoicemailMsg", "RIL:GetVoicemailInfo" ]; const RIL_IPC_CELLBROADCAST_MSG_NAMES = [ - "RIL:GetNumRadioInterfaces", "RIL:RegisterCellBroadcastMsg" ]; @@ -209,7 +210,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { init: function init(ril) { this.ril = ril; - Services.obs.addObserver(this, "xpcom-shutdown", false); + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false); this._registerMessageListeners(); }, @@ -217,7 +218,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { _shutdown: function _shutdown() { this.ril = null; - Services.obs.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); this._unregisterMessageListeners(); }, @@ -395,8 +396,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { } switch (msg.name) { - case "RIL:GetNumRadioInterfaces": - return this.ril.numRadioInterfaces; case "RIL:RegisterMobileConnectionMsg": this._registerMessageTarget("mobileconnection", msg.target); return null; @@ -431,7 +430,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic); this._resendQueuedTargetMessage(); break; - case "xpcom-shutdown": + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: this._shutdown(); break; } @@ -467,6 +466,25 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { }; }); +// Initialize shared preference 'ril.numRadioInterfaces' according to system +// property. +try { + Services.prefs.setIntPref(kPrefRilNumRadioInterfaces, (function () { + // When Gonk property "ro.moz.ril.numclients" is not set, return 1; if + // explicitly set to any number larger-equal than 0, return num; else, return + // 1 for compatibility. + try { + let numString = libcutils.property_get("ro.moz.ril.numclients", "1"); + let num = parseInt(numString, 10); + if (num >= 0) { + return num; + } + } catch (e) {} + + return 1; + })()); +} catch (e) {} + function IccInfo() {} IccInfo.prototype = { iccType: null, @@ -524,11 +542,11 @@ function RadioInterfaceLayer() { try { options.cellBroadcastDisabled = - Services.prefs.getBoolPref(kCellBroadcastDisabled); + Services.prefs.getBoolPref(kPrefCellBroadcastDisabled); } catch(e) {} try { - options.clirMode = Services.prefs.getIntPref(kClirModePreference); + options.clirMode = Services.prefs.getIntPref(kPrefClirModePreference); } catch(e) {} let numIfaces = this.numRadioInterfaces; @@ -568,16 +586,9 @@ RadioInterfaceLayer.prototype = { XPCOMUtils.defineLazyGetter(RadioInterfaceLayer.prototype, "numRadioInterfaces", function () { - // When Gonk property "ro.moz.ril.numclients" is not set, return 1; if - // explicitly set to any number larger-equal than 0, return num; else, return - // 1 for compatibility. try { - let numString = libcutils.property_get("ro.moz.ril.numclients", "1"); - let num = parseInt(numString, 10); - if (num >= 0) { - return num; - } - } catch (e) {} + return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); + } catch(e) {} return 1; }); @@ -781,11 +792,11 @@ function RadioInterface(options) { // Read the 'time.clock.automatic-update.enabled' setting to see if // we need to adjust the system clock time by NITZ or SNTP. - lock.get(kClockAutoUpdateEnabled, this); + lock.get(kSettingsClockAutoUpdateEnabled, this); // Read the 'time.timezone.automatic-update.enabled' setting to see if // we need to adjust the system timezone by NITZ. - lock.get(kTimezoneAutoUpdateEnabled, this); + lock.get(kSettingsTimezoneAutoUpdateEnabled, this); // Set "time.clock.automatic-update.available" to false when starting up. this.setClockAutoUpdateAvailable(false); @@ -795,16 +806,16 @@ function RadioInterface(options) { // Read the Cell Broadcast Search List setting, string of integers or integer // ranges separated by comma, to set listening channels. - lock.get(kCellBroadcastSearchList, this); + lock.get(kSettingsCellBroadcastSearchList, this); - Services.obs.addObserver(this, "xpcom-shutdown", false); + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false); Services.obs.addObserver(this, kSysClockChangeObserverTopic, false); Services.obs.addObserver(this, kScreenStateChangedTopic, false); Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false); - Services.prefs.addObserver(kCellBroadcastDisabled, this, false); + Services.prefs.addObserver(kPrefCellBroadcastDisabled, this, false); this.portAddressedSmsApps = {}; this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this); @@ -1336,7 +1347,7 @@ RadioInterface.prototype = { (function callback(response) { if (!response.success) { let lock = gSettingsService.createLock(); - lock.set(kCellBroadcastSearchList, + lock.set(kSettingsCellBroadcastSearchList, this._cellBroadcastSearchListStr, null); } else { this._cellBroadcastSearchListStr = response.searchListStr; @@ -1968,7 +1979,7 @@ RadioInterface.prototype = { * Set the setting value of "time.clock.automatic-update.available". */ setClockAutoUpdateAvailable: function setClockAutoUpdateAvailable(value) { - gSettingsService.createLock().set(kClockAutoUpdateAvailable, value, null, + gSettingsService.createLock().set(kSettingsClockAutoUpdateAvailable, value, null, "fromInternalSetting"); }, @@ -1976,7 +1987,7 @@ RadioInterface.prototype = { * Set the setting value of "time.timezone.automatic-update.available". */ setTimezoneAutoUpdateAvailable: function setTimezoneAutoUpdateAvailable(value) { - gSettingsService.createLock().set(kTimezoneAutoUpdateAvailable, value, null, + gSettingsService.createLock().set(kSettingsTimezoneAutoUpdateAvailable, value, null, "fromInternalSetting"); }, @@ -2152,17 +2163,17 @@ RadioInterface.prototype = { let setting = JSON.parse(data); this.handleSettingsChange(setting.key, setting.value, setting.message); break; - case kPrefenceChangedObserverTopic: - if (data === kCellBroadcastDisabled) { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (data === kPrefCellBroadcastDisabled) { let value = false; try { - value = Services.prefs.getBoolPref(kCellBroadcastDisabled); + value = Services.prefs.getBoolPref(kPrefCellBroadcastDisabled); } catch(e) {} this.workerMessenger.send("setCellBroadcastDisabled", { disabled: value }); } break; - case "xpcom-shutdown": + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: // Cancel the timer of the CPU wake lock for handling the received SMS. this._cancelSmsHandledWakeLockTimer(); @@ -2172,12 +2183,11 @@ RadioInterface.prototype = { apnSetting.iface.shutdown(); } } - Services.obs.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic); Services.obs.removeObserver(this, kSysClockChangeObserverTopic); Services.obs.removeObserver(this, kScreenStateChangedTopic); Services.obs.removeObserver(this, kNetworkInterfaceStateChangedTopic); - Services.prefs.removeObserver(kCellBroadcastDisabled, this); break; case kSysClockChangeObserverTopic: let offset = parseInt(data, 10); @@ -2240,7 +2250,7 @@ RadioInterface.prototype = { handleSettingsChange: function handleSettingsChange(aName, aResult, aMessage) { // Don't allow any content processes to modify the setting // "time.clock.automatic-update.available" except for the chrome process. - if (aName === kClockAutoUpdateAvailable && + if (aName === kSettingsClockAutoUpdateAvailable && aMessage !== "fromInternalSetting") { let isClockAutoUpdateAvailable = this._lastNitzMessage !== null || this._sntp.isAvailable(); @@ -2254,7 +2264,7 @@ RadioInterface.prototype = { // Don't allow any content processes to modify the setting // "time.timezone.automatic-update.available" except for the chrome // process. - if (aName === kTimezoneAutoUpdateAvailable && + if (aName === kSettingsTimezoneAutoUpdateAvailable && aMessage !== "fromInternalSetting") { let isTimezoneAutoUpdateAvailable = this._lastNitzMessage !== null; if (aResult !== isTimezoneAutoUpdateAvailable) { @@ -2306,7 +2316,7 @@ RadioInterface.prototype = { this.updateRILNetworkInterface(); } break; - case kClockAutoUpdateEnabled: + case kSettingsClockAutoUpdateEnabled: this._clockAutoUpdateEnabled = aResult; if (!this._clockAutoUpdateEnabled) { break; @@ -2326,7 +2336,7 @@ RadioInterface.prototype = { } } break; - case kTimezoneAutoUpdateEnabled: + case kSettingsTimezoneAutoUpdateEnabled: this._timezoneAutoUpdateEnabled = aResult; if (this._timezoneAutoUpdateEnabled) { @@ -2336,9 +2346,9 @@ RadioInterface.prototype = { } } break; - case kCellBroadcastSearchList: + case kSettingsCellBroadcastSearchList: if (DEBUG) { - this.debug("'" + kCellBroadcastSearchList + "' is now " + aResult); + this.debug("'" + kSettingsCellBroadcastSearchList + "' is now " + aResult); } this.setCellBroadcastSearchList(aResult); break; @@ -2381,10 +2391,10 @@ RadioInterface.prototype = { _updateCallingLineIdRestrictionPref: function _updateCallingLineIdRestrictionPref(mode) { try { - Services.prefs.setIntPref(kClirModePreference, mode); + Services.prefs.setIntPref(kPrefClirModePreference, mode); Services.prefs.savePrefFile(null); if (DEBUG) { - this.debug(kClirModePreference + " pref is now " + mode); + this.debug(kPrefClirModePreference + " pref is now " + mode); } } catch (e) {} }, diff --git a/dom/system/gonk/tests/marionette/manifest.ini b/dom/system/gonk/tests/marionette/manifest.ini index 94d788d5016..f53e26d0b33 100644 --- a/dom/system/gonk/tests/marionette/manifest.ini +++ b/dom/system/gonk/tests/marionette/manifest.ini @@ -8,3 +8,4 @@ disabled = Bug 808783 [test_fakevolume.js] [test_ril_code_quality.py] [test_screen_state.js] +[test_dsds_numRadioInterfaces.js] diff --git a/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js b/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js new file mode 100644 index 00000000000..de4739a60a8 --- /dev/null +++ b/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js @@ -0,0 +1,43 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; +MARIONETTE_CONTEXT = "chrome"; + +Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/systemlibs.js"); + +const NS_RIL_CONTRACTID = "@mozilla.org/ril;1"; + +const PROP_RO_MOZ_RIL_NUMCLIENTS = "ro.moz.ril.numclients"; + +const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces"; + +ok(libcutils, "libcutils is available"); + +let propNum = (function () { + try { + let numString = libcutils.property_get(PROP_RO_MOZ_RIL_NUMCLIENTS, "1"); + let num = parseInt(numString, 10); + if (num >= 0) { + return num; + } + } catch (e) {} +})(); + +log("Retrieved '" + PROP_RO_MOZ_RIL_NUMCLIENTS + "' = " + propNum); +ok(propNum, PROP_RO_MOZ_RIL_NUMCLIENTS); + +let prefNum = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES); +log("Retrieved '" + PREF_RIL_NUM_RADIO_INTERFACES + "' = " + prefNum); + +let ril = Cc[NS_RIL_CONTRACTID].getService(Ci.nsIRadioInterfaceLayer); +ok(ril, "ril.constructor is " + ril.constructor); + +let ifaceNum = ril.numRadioInterfaces; +log("Retrieved 'nsIRadioInterfaceLayer.numRadioInterfaces' = " + ifaceNum); + +is(propNum, prefNum); +is(propNum, ifaceNum); + +finish(); diff --git a/dom/telephony/gonk/TelephonyProvider.js b/dom/telephony/gonk/TelephonyProvider.js index b16566152d8..123011220c1 100644 --- a/dom/telephony/gonk/TelephonyProvider.js +++ b/dom/telephony/gonk/TelephonyProvider.js @@ -18,8 +18,13 @@ const GONK_TELEPHONYPROVIDER_CONTRACTID = const GONK_TELEPHONYPROVIDER_CID = Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}"); -const kPrefenceChangedObserverTopic = "nsPref:changed"; -const kXpcomShutdownObserverTopic = "xpcom-shutdown"; +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; + +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; + +const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; +const kPrefDefaultServiceId = "dom.telephony.defaultServiceId"; const nsIAudioManager = Ci.nsIAudioManager; const nsITelephonyProvider = Ci.nsITelephonyProvider; @@ -83,9 +88,12 @@ function TelephonyProvider() { this._listeners = []; this._updateDebugFlag(); + this.defaultServiceId = this._getDefaultServiceId(); - Services.obs.addObserver(this, kPrefenceChangedObserverTopic, false); - Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false); + Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); + Services.prefs.addObserver(kPrefDefaultServiceId, this, false); + + Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); } TelephonyProvider.prototype = { classID: GONK_TELEPHONYPROVIDER_CID, @@ -265,14 +273,27 @@ TelephonyProvider.prototype = { _updateDebugFlag: function _updateDebugFlag() { try { DEBUG = RIL.DEBUG_RIL || - Services.prefs.getBoolPref("ril.debugging.enabled"); + Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); } catch (e) {} }, + _getDefaultServiceId: function _getDefaultServiceId() { + let id = Services.prefs.getIntPref(kPrefDefaultServiceId); + let numRil = Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); + + if (id >= numRil || id < 0) { + id = 0; + } + + return id; + }, + /** * nsITelephonyProvider interface. */ + defaultServiceId: 0, + registerListener: function(aListener) { if (this._listeners.indexOf(aListener) >= 0) { throw Cr.NS_ERROR_UNEXPECTED; @@ -506,18 +527,19 @@ TelephonyProvider.prototype = { observe: function observe(aSubject, aTopic, aData) { switch (aTopic) { - case kPrefenceChangedObserverTopic: - if (aData === "ril.debugging.enabled") { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (aData === kPrefRilDebuggingEnabled) { this._updateDebugFlag(); + } else if (aData === kPrefDefaultServiceId) { + this.defaultServiceId = this._getDefaultServiceId(); } break; - case kXpcomShutdownObserverTopic: + case NS_XPCOM_SHUTDOWN_OBSERVER_ID: // Cancel the timer for the call-ring wake lock. this._cancelCallRingWakeLockTimer(); - Services.obs.removeObserver(this, kPrefenceChangedObserverTopic); - Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); + Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); break; } } diff --git a/dom/telephony/ipc/TelephonyIPCProvider.cpp b/dom/telephony/ipc/TelephonyIPCProvider.cpp index 3b40a31271c..6da47f8face 100644 --- a/dom/telephony/ipc/TelephonyIPCProvider.cpp +++ b/dom/telephony/ipc/TelephonyIPCProvider.cpp @@ -3,22 +3,52 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "ipc/TelephonyIPCProvider.h" + #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/telephony/TelephonyChild.h" -#include "ipc/TelephonyIPCProvider.h" +#include "mozilla/Preferences.h" USING_TELEPHONY_NAMESPACE using namespace mozilla::dom; -NS_IMPL_ISUPPORTS2(TelephonyIPCProvider, +namespace { + +const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; +#define kPrefDefaultServiceId "dom.telephony.defaultServiceId" +const char* kObservedPrefs[] = { + kPrefDefaultServiceId, + nullptr +}; + +uint32_t +getDefaultServiceId() +{ + int32_t id = mozilla::Preferences::GetInt(kPrefDefaultServiceId, 0); + int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1); + + if (id >= numRil || id < 0) { + id = 0; + } + + return id; +} + +} // Anonymous namespace + +NS_IMPL_ISUPPORTS3(TelephonyIPCProvider, nsITelephonyProvider, - nsITelephonyListener) + nsITelephonyListener, + nsIObserver) TelephonyIPCProvider::TelephonyIPCProvider() { // Deallocated in ContentChild::DeallocPTelephonyChild(). mPTelephonyChild = new TelephonyChild(this); ContentChild::GetSingleton()->SendPTelephonyConstructor(mPTelephonyChild); + + Preferences::AddStrongObservers(this, kObservedPrefs); + mDefaultServiceId = getDefaultServiceId(); } TelephonyIPCProvider::~TelephonyIPCProvider() @@ -27,10 +57,38 @@ TelephonyIPCProvider::~TelephonyIPCProvider() mPTelephonyChild = nullptr; } +/* + * Implementation of nsIObserver. + */ + +NS_IMETHODIMP +TelephonyIPCProvider::Observe(nsISupports* aSubject, + const char* aTopic, + const PRUnichar* aData) +{ + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + nsDependentString data(aData); + if (data.EqualsLiteral(kPrefDefaultServiceId)) { + mDefaultServiceId = getDefaultServiceId(); + } + return NS_OK; + } + + MOZ_ASSERT(false, "TelephonyIPCProvider got unexpected topic!"); + return NS_ERROR_UNEXPECTED; +} + /* * Implementation of nsITelephonyProvider. */ +NS_IMETHODIMP +TelephonyIPCProvider::GetDefaultServiceId(uint32_t* aServiceId) +{ + *aServiceId = mDefaultServiceId; + return NS_OK; +} + NS_IMETHODIMP TelephonyIPCProvider::RegisterListener(nsITelephonyListener *aListener) { diff --git a/dom/telephony/ipc/TelephonyIPCProvider.h b/dom/telephony/ipc/TelephonyIPCProvider.h index 928fd1d6567..215bc7a9deb 100644 --- a/dom/telephony/ipc/TelephonyIPCProvider.h +++ b/dom/telephony/ipc/TelephonyIPCProvider.h @@ -8,6 +8,7 @@ #include "mozilla/dom/telephony/TelephonyCommon.h" #include "mozilla/Attributes.h" +#include "nsIObserver.h" #include "nsITelephonyProvider.h" BEGIN_TELEPHONY_NAMESPACE @@ -16,11 +17,13 @@ class PTelephonyChild; class TelephonyIPCProvider MOZ_FINAL : public nsITelephonyProvider , public nsITelephonyListener + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSITELEPHONYPROVIDER NS_DECL_NSITELEPHONYLISTENER + NS_DECL_NSIOBSERVER TelephonyIPCProvider(); @@ -30,6 +33,7 @@ protected: private: nsTArray > mListeners; PTelephonyChild* mPTelephonyChild; + uint32_t mDefaultServiceId; }; END_TELEPHONY_NAMESPACE diff --git a/dom/telephony/nsITelephonyProvider.idl b/dom/telephony/nsITelephonyProvider.idl index d8cb28adc70..cda5e1ba109 100644 --- a/dom/telephony/nsITelephonyProvider.idl +++ b/dom/telephony/nsITelephonyProvider.idl @@ -118,7 +118,7 @@ interface nsITelephonyListener : nsISupports * XPCOM component (in the content process) that provides the telephony * information. */ -[scriptable, uuid(effca006-1ca8-47f7-9bab-1323f90a14ec)] +[scriptable, uuid(f7680b82-53fc-42a7-9adf-bc0f2726425c)] interface nsITelephonyProvider : nsISupports { const unsigned short CALL_STATE_UNKNOWN = 0; @@ -136,6 +136,8 @@ interface nsITelephonyProvider : nsISupports const unsigned short NOTIFICATION_REMOTE_HELD = 0; const unsigned short NOTIFICATION_REMOTE_RESUMED = 1; + readonly attribute unsigned long defaultServiceId; + /** * Called when a content process registers receiving unsolicited messages from * RadioInterfaceLayer in the chrome process. Only a content process that has diff --git a/dom/telephony/test/marionette/manifest.ini b/dom/telephony/test/marionette/manifest.ini index e610b63b886..32de7143002 100644 --- a/dom/telephony/test/marionette/manifest.ini +++ b/dom/telephony/test/marionette/manifest.ini @@ -43,3 +43,4 @@ disabled = Bug 821958 [test_outgoing_emergency_in_airplane_mode.js] [test_emergency_label.js] [test_conference.js] +[test_dsds_default_service_id.js] diff --git a/dom/telephony/test/marionette/test_dsds_default_service_id.js b/dom/telephony/test/marionette/test_dsds_default_service_id.js new file mode 100644 index 00000000000..182ae95e481 --- /dev/null +++ b/dom/telephony/test/marionette/test_dsds_default_service_id.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; +MARIONETTE_CONTEXT = "chrome"; + +Cu.import("resource://gre/modules/Promise.jsm"); + +const TELEPHONY_PROVIDER_CONTRACTID = + "@mozilla.org/telephony/telephonyprovider;1"; + +const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces"; +const PREF_DEFAULT_SERVICE_ID = "dom.telephony.defaultServiceId"; + +function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) { + log(" Set '" + prefKey + "' to " + setVal); + Services.prefs.setIntPref(prefKey, setVal); + let prefVal = Services.prefs.getIntPref(prefKey); + is(prefVal, setVal, "'" + prefKey + "' set to " + setVal); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, expectedVal, attrName); + + deferred.resolve(service); + }, 0); +} + +function getNumRadioInterfaces() { + let deferred = Promise.defer(); + + window.setTimeout(function () { + let numRil = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES); + log("numRil = " + numRil); + + deferred.resolve(numRil); + }, 0); + + return deferred.promise; +} + +function getService(contractId, ifaceName) { + let deferred = Promise.defer(); + + window.setTimeout(function () { + log("Getting service for " + ifaceName); + let service = Cc[contractId].getService(Ci[ifaceName]); + ok(service, "service.constructor is " + service.constructor); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkInitialEquality(attrName, prefKey, service) { + let deferred = Promise.defer(); + + log(" Checking initial value for '" + prefKey + "'"); + let origPrefVal = Services.prefs.getIntPref(prefKey); + ok(isFinite(origPrefVal), "default '" + prefKey + "' value"); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, origPrefVal, attrName); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkSetToNegtiveValue(attrName, prefKey, service) { + let deferred = Promise.defer(); + + // Set to -1 and verify defaultVal == 0. + setPrefAndVerify(prefKey, -1, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkSetToOverflowedValue(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + // Set to larger-equal than numRil and verify defaultVal == 0. + setPrefAndVerify(prefKey, numRil, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkValueChange(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + if (numRil > 1) { + // Set to (numRil - 1) and verify defaultVal equals. + setPrefAndVerify(prefKey, numRil - 1, service, attrName, numRil - 1, deferred); + } else { + window.setTimeout(function () { + deferred.resolve(service); + }, 0); + } + + return deferred.promise; +} + +function verify(contractId, ifaceName, attrName, prefKey, numRil) { + let deferred = Promise.defer(); + + getService(contractId, ifaceName) + .then(checkInitialEquality.bind(null, attrName, prefKey)) + .then(checkSetToNegtiveValue.bind(null, attrName, prefKey)) + .then(checkSetToOverflowedValue.bind(null, attrName, prefKey, numRil)) + .then(checkValueChange.bind(null, attrName, prefKey, numRil)) + .then(function () { + // Reset. + Services.prefs.clearUserPref(prefKey); + + deferred.resolve(numRil); + }); + + return deferred.promise; +} + +getNumRadioInterfaces() + .then(verify.bind(null, TELEPHONY_PROVIDER_CONTRACTID, "nsITelephonyProvider", + "defaultServiceId", PREF_DEFAULT_SERVICE_ID)) + .then(finish); diff --git a/dom/voicemail/nsIVoicemailProvider.idl b/dom/voicemail/nsIVoicemailProvider.idl index 4d036386f6a..115e35cc80a 100644 --- a/dom/voicemail/nsIVoicemailProvider.idl +++ b/dom/voicemail/nsIVoicemailProvider.idl @@ -22,9 +22,11 @@ interface nsIVoicemailListener : nsISupports * XPCOM component (in the content process) that provides the voicemail * information. */ -[scriptable, uuid(37bc0991-21a3-4de9-b888-d667fea6c05d)] +[scriptable, uuid(38746f3c-f4e3-4804-b900-ba2463b923c8)] interface nsIVoicemailProvider : nsISupports { + readonly attribute unsigned long voicemailDefaultServiceId; + /** * Called when a content process registers receiving unsolicited messages from * RadioInterfaceLayer in the chrome process. Only a content process that has diff --git a/dom/voicemail/test/marionette/manifest.ini b/dom/voicemail/test/marionette/manifest.ini index 47c83c88a10..9f5ab7423f6 100644 --- a/dom/voicemail/test/marionette/manifest.ini +++ b/dom/voicemail/test/marionette/manifest.ini @@ -5,3 +5,4 @@ qemu = true [test_voicemail_statuschanged.py] [test_voicemail_number.js] +[test_dsds_default_service_id.js] diff --git a/dom/voicemail/test/marionette/test_dsds_default_service_id.js b/dom/voicemail/test/marionette/test_dsds_default_service_id.js new file mode 100644 index 00000000000..b45962fd998 --- /dev/null +++ b/dom/voicemail/test/marionette/test_dsds_default_service_id.js @@ -0,0 +1,126 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; +MARIONETTE_CONTEXT = "chrome"; + +Cu.import("resource://gre/modules/Promise.jsm"); + +const VOICEMAIL_PROVIDER_CONTRACTID = "@mozilla.org/ril/content-helper;1"; + +const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces"; +const PREF_DEFAULT_SERVICE_ID = "dom.voicemail.defaultServiceId"; + +function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) { + log(" Set '" + prefKey + "' to " + setVal); + Services.prefs.setIntPref(prefKey, setVal); + let prefVal = Services.prefs.getIntPref(prefKey); + is(prefVal, setVal, "'" + prefKey + "' set to " + setVal); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, expectedVal, attrName); + + deferred.resolve(service); + }, 0); +} + +function getNumRadioInterfaces() { + let deferred = Promise.defer(); + + window.setTimeout(function () { + let numRil = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES); + log("numRil = " + numRil); + + deferred.resolve(numRil); + }, 0); + + return deferred.promise; +} + +function getService(contractId, ifaceName) { + let deferred = Promise.defer(); + + window.setTimeout(function () { + log("Getting service for " + ifaceName); + let service = Cc[contractId].getService(Ci[ifaceName]); + ok(service, "service.constructor is " + service.constructor); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkInitialEquality(attrName, prefKey, service) { + let deferred = Promise.defer(); + + log(" Checking initial value for '" + prefKey + "'"); + let origPrefVal = Services.prefs.getIntPref(prefKey); + ok(isFinite(origPrefVal), "default '" + prefKey + "' value"); + + window.setTimeout(function () { + let defaultVal = service[attrName]; + is(defaultVal, origPrefVal, attrName); + + deferred.resolve(service); + }, 0); + + return deferred.promise; +} + +function checkSetToNegtiveValue(attrName, prefKey, service) { + let deferred = Promise.defer(); + + // Set to -1 and verify defaultVal == 0. + setPrefAndVerify(prefKey, -1, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkSetToOverflowedValue(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + // Set to larger-equal than numRil and verify defaultVal == 0. + setPrefAndVerify(prefKey, numRil, service, attrName, 0, deferred); + + return deferred.promise; +} + +function checkValueChange(attrName, prefKey, numRil, service) { + let deferred = Promise.defer(); + + if (numRil > 1) { + // Set to (numRil - 1) and verify defaultVal equals. + setPrefAndVerify(prefKey, numRil - 1, service, attrName, numRil - 1, deferred); + } else { + window.setTimeout(function () { + deferred.resolve(service); + }, 0); + } + + return deferred.promise; +} + +function verify(contractId, ifaceName, attrName, prefKey, numRil) { + let deferred = Promise.defer(); + + getService(contractId, ifaceName) + .then(checkInitialEquality.bind(null, attrName, prefKey)) + .then(checkSetToNegtiveValue.bind(null, attrName, prefKey)) + .then(checkSetToOverflowedValue.bind(null, attrName, prefKey, numRil)) + .then(checkValueChange.bind(null, attrName, prefKey, numRil)) + .then(function () { + // Reset. + Services.prefs.clearUserPref(prefKey); + + deferred.resolve(numRil); + }); + + return deferred.promise; +} + +getNumRadioInterfaces() + .then(verify.bind(null, VOICEMAIL_PROVIDER_CONTRACTID, "nsIVoicemailProvider", + "voicemailDefaultServiceId", PREF_DEFAULT_SERVICE_ID)) + .then(finish); diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index d2b84cf01cc..eab693dcba9 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -4300,7 +4300,9 @@ pref("dom.sms.enabled", false); // 7-bit default alphabet. pref("dom.sms.strict7BitEncoding", false); pref("dom.sms.requestStatusReport", true); -pref("dom.mms.requestStatusReport", true); +// Numeric default service id for SMS API calls with |serviceId| parameter +// omitted. +pref("dom.sms.defaultServiceId", 0); // WebContacts pref("dom.mozContacts.enabled", false); @@ -4426,6 +4428,8 @@ pref("wap.UAProf.tagname", "x-wap-profile"); // @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.34 pref("dom.mms.version", 19); +pref("dom.mms.requestStatusReport", true); + // Retrieval mode for MMS // manual: Manual retrieval mode. // automatic: Automatic retrieval mode even in roaming. @@ -4438,10 +4442,15 @@ pref("dom.mms.sendRetryInterval", 300000); pref("dom.mms.retrievalRetryCount", 4); pref("dom.mms.retrievalRetryIntervals", "60000,300000,600000,1800000"); - +// Numeric default service id for MMS API calls with |serviceId| parameter +// omitted. +pref("dom.mms.defaultServiceId", 0); // Debug enabler for MMS. pref("mms.debugging.enabled", false); +// Number of RadioInterface instances to create. +pref("ril.numRadioInterfaces", 0); + // If the user puts a finger down on an element and we think the user // might be executing a pan gesture, how long do we wait before // tentatively deciding the gesture is actually a tap and activating @@ -4477,6 +4486,9 @@ pref("dom.datastore.enabled", false); // Telephony API pref("dom.telephony.enabled", false); +// Numeric default service id for WebTelephony API calls with |serviceId| +// parameter omitted. +pref("dom.telephony.defaultServiceId", 0); // Cell Broadcast API pref("dom.cellbroadcast.enabled", false); @@ -4489,6 +4501,9 @@ pref("dom.mobileconnection.enabled", false); // Voice Mail API pref("dom.voicemail.enabled", false); +// Numeric default service id for Voice Mail API calls with |serviceId| +// parameter omitted. +pref("dom.voicemail.defaultServiceId", 0); // DOM Inter-App Communication API. pref("dom.inter-app-communication-api.enabled", false);