зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound on a CLOSED TREE.
This commit is contained in:
Коммит
1d57260a86
|
@ -430,7 +430,7 @@ pref("services.push.requestTimeout", 10000);
|
|||
pref("services.push.udp.wakeupEnabled", true);
|
||||
|
||||
// NetworkStats
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
pref("dom.mozNetworkStats.enabled", true);
|
||||
pref("dom.webapps.firstRunWithSIM", true);
|
||||
#endif
|
||||
|
@ -825,22 +825,9 @@ pref("gfx.canvas.skiagl.dynamic-cache", true);
|
|||
// enable fence with readpixels for SurfaceStream
|
||||
pref("gfx.gralloc.fence-with-readpixels", true);
|
||||
|
||||
// Enable Telephony API
|
||||
pref("dom.telephony.enabled", true);
|
||||
|
||||
// Cell Broadcast API
|
||||
pref("dom.cellbroadcast.enabled", true);
|
||||
pref("ril.cellbroadcast.disabled", false);
|
||||
|
||||
// ICC API
|
||||
pref("dom.icc.enabled", true);
|
||||
|
||||
// Mobile Connection API
|
||||
pref("dom.mobileconnection.enabled", true);
|
||||
|
||||
// Voice Mail API
|
||||
pref("dom.voicemail.enabled", true);
|
||||
|
||||
// The url of the page used to display network error details.
|
||||
pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
|
||||
|
||||
|
|
|
@ -636,7 +636,7 @@ let FormAssistant = {
|
|||
},
|
||||
|
||||
showKeyboard: function fa_showKeyboard(target) {
|
||||
if (this.isKeyboardOpened)
|
||||
if (this.focusedElement === target)
|
||||
return;
|
||||
|
||||
if (target instanceof HTMLOptionElement)
|
||||
|
|
|
@ -138,6 +138,11 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
|||
Services.prefs.setBoolPref('dom.mms.requestStatusReport', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('ril.mms.requestReadReport.enabled', true,
|
||||
function(value) {
|
||||
Services.prefs.setBoolPref('dom.mms.requestReadReport', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('ril.cellbroadcast.disabled', false,
|
||||
function(value) {
|
||||
Services.prefs.setBoolPref('ril.cellbroadcast.disabled', value);
|
||||
|
|
|
@ -18,7 +18,7 @@ Cu.import("resource://gre/modules/AppsUtils.jsm");
|
|||
Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
|
||||
Cu.import('resource://gre/modules/Keyboard.jsm');
|
||||
Cu.import('resource://gre/modules/ErrorPage.jsm');
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
Cu.import('resource://gre/modules/NetworkStatsService.jsm');
|
||||
#endif
|
||||
|
||||
|
@ -611,7 +611,7 @@ var shell = {
|
|||
|
||||
this.sendEvent(window, 'ContentStart');
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
Cu.import('resource://gre/modules/OperatorApps.jsm');
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "d2dbad943faf566fe36dbe79086127da837af6a3",
|
||||
"revision": "aa1ebd9c011628a4e1a9802fd552ec853610b2f5",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -164,10 +164,12 @@
|
|||
@BINPATH@/components/dom_audiochannel.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_system.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@BINPATH@/components/dom_wifi.xpt
|
||||
@BINPATH@/components/dom_system_gonk.xpt
|
||||
#endif
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
@BINPATH@/components/dom_icc.xpt
|
||||
@BINPATH@/components/dom_cellbroadcast.xpt
|
||||
@BINPATH@/components/dom_wappush.xpt
|
||||
|
@ -399,6 +401,36 @@
|
|||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/nsSidebar.manifest
|
||||
@BINPATH@/components/nsSidebar.js
|
||||
|
||||
; WiFi, NetworkManager, NetworkStats
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@BINPATH@/components/DOMWifiManager.js
|
||||
@BINPATH@/components/DOMWifiManager.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.js
|
||||
@BINPATH@/components/NetworkInterfaceListService.manifest
|
||||
@BINPATH@/components/NetworkManager.js
|
||||
@BINPATH@/components/NetworkManager.manifest
|
||||
@BINPATH@/components/NetworkStatsManager.js
|
||||
@BINPATH@/components/NetworkStatsManager.manifest
|
||||
@BINPATH@/components/NetworkStatsServiceProxy.js
|
||||
@BINPATH@/components/NetworkStatsServiceProxy.manifest
|
||||
@BINPATH@/components/WifiWorker.js
|
||||
@BINPATH@/components/WifiWorker.manifest
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
|
||||
; RIL
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
@BINPATH@/components/MmsService.js
|
||||
@BINPATH@/components/MmsService.manifest
|
||||
@BINPATH@/components/MobileMessageDatabaseService.js
|
||||
@BINPATH@/components/MobileMessageDatabaseService.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/TelephonyProvider.js
|
||||
@BINPATH@/components/TelephonyProvider.manifest
|
||||
#endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
@BINPATH@/components/extensions.manifest
|
||||
@BINPATH@/components/addonManager.js
|
||||
|
@ -464,29 +496,6 @@
|
|||
@BINPATH@/components/webvtt.xpt
|
||||
@BINPATH@/components/WebVTT.manifest
|
||||
@BINPATH@/components/WebVTTParserWrapper.js
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/NetworkManager.manifest
|
||||
@BINPATH@/components/NetworkManager.js
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/MmsService.manifest
|
||||
@BINPATH@/components/MmsService.js
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/MobileMessageDatabaseService.manifest
|
||||
@BINPATH@/components/MobileMessageDatabaseService.js
|
||||
@BINPATH@/components/WifiWorker.js
|
||||
@BINPATH@/components/WifiWorker.manifest
|
||||
@BINPATH@/components/DOMWifiManager.js
|
||||
@BINPATH@/components/DOMWifiManager.manifest
|
||||
@BINPATH@/components/NetworkStatsManager.js
|
||||
@BINPATH@/components/NetworkStatsManager.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.js
|
||||
@BINPATH@/components/TelephonyProvider.manifest
|
||||
@BINPATH@/components/TelephonyProvider.js
|
||||
@BINPATH@/components/NetworkStatsServiceProxy.manifest
|
||||
@BINPATH@/components/NetworkStatsServiceProxy.js
|
||||
#endif
|
||||
#ifdef MOZ_ENABLE_DBUS
|
||||
@BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
|
||||
#endif
|
||||
|
|
|
@ -3014,11 +3014,11 @@ const BrowserSearch = {
|
|||
* allows the search service to provide a different nsISearchSubmission
|
||||
* depending on e.g. where the search is triggered in the UI.
|
||||
*
|
||||
* @return string Name of the search engine used to perform a search or null
|
||||
* if a search was not performed.
|
||||
* @return engine The search engine used to perform a search, or null if no
|
||||
* search was performed.
|
||||
*/
|
||||
loadSearch: function BrowserSearch_search(searchText, useNewTab, purpose) {
|
||||
var engine;
|
||||
_loadSearch: function (searchText, useNewTab, purpose) {
|
||||
let engine;
|
||||
|
||||
// If the search bar is visible, use the current engine, otherwise, fall
|
||||
// back to the default engine.
|
||||
|
@ -3027,7 +3027,7 @@ const BrowserSearch = {
|
|||
else
|
||||
engine = Services.search.defaultEngine;
|
||||
|
||||
var submission = engine.getSubmission(searchText, null, purpose); // HTML response
|
||||
let submission = engine.getSubmission(searchText, null, purpose); // HTML response
|
||||
|
||||
// getSubmission can return null if the engine doesn't have a URL
|
||||
// with a text/html response type. This is unlikely (since
|
||||
|
@ -3044,6 +3044,20 @@ const BrowserSearch = {
|
|||
inBackground: inBackground,
|
||||
relatedToCurrent: true });
|
||||
|
||||
return engine;
|
||||
},
|
||||
|
||||
/**
|
||||
* Just like _loadSearch, but preserving an old API.
|
||||
*
|
||||
* @return string Name of the search engine used to perform a search or null
|
||||
* if a search was not performed.
|
||||
*/
|
||||
loadSearch: function BrowserSearch_search(searchText, useNewTab, purpose) {
|
||||
let engine = BrowserSearch._loadSearch(searchText, useNewTab, purpose);
|
||||
if (!engine) {
|
||||
return null;
|
||||
}
|
||||
return engine.name;
|
||||
},
|
||||
|
||||
|
@ -3054,7 +3068,7 @@ const BrowserSearch = {
|
|||
* BrowserSearch.loadSearch for the preferred API.
|
||||
*/
|
||||
loadSearchFromContext: function (terms) {
|
||||
let engine = BrowserSearch.loadSearch(terms, true, "contextmenu");
|
||||
let engine = BrowserSearch._loadSearch(terms, true, "contextmenu");
|
||||
if (engine) {
|
||||
BrowserSearch.recordSearchInHealthReport(engine, "contextmenu");
|
||||
}
|
||||
|
@ -3080,8 +3094,7 @@ const BrowserSearch = {
|
|||
* FHR records only search counts and nothing pertaining to the search itself.
|
||||
*
|
||||
* @param engine
|
||||
* (string) The name of the engine used to perform the search. This
|
||||
* is typically nsISearchEngine.name.
|
||||
* (nsISearchEngine) The engine handling the search.
|
||||
* @param source
|
||||
* (string) Where the search originated from. See the FHR
|
||||
* SearchesProvider for allowed values.
|
||||
|
|
|
@ -486,7 +486,7 @@ function getNumberOfSearches(aEngineName) {
|
|||
let provider = reporter.getProvider("org.mozilla.searches");
|
||||
ok(provider, "Searches provider is available.");
|
||||
|
||||
let m = provider.getMeasurement("counts", 2);
|
||||
let m = provider.getMeasurement("counts", 3);
|
||||
return m.getValues().then(data => {
|
||||
let now = new Date();
|
||||
let yday = new Date(now);
|
||||
|
|
|
@ -47,7 +47,7 @@ function test() {
|
|||
let provider = reporter.getProvider("org.mozilla.searches");
|
||||
ok(provider, "Searches provider is available.");
|
||||
|
||||
let m = provider.getMeasurement("counts", 2);
|
||||
let m = provider.getMeasurement("counts", 3);
|
||||
m.getValues().then(function onValues(data) {
|
||||
let now = new Date();
|
||||
ok(data.days.hasDay(now), "Have data for today.");
|
||||
|
|
|
@ -23,7 +23,7 @@ function test() {
|
|||
reporter.onInit().then(function onInit() {
|
||||
let provider = reporter.getProvider("org.mozilla.searches");
|
||||
ok(provider, "Searches provider is available.");
|
||||
let m = provider.getMeasurement("counts", 2);
|
||||
let m = provider.getMeasurement("counts", 3);
|
||||
|
||||
m.getValues().then(function onData(data) {
|
||||
let now = new Date();
|
||||
|
|
|
@ -320,9 +320,8 @@ BrowserGlue.prototype = {
|
|||
|
||||
reporter.onInit().then(function record() {
|
||||
try {
|
||||
let name = subject.QueryInterface(Ci.nsISearchEngine).name;
|
||||
reporter.getProvider("org.mozilla.searches").recordSearch(name,
|
||||
"urlbar");
|
||||
let engine = subject.QueryInterface(Ci.nsISearchEngine);
|
||||
reporter.getProvider("org.mozilla.searches").recordSearch(engine, "urlbar");
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@
|
|||
|
||||
// null parameter below specifies HTML response for search
|
||||
var submission = this.currentEngine.getSubmission(aData, null, "searchbar");
|
||||
BrowserSearch.recordSearchInHealthReport(this.currentEngine.name, "searchbar");
|
||||
BrowserSearch.recordSearchInHealthReport(this.currentEngine, "searchbar");
|
||||
openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
|
||||
]]></body>
|
||||
</method>
|
||||
|
|
|
@ -27,14 +27,15 @@ function test() {
|
|||
ok(reporter, "Health Reporter available.");
|
||||
reporter.onInit().then(function onInit() {
|
||||
let provider = reporter.getProvider("org.mozilla.searches");
|
||||
let m = provider.getMeasurement("counts", 2);
|
||||
let m = provider.getMeasurement("counts", 3);
|
||||
|
||||
m.getValues().then(function onData(data) {
|
||||
let now = new Date();
|
||||
let oldCount = 0;
|
||||
|
||||
// Foo engine goes into "other" bucket.
|
||||
let field = "other.searchbar";
|
||||
// Find the right bucket for the "Foo" engine.
|
||||
let engine = Services.search.getEngineByName("Foo");
|
||||
let field = (engine.identifier || "other-Foo") + ".searchbar";
|
||||
|
||||
if (data.days.hasDay(now)) {
|
||||
let day = data.days.getDay(now);
|
||||
|
|
|
@ -306,7 +306,20 @@ TabTarget.prototype = {
|
|||
this._client.connect((aType, aTraits) => {
|
||||
this._client.listTabs(aResponse => {
|
||||
this._root = aResponse;
|
||||
this._form = aResponse.tabs[aResponse.selected];
|
||||
|
||||
let windowUtils = this.window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let outerWindow = windowUtils.outerWindowID;
|
||||
aResponse.tabs.some((tab) => {
|
||||
if (tab.outerWindowID === outerWindow) {
|
||||
this._form = tab;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!this._form) {
|
||||
this._form = aResponse.tabs[aResponse.selected];
|
||||
}
|
||||
attachTab();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -165,11 +165,12 @@ let AboutHome = {
|
|||
Cu.reportError(ex);
|
||||
break;
|
||||
}
|
||||
let engine = Services.search.currentEngine;
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
window.BrowserSearch.recordSearchInHealthReport(data.engineName, "abouthome");
|
||||
window.BrowserSearch.recordSearchInHealthReport(engine, "abouthome");
|
||||
#endif
|
||||
// Trigger a search through nsISearchEngine.getSubmission()
|
||||
let submission = Services.search.currentEngine.getSubmission(data.searchTerms, null, "homepage");
|
||||
let submission = engine.getSubmission(data.searchTerms, null, "homepage");
|
||||
window.loadURI(submission.uri.spec, null, submission.postData);
|
||||
break;
|
||||
}
|
||||
|
|
11
configure.in
11
configure.in
|
@ -1943,7 +1943,7 @@ ia64*-hpux*)
|
|||
no_x=yes
|
||||
if test -n "$gonkdir"; then
|
||||
_PLATFORM_DEFAULT_TOOLKIT=cairo-gonk
|
||||
MOZ_B2G_RIL=1
|
||||
_PLATFORM_HAVE_RIL=1
|
||||
MOZ_B2G_FM=1
|
||||
MOZ_SYNTH_PICO=1
|
||||
else
|
||||
|
@ -7276,9 +7276,14 @@ dnl ========================================================
|
|||
MOZ_ARG_ENABLE_BOOL(b2g-ril,
|
||||
[ --enable-b2g-ril Set compile flags necessary for testing B2G Radio Interface Layer via network sockets ],
|
||||
MOZ_B2G_RIL=1,
|
||||
MOZ_B2G_RIL= )
|
||||
MOZ_B2G_RIL=,
|
||||
MOZ_B2G_RIL=$_PLATFORM_HAVE_RIL )
|
||||
if test -n "$MOZ_B2G_RIL"; then
|
||||
AC_DEFINE(MOZ_B2G_RIL)
|
||||
if test -n "$_PLATFORM_HAVE_RIL"; then
|
||||
AC_DEFINE(MOZ_B2G_RIL)
|
||||
else
|
||||
AC_MSG_ERROR([b2g-ril cannot be enabled because target platform doesn't support it.])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(MOZ_B2G_RIL)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(srcdir)/../../../layout/xul/tree/ \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../../../dom/wifi \
|
||||
$(NULL)
|
||||
|
|
|
@ -87,7 +87,9 @@ nsresult MediaOmxReader::InitOmxDecoder()
|
|||
dataSource->initCheck();
|
||||
|
||||
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
|
||||
|
||||
if (!extractor.get()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
|
||||
if (!mOmxDecoder->Init(extractor)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsIDOMWakeLock.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "mozilla/dom/MobileMessageManager.h"
|
||||
#include "mozilla/dom/Telephony.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "nsISiteSpecificUserAgent.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
@ -38,9 +39,8 @@
|
|||
#include "nsGlobalWindow.h"
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "mozilla/dom/IccManager.h"
|
||||
#include "MobileConnection.h"
|
||||
#include "mozilla/dom/CellBroadcast.h"
|
||||
#include "mozilla/dom/Telephony.h"
|
||||
#include "mozilla/dom/network/MobileConnection.h"
|
||||
#include "mozilla/dom/Voicemail.h"
|
||||
#endif
|
||||
#include "nsIIdleObserver.h"
|
||||
|
@ -138,12 +138,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
|
@ -209,6 +209,10 @@ Navigator::Invalidate()
|
|||
mMobileMessageManager = nullptr;
|
||||
}
|
||||
|
||||
if (mTelephony) {
|
||||
mTelephony = nullptr;
|
||||
}
|
||||
|
||||
if (mConnection) {
|
||||
mConnection->Shutdown();
|
||||
mConnection = nullptr;
|
||||
|
@ -229,10 +233,6 @@ Navigator::Invalidate()
|
|||
mIccManager = nullptr;
|
||||
}
|
||||
|
||||
if (mTelephony) {
|
||||
mTelephony = nullptr;
|
||||
}
|
||||
|
||||
if (mVoicemail) {
|
||||
mVoicemail = nullptr;
|
||||
}
|
||||
|
@ -1165,6 +1165,20 @@ Navigator::GetMozMobileMessage()
|
|||
return mMobileMessageManager;
|
||||
}
|
||||
|
||||
Telephony*
|
||||
Navigator::GetMozTelephony(ErrorResult& aRv)
|
||||
{
|
||||
if (!mTelephony) {
|
||||
if (!mWindow) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
mTelephony = Telephony::Create(mWindow, aRv);
|
||||
}
|
||||
|
||||
return mTelephony;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
||||
CellBroadcast*
|
||||
|
@ -1181,20 +1195,6 @@ Navigator::GetMozCellBroadcast(ErrorResult& aRv)
|
|||
return mCellBroadcast;
|
||||
}
|
||||
|
||||
Telephony*
|
||||
Navigator::GetMozTelephony(ErrorResult& aRv)
|
||||
{
|
||||
if (!mTelephony) {
|
||||
if (!mWindow) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
mTelephony = Telephony::Create(mWindow, aRv);
|
||||
}
|
||||
|
||||
return mTelephony;
|
||||
}
|
||||
|
||||
Voicemail*
|
||||
Navigator::GetMozVoicemail(ErrorResult& aRv)
|
||||
{
|
||||
|
@ -1697,15 +1697,6 @@ Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
|
||||
return win && nsDOMCameraManager::CheckPermission(win);
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasTelephonySupport(JSContext* /* unused */, JSObject* aGlobal)
|
||||
|
@ -1719,6 +1710,15 @@ Navigator::HasTelephonySupport(JSContext* /* unused */, JSObject* aGlobal)
|
|||
return win && CheckPermission(win, "telephony");
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
|
||||
return win && nsDOMCameraManager::CheckPermission(win);
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasMobileConnectionSupport(JSContext* /* unused */,
|
||||
|
|
|
@ -86,11 +86,11 @@ class BluetoothManager;
|
|||
#ifdef MOZ_B2G_RIL
|
||||
class CellBroadcast;
|
||||
class IccManager;
|
||||
class Telephony;
|
||||
class Voicemail;
|
||||
#endif
|
||||
|
||||
class PowerManager;
|
||||
class Telephony;
|
||||
|
||||
namespace time {
|
||||
class TimeManager;
|
||||
|
@ -211,6 +211,7 @@ public:
|
|||
bool MozIsLocallyAvailable(const nsAString& aURI, bool aWhenOffline,
|
||||
ErrorResult& aRv);
|
||||
nsIDOMMozMobileMessageManager* GetMozMobileMessage();
|
||||
Telephony* GetMozTelephony(ErrorResult& aRv);
|
||||
nsIDOMMozConnection* GetMozConnection();
|
||||
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
|
||||
void MozSetMessageHandler(const nsAString& aType,
|
||||
|
@ -218,7 +219,6 @@ public:
|
|||
ErrorResult& aRv);
|
||||
bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
Telephony* GetMozTelephony(ErrorResult& aRv);
|
||||
nsIDOMMozMobileConnection* GetMozMobileConnection(ErrorResult& aRv);
|
||||
CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
|
||||
Voicemail* GetMozVoicemail(ErrorResult& aRv);
|
||||
|
@ -268,11 +268,11 @@ public:
|
|||
}
|
||||
static bool HasMobileMessageSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasTelephonySupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasCameraSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
static bool HasTelephonySupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasMobileConnectionSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasCellBroadcastSupport(JSContext* /* unused */,
|
||||
|
@ -326,12 +326,12 @@ private:
|
|||
#endif
|
||||
nsRefPtr<PowerManager> mPowerManager;
|
||||
nsRefPtr<MobileMessageManager> mMobileMessageManager;
|
||||
nsRefPtr<Telephony> mTelephony;
|
||||
nsRefPtr<network::Connection> mConnection;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsRefPtr<network::MobileConnection> mMobileConnection;
|
||||
nsRefPtr<CellBroadcast> mCellBroadcast;
|
||||
nsRefPtr<IccManager> mIccManager;
|
||||
nsRefPtr<Telephony> mTelephony;
|
||||
nsRefPtr<Voicemail> mVoicemail;
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
|
|
|
@ -128,7 +128,6 @@ LIBRARY_NAME = 'jsdombase_s'
|
|||
LOCAL_INCLUDES += [
|
||||
'../battery',
|
||||
'../bluetooth',
|
||||
'../icc/src',
|
||||
'../media',
|
||||
'../network/src',
|
||||
'../src/geolocation',
|
||||
|
@ -144,7 +143,7 @@ LOCAL_INCLUDES += [
|
|||
'/layout/xul/base/src',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
LOCAL_INCLUDES += [
|
||||
'../fmradio',
|
||||
'../system/gonk',
|
||||
|
|
|
@ -881,6 +881,7 @@ BluetoothAdapter::IsScoConnected(ErrorResult& aRv)
|
|||
already_AddRefed<DOMRequest>
|
||||
BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -899,11 +900,16 @@ BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
|
|||
bs->AnswerWaitingCall(results);
|
||||
|
||||
return request.forget();
|
||||
#else
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
#endif // MOZ_B2G_RIL
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -922,11 +928,16 @@ BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
|
|||
bs->IgnoreWaitingCall(results);
|
||||
|
||||
return request.forget();
|
||||
#else
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
#endif // MOZ_B2G_RIL
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -945,6 +956,10 @@ BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
|
|||
bs->ToggleCalls(results);
|
||||
|
||||
return request.forget();
|
||||
#else
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
#endif // MOZ_B2G_RIL
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
|
|
|
@ -15,19 +15,24 @@
|
|||
#include "BluetoothUtils.h"
|
||||
#include "BluetoothUuid.h"
|
||||
|
||||
#include "MobileConnection.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIAudioManager.h"
|
||||
#include "nsIDOMIccInfo.h"
|
||||
#include "nsIIccProvider.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsISettingsService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIDOMIccInfo.h"
|
||||
#include "nsIDOMMobileConnection.h"
|
||||
#include "nsIIccProvider.h"
|
||||
#include "nsIMobileConnectionProvider.h"
|
||||
#include "nsITelephonyProvider.h"
|
||||
#include "nsRadioInterfaceLayer.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BRSF bitmask of AG supported features. See 4.34.1 "Bluetooth Defined AT
|
||||
|
@ -44,6 +49,7 @@
|
|||
#define BRSF_BIT_EXTENDED_ERR_RESULT_CODES (1 << 8)
|
||||
#define BRSF_BIT_CODEC_NEGOTIATION (1 << 9)
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/**
|
||||
* These constants are used in result code such as +CLIP and +CCWA. The value
|
||||
* of these constants is the same as TOA_INTERNATIONAL/TOA_UNKNOWN defined in
|
||||
|
@ -51,6 +57,7 @@
|
|||
*/
|
||||
#define TOA_UNKNOWN 0x81
|
||||
#define TOA_INTERNATIONAL 0x91
|
||||
#endif
|
||||
|
||||
#define CR_LF "\xd\xa";
|
||||
|
||||
|
@ -66,6 +73,7 @@ namespace {
|
|||
bool sInShutdown = false;
|
||||
static const char kHfpCrlf[] = "\xd\xa";
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Sending ringtone related
|
||||
static bool sStopSendingRingFlag = true;
|
||||
static int sRingInterval = 3000; //unit: ms
|
||||
|
@ -79,8 +87,10 @@ namespace {
|
|||
// The mechanism should be revised once we know the exact time at which
|
||||
// Dialer stops playing.
|
||||
static int sBusyToneInterval = 3700; //unit: ms
|
||||
#endif // MOZ_B2G_RIL
|
||||
} // anonymous namespace
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/* CallState for sCINDItems[CINDType::CALL].value
|
||||
* - NO_CALL: there are no calls in progress
|
||||
* - IN_PROGRESS: at least one call is in progress
|
||||
|
@ -113,6 +123,7 @@ enum CallHeldState {
|
|||
ONHOLD_ACTIVE,
|
||||
ONHOLD_NOACTIVE
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
|
@ -123,23 +134,27 @@ typedef struct {
|
|||
|
||||
enum CINDType {
|
||||
BATTCHG = 1,
|
||||
#ifdef MOZ_B2G_RIL
|
||||
CALL,
|
||||
CALLHELD,
|
||||
CALLSETUP,
|
||||
SERVICE,
|
||||
SIGNAL,
|
||||
ROAM
|
||||
#endif
|
||||
};
|
||||
|
||||
static CINDItem sCINDItems[] = {
|
||||
{},
|
||||
{"battchg", "0-5", 5, true},
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{"call", "0,1", CallState::NO_CALL, true},
|
||||
{"callheld", "0-2", CallHeldState::NO_CALLHELD, true},
|
||||
{"callsetup", "0-3", CallSetupState::NO_CALLSETUP, true},
|
||||
{"service", "0,1", 0, true},
|
||||
{"signal", "0-5", 0, true},
|
||||
{"roam", "0,1", 0, true}
|
||||
#endif
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::GetVolumeTask : public nsISettingsServiceCallback
|
||||
|
@ -206,6 +221,7 @@ BluetoothHfpManager::Notify(const hal::BatteryInformation& aBatteryInfo)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class BluetoothHfpManager::RespondToBLDNTask : public Task
|
||||
{
|
||||
private:
|
||||
|
@ -265,6 +281,7 @@ private:
|
|||
nsString mNumber;
|
||||
int mType;
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
class BluetoothHfpManager::CloseScoTask : public Task
|
||||
{
|
||||
|
@ -277,6 +294,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
static bool
|
||||
IsValidDtmf(const char aChar) {
|
||||
// Valid DTMF: [*#0-9ABCD]
|
||||
|
@ -319,6 +337,7 @@ Call::IsActive()
|
|||
{
|
||||
return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
/**
|
||||
* BluetoothHfpManager
|
||||
|
@ -328,6 +347,7 @@ BluetoothHfpManager::BluetoothHfpManager() : mController(nullptr)
|
|||
Reset();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothHfpManager::ResetCallArray()
|
||||
{
|
||||
|
@ -341,25 +361,31 @@ BluetoothHfpManager::ResetCallArray()
|
|||
mCdmaSecondCall.Reset();
|
||||
}
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
BluetoothHfpManager::Reset()
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
sStopSendingRingFlag = true;
|
||||
sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
|
||||
sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
|
||||
sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
|
||||
#endif
|
||||
for (uint8_t i = 1; i < ArrayLength(sCINDItems); i++) {
|
||||
sCINDItems[i].activated = true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
mCCWA = false;
|
||||
mCLIP = false;
|
||||
mDialingRequestProcessed = true;
|
||||
#endif
|
||||
mCMEE = false;
|
||||
mCMER = false;
|
||||
mReceiveVgsFlag = false;
|
||||
mDialingRequestProcessed = true;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// We disable BSIR by default as it requires OEM implement BT SCO + SPEAKER
|
||||
// output audio path in audio driver. OEM can enable BSIR by setting
|
||||
// mBSIR=true here.
|
||||
|
@ -368,6 +394,7 @@ BluetoothHfpManager::Reset()
|
|||
mBSIR = false;
|
||||
|
||||
ResetCallArray();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -386,11 +413,13 @@ BluetoothHfpManager::Init()
|
|||
|
||||
hal::RegisterBatteryObserver(this);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
mListener = new BluetoothRilListener();
|
||||
if (!mListener->StartListening()) {
|
||||
BT_WARNING("Failed to start listening RIL");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISettingsService> settings =
|
||||
do_GetService("@mozilla.org/settingsService;1");
|
||||
|
@ -417,10 +446,12 @@ BluetoothHfpManager::Init()
|
|||
|
||||
BluetoothHfpManager::~BluetoothHfpManager()
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (!mListener->StopListening()) {
|
||||
BT_WARNING("Failed to stop listening RIL");
|
||||
}
|
||||
mListener = nullptr;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
@ -486,6 +517,7 @@ BluetoothHfpManager::NotifyConnectionStatusChanged(const nsAString& aType)
|
|||
DispatchStatusChangedEvent(eventName, mDeviceAddress, status);
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothHfpManager::NotifyDialer(const nsAString& aCommand)
|
||||
{
|
||||
|
@ -502,6 +534,7 @@ BluetoothHfpManager::NotifyDialer(const nsAString& aCommand)
|
|||
BT_WARNING("Failed to broadcast system message to dialer");
|
||||
}
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
|
||||
|
@ -551,6 +584,7 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothHfpManager::HandleVoiceConnectionChanged()
|
||||
{
|
||||
|
@ -559,7 +593,8 @@ BluetoothHfpManager::HandleVoiceConnectionChanged()
|
|||
NS_ENSURE_TRUE_VOID(connection);
|
||||
|
||||
nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
|
||||
connection->GetVoiceConnectionInfo(getter_AddRefs(voiceInfo));
|
||||
// TODO: Bug 921991 - B2G BT: support multiple sim cards
|
||||
connection->GetVoiceConnectionInfo(0, getter_AddRefs(voiceInfo));
|
||||
NS_ENSURE_TRUE_VOID(voiceInfo);
|
||||
|
||||
nsString type;
|
||||
|
@ -595,7 +630,8 @@ BluetoothHfpManager::HandleVoiceConnectionChanged()
|
|||
* - manual: set mNetworkSelectionMode to 1 (manual)
|
||||
*/
|
||||
nsString mode;
|
||||
connection->GetNetworkSelectionMode(mode);
|
||||
// TODO: Bug 921991 - B2G BT: support multiple sim cards
|
||||
connection->GetNetworkSelectionMode(0, mode);
|
||||
if (mode.EqualsLiteral("manual")) {
|
||||
mNetworkSelectionMode = 1;
|
||||
} else {
|
||||
|
@ -636,6 +672,7 @@ BluetoothHfpManager::HandleIccInfoChanged()
|
|||
NS_ENSURE_TRUE_VOID(gsmIccInfo);
|
||||
gsmIccInfo->GetMsisdn(mMsisdn);
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
BluetoothHfpManager::HandleShutdown()
|
||||
|
@ -663,6 +700,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
// For more information, please refer to 4.34.1 "Bluetooth Defined AT
|
||||
// Capabilities" in Bluetooth hands-free profile 1.6
|
||||
if (msg.Find("AT+BRSF=") != -1) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
uint32_t brsf = BRSF_BIT_ABILITY_TO_REJECT_CALL |
|
||||
BRSF_BIT_ENHANCED_CALL_STATUS;
|
||||
|
||||
|
@ -675,6 +713,9 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
if (mBSIR) {
|
||||
brsf |= BRSF_BIT_IN_BAND_RING_TONE;
|
||||
}
|
||||
#else
|
||||
uint32_t brsf = 0;
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
SendCommand("+BRSF: ", brsf);
|
||||
} else if (msg.Find("AT+CIND=?") != -1) {
|
||||
|
@ -715,6 +756,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
// AT+CMEE = 1: use numeric <err>
|
||||
// AT+CMEE = 2: use verbose <err>
|
||||
mCMEE = !atCommandValues[0].EqualsLiteral("0");
|
||||
#ifdef MOZ_B2G_RIL
|
||||
} else if (msg.Find("AT+COPS=") != -1) {
|
||||
ParseAtCommand(msg, 8, atCommandValues);
|
||||
|
||||
|
@ -753,6 +795,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
message += atCommandValues[0].get()[0];
|
||||
NotifyDialer(NS_ConvertUTF8toUTF16(message));
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
} else if (msg.Find("AT+VGM=") != -1) {
|
||||
ParseAtCommand(msg, 7, atCommandValues);
|
||||
|
||||
|
@ -770,6 +813,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
|
||||
NS_ASSERTION(vgm >= 0 && vgm <= 15, "Received invalid VGM value");
|
||||
mCurrentVgm = vgm;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
} else if (msg.Find("AT+CHLD=?") != -1) {
|
||||
SendLine("+CHLD: (0,1,2)");
|
||||
} else if (msg.Find("AT+CHLD=") != -1) {
|
||||
|
@ -820,6 +864,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
SendLine("ERROR");
|
||||
return;
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
} else if (msg.Find("AT+VGS=") != -1) {
|
||||
// Adjust volume by headset
|
||||
mReceiveVgsFlag = true;
|
||||
|
@ -847,6 +892,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
data.AppendInt(newVgs);
|
||||
os->NotifyObservers(nullptr, "bluetooth-volume-change", data.get());
|
||||
#ifdef MOZ_B2G_RIL
|
||||
} else if ((msg.Find("AT+BLDN") != -1) || (msg.Find("ATD>") != -1)) {
|
||||
// Dialer app of FFOS v1 does not have plan to support Memory Dailing.
|
||||
// However, in order to pass Bluetooth HFP certification, we still have to
|
||||
|
@ -972,6 +1018,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
|||
// Ignore requests to activate/deactivate mandatory indicators
|
||||
}
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
} else {
|
||||
nsCString warningMsg;
|
||||
warningMsg.Append(NS_LITERAL_CSTRING("Unsupported AT command: "));
|
||||
|
@ -1096,6 +1143,7 @@ BluetoothHfpManager::Disconnect(BluetoothProfileController* aController)
|
|||
mSocket->Disconnect();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothHfpManager::SendCCWA(const nsAString& aNumber, int aType)
|
||||
{
|
||||
|
@ -1157,6 +1205,7 @@ BluetoothHfpManager::SendCLCC(const Call& aCall, int aIndex)
|
|||
|
||||
return SendLine(message.get());
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
bool
|
||||
BluetoothHfpManager::SendLine(const char* aMessage)
|
||||
|
@ -1222,6 +1271,7 @@ BluetoothHfpManager::SendCommand(const char* aCommand, uint32_t aValue)
|
|||
message.AppendLiteral(",");
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_B2G_RIL
|
||||
} else if (!strcmp(aCommand, "+CLCC: ")) {
|
||||
bool rv = true;
|
||||
uint32_t callNumbers = mCurrentCallArray.Length();
|
||||
|
@ -1238,6 +1288,7 @@ BluetoothHfpManager::SendCommand(const char* aCommand, uint32_t aValue)
|
|||
}
|
||||
|
||||
return rv;
|
||||
#endif // MOZ_B2G_RIL
|
||||
} else {
|
||||
message.AppendInt(aValue);
|
||||
}
|
||||
|
@ -1245,6 +1296,7 @@ BluetoothHfpManager::SendCommand(const char* aCommand, uint32_t aValue)
|
|||
return SendLine(message.get());
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothHfpManager::UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend)
|
||||
{
|
||||
|
@ -1525,12 +1577,15 @@ BluetoothHfpManager::ToggleCalls()
|
|||
nsITelephonyProvider::CALL_STATE_HELD :
|
||||
nsITelephonyProvider::CALL_STATE_CONNECTED;
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
|
||||
{
|
||||
MOZ_ASSERT(aSocket);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
MOZ_ASSERT(mListener);
|
||||
#endif
|
||||
|
||||
// Success to create a SCO socket
|
||||
if (aSocket == mScoSocket) {
|
||||
|
@ -1559,10 +1614,12 @@ BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
|
|||
mHandsfreeSocket = nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Enumerate current calls
|
||||
mListener->EnumerateCalls();
|
||||
|
||||
mFirstCKPD = true;
|
||||
#endif
|
||||
|
||||
// Cache device path for NotifySettings() since we can't get socket address
|
||||
// when a headset disconnect with us
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "BluetoothRilListener.h"
|
||||
#endif
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "mozilla/Hal.h"
|
||||
|
@ -18,6 +20,8 @@ BEGIN_BLUETOOTH_NAMESPACE
|
|||
|
||||
class BluetoothReplyRunnable;
|
||||
class BluetoothSocket;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class Call;
|
||||
|
||||
/**
|
||||
|
@ -67,6 +71,7 @@ public:
|
|||
nsString mNumber;
|
||||
int mType;
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
class BluetoothHfpManager : public BluetoothSocketObserver
|
||||
, public BluetoothProfileManagerBase
|
||||
|
@ -109,6 +114,7 @@ public:
|
|||
bool DisconnectSco();
|
||||
bool ListenSco();
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/**
|
||||
* @param aSend A boolean indicates whether we need to notify headset or not
|
||||
*/
|
||||
|
@ -117,26 +123,33 @@ public:
|
|||
const bool aIsOutgoing, bool aSend);
|
||||
void HandleIccInfoChanged();
|
||||
void HandleVoiceConnectionChanged();
|
||||
#endif
|
||||
|
||||
bool IsConnected();
|
||||
bool IsScoConnected();
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// CDMA-specific functions
|
||||
void UpdateSecondNumber(const nsAString& aNumber);
|
||||
void AnswerWaitingCall();
|
||||
void IgnoreWaitingCall();
|
||||
void ToggleCalls();
|
||||
#endif
|
||||
|
||||
private:
|
||||
class CloseScoTask;
|
||||
class GetVolumeTask;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class RespondToBLDNTask;
|
||||
class SendRingIndicatorTask;
|
||||
#endif
|
||||
|
||||
friend class CloseScoTask;
|
||||
friend class GetVolumeTask;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
friend class RespondToBLDNTask;
|
||||
friend class SendRingIndicatorTask;
|
||||
#endif
|
||||
friend class BluetoothHfpManagerObserver;
|
||||
|
||||
BluetoothHfpManager();
|
||||
|
@ -146,41 +159,55 @@ private:
|
|||
bool Init();
|
||||
void Notify(const hal::BatteryInformation& aBatteryInfo);
|
||||
void Reset();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void ResetCallArray();
|
||||
uint32_t FindFirstCall(uint16_t aState);
|
||||
uint32_t GetNumberOfCalls(uint16_t aState);
|
||||
PhoneType GetPhoneType(const nsAString& aType);
|
||||
#endif
|
||||
|
||||
void NotifyConnectionStatusChanged(const nsAString& aType);
|
||||
void NotifyDialer(const nsAString& aCommand);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void SendCCWA(const nsAString& aNumber, int aType);
|
||||
bool SendCLCC(const Call& aCall, int aIndex);
|
||||
#endif
|
||||
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
|
||||
bool SendLine(const char* aMessage);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
|
||||
#endif
|
||||
void OnScoConnectSuccess();
|
||||
void OnScoConnectError();
|
||||
void OnScoDisconnect();
|
||||
|
||||
int mCurrentVgs;
|
||||
int mCurrentVgm;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mBSIR;
|
||||
bool mCCWA;
|
||||
bool mCLIP;
|
||||
#endif
|
||||
bool mCMEE;
|
||||
bool mCMER;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mFirstCKPD;
|
||||
int mNetworkSelectionMode;
|
||||
PhoneType mPhoneType;
|
||||
#endif
|
||||
bool mReceiveVgsFlag;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mDialingRequestProcessed;
|
||||
#endif
|
||||
nsString mDeviceAddress;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsString mMsisdn;
|
||||
nsString mOperatorName;
|
||||
|
||||
nsTArray<Call> mCurrentCallArray;
|
||||
nsAutoPtr<BluetoothRilListener> mListener;
|
||||
#endif
|
||||
nsRefPtr<BluetoothProfileController> mController;
|
||||
nsRefPtr<BluetoothReplyRunnable> mScoRunnable;
|
||||
|
||||
|
@ -198,8 +225,10 @@ private:
|
|||
nsRefPtr<BluetoothSocket> mScoSocket;
|
||||
SocketConnectionStatus mScoSocketStatus;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// CDMA-specific variable
|
||||
Call mCdmaSecondCall;
|
||||
#endif
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
|
|
@ -125,6 +125,12 @@ MobileConnectionListener::NotifyOtaStatusChanged(const nsAString & status)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileConnectionListener::NotifyIccChanged()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* TelephonyListener Implementation
|
||||
*/
|
||||
|
@ -292,8 +298,9 @@ BluetoothRilListener::StartMobileConnectionListening()
|
|||
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(provider, false);
|
||||
|
||||
// TODO: Bug 921991 - B2G BT: support multiple sim cards
|
||||
nsresult rv = provider->
|
||||
RegisterMobileConnectionMsg(mMobileConnectionListener);
|
||||
RegisterMobileConnectionMsg(0, mMobileConnectionListener);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
|
@ -304,8 +311,9 @@ BluetoothRilListener::StopMobileConnectionListening()
|
|||
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(provider, false);
|
||||
|
||||
// TODO: Bug 921991 - B2G BT: support multiple sim cards
|
||||
nsresult rv = provider->
|
||||
UnregisterMobileConnectionMsg(mMobileConnectionListener);
|
||||
UnregisterMobileConnectionMsg(0, mMobileConnectionListener);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -266,6 +266,7 @@ public:
|
|||
virtual void
|
||||
IsScoConnected(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
virtual void
|
||||
AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
|
@ -274,6 +275,7 @@ public:
|
|||
|
||||
virtual void
|
||||
ToggleCalls(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
#endif
|
||||
|
||||
virtual void
|
||||
SendMetaData(const nsAString& aTitle,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/*
|
||||
** Copyright 2006, The Android Open Source Project
|
||||
|
@ -31,6 +31,8 @@ using namespace mozilla;
|
|||
using namespace mozilla::ipc;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef char bdstr_t[18];
|
||||
|
||||
/**
|
||||
* Classes only used in this file
|
||||
*/
|
||||
|
@ -63,6 +65,11 @@ private:
|
|||
static bluetooth_device_t* sBtDevice;
|
||||
static const bt_interface_t* sBtInterface;
|
||||
static bool sIsBtEnabled = false;
|
||||
static bool sAdapterDiscoverable = false;
|
||||
static nsString sAdapterBdAddress;
|
||||
static nsString sAdapterBdName;
|
||||
static uint32_t sAdapterDiscoverableTimeout;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
|
||||
|
||||
/**
|
||||
* Static callback functions
|
||||
|
@ -72,7 +79,7 @@ AdapterStateChangeCallback(bt_state_t aStatus)
|
|||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
BT_LOGD("Enter: %s, BT_STATE:%d", __FUNCTION__, aStatus);
|
||||
BT_LOGD("%s, BT_STATE:%d", __FUNCTION__, aStatus);
|
||||
nsAutoString signalName;
|
||||
if (aStatus == BT_STATE_ON) {
|
||||
sIsBtEnabled = true;
|
||||
|
@ -90,9 +97,85 @@ AdapterStateChangeCallback(bt_state_t aStatus)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
|
||||
{
|
||||
uint8_t* addr = aBdAddressType->address;
|
||||
bdstr_t bdstr;
|
||||
|
||||
sprintf((char*)bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
(int)addr[0],(int)addr[1],(int)addr[2],
|
||||
(int)addr[3],(int)addr[4],(int)addr[5]);
|
||||
|
||||
aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr);
|
||||
}
|
||||
|
||||
static void
|
||||
AdapterPropertiesChangeCallback(bt_status_t aStatus, int aNumProperties,
|
||||
bt_property_t *aProperties)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
BluetoothValue propertyValue;
|
||||
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
||||
|
||||
for (int i = 0; i < aNumProperties; i++) {
|
||||
bt_property_t p = aProperties[i];
|
||||
|
||||
if (p.type == BT_PROPERTY_BDADDR) {
|
||||
BdAddressTypeToString((bt_bdaddr_t*)p.val, sAdapterBdAddress);
|
||||
propertyValue = sAdapterBdAddress;
|
||||
propertiesArray.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Address"), propertyValue));
|
||||
} else if (p.type == BT_PROPERTY_BDNAME) {
|
||||
// Construct nsCString here because Bd name returned from bluedroid
|
||||
// is missing a null terminated character after SetProperty.
|
||||
propertyValue = sAdapterBdName = NS_ConvertUTF8toUTF16(
|
||||
nsCString((char*)p.val, p.len));
|
||||
propertiesArray.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Name"), propertyValue));
|
||||
} else if (p.type == BT_PROPERTY_ADAPTER_SCAN_MODE) {
|
||||
propertyValue = sAdapterDiscoverable = *(uint32_t*)p.val;
|
||||
propertiesArray.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Discoverable"), propertyValue));
|
||||
} else if (p.type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) {
|
||||
propertyValue = sAdapterDiscoverableTimeout = *(uint32_t*)p.val;
|
||||
propertiesArray.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("DiscoverableTimeout"),
|
||||
propertyValue));
|
||||
} else if (p.type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
|
||||
//FIXME: This will be implemented in the later patchset
|
||||
return;
|
||||
} else if (p.type == BT_PROPERTY_UUIDS) {
|
||||
//FIXME: This will be implemented in the later patchset
|
||||
return;
|
||||
} else {
|
||||
BT_LOGR("Unhandled adapter property type: %d", p.type);
|
||||
return;
|
||||
}
|
||||
|
||||
BluetoothValue value(propertiesArray);
|
||||
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
|
||||
NS_LITERAL_STRING(KEY_ADAPTER), value);
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
// bluedroid BTU task was stored in the task queue, see GKI_send_msg
|
||||
if (!sSetPropertyRunnableArray.IsEmpty()) {
|
||||
DispatchBluetoothReply(sSetPropertyRunnableArray[0], BluetoothValue(true),
|
||||
EmptyString());
|
||||
sSetPropertyRunnableArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bt_callbacks_t sBluetoothCallbacks = {
|
||||
sizeof(sBluetoothCallbacks),
|
||||
AdapterStateChangeCallback
|
||||
AdapterStateChangeCallback,
|
||||
AdapterPropertiesChangeCallback
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -145,6 +228,32 @@ StartStopGonkBluetooth(bool aShouldEnable)
|
|||
return (ret == BT_STATUS_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static void
|
||||
ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable,
|
||||
int aStatusCode, const nsAString& aCustomMsg)
|
||||
{
|
||||
MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr");
|
||||
nsAutoString replyError;
|
||||
|
||||
replyError.Assign(aCustomMsg);
|
||||
if (aStatusCode == BT_STATUS_BUSY) {
|
||||
replyError.AppendLiteral(":BT_STATUS_BUSY");
|
||||
} else if (aStatusCode == BT_STATUS_NOT_READY) {
|
||||
replyError.AppendLiteral(":BT_STATUS_NOT_READY");
|
||||
} else if (aStatusCode == BT_STATUS_DONE) {
|
||||
replyError.AppendLiteral(":BT_STATUS_DONE");
|
||||
} else if (aStatusCode == BT_STATUS_AUTH_FAILURE) {
|
||||
replyError.AppendLiteral(":BT_STATUS_AUTH_FAILURE");
|
||||
} else if (aStatusCode == BT_STATUS_RMT_DEV_DOWN) {
|
||||
replyError.AppendLiteral(":BT_STATUS_RMT_DEV_DOWN");
|
||||
} else if (aStatusCode == BT_STATUS_FAIL) {
|
||||
replyError.AppendLiteral(":BT_STATUS_FAIL");
|
||||
}
|
||||
|
||||
DispatchBluetoothReply(aBluetoothReplyRunnable, BluetoothValue(true),
|
||||
replyError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Member functions
|
||||
*/
|
||||
|
@ -191,6 +300,19 @@ nsresult
|
|||
BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Name"), sAdapterBdName));
|
||||
|
||||
nsAutoString replyError;
|
||||
DispatchBluetoothReply(runnable.get(), v, replyError);
|
||||
|
||||
runnable.forget();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -235,6 +357,50 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
|
|||
const BluetoothNamedValue& aValue,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
const nsString propName = aValue.name();
|
||||
bt_property_t prop;
|
||||
nsString str;
|
||||
|
||||
// For Bluedroid, it's necessary to check property name for SetProperty
|
||||
if (propName.EqualsLiteral("Name")) {
|
||||
prop.type = BT_PROPERTY_BDNAME;
|
||||
} else if (propName.EqualsLiteral("Discoverable")) {
|
||||
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
|
||||
} else if (propName.EqualsLiteral("DiscoverableTimeout")) {
|
||||
prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
|
||||
} else {
|
||||
BT_LOGR("Warning: Property type is not supported yet, type: %d", prop.type);
|
||||
}
|
||||
|
||||
if (aValue.value().type() == BluetoothValue::Tuint32_t) {
|
||||
// Set discoverable timeout
|
||||
prop.val = (void*)aValue.value().get_uint32_t();
|
||||
} else if (aValue.value().type() == BluetoothValue::TnsString) {
|
||||
// Set name
|
||||
str = aValue.value().get_nsString();
|
||||
const char* name = NS_ConvertUTF16toUTF8(str).get();
|
||||
prop.val = (void*)name;
|
||||
prop.len = strlen(name);
|
||||
} else if (aValue.value().type() == BluetoothValue::Tbool) {
|
||||
bt_scan_mode_t mode = aValue.value().get_bool() ?
|
||||
BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE :
|
||||
BT_SCAN_MODE_CONNECTABLE;
|
||||
bt_scan_mode_t* sss = &mode;
|
||||
prop.val = (void*)sss;
|
||||
prop.len = sizeof(sss);
|
||||
} else {
|
||||
BT_LOGR("SetProperty but the property cannot be recognized correctly.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
sSetPropertyRunnableArray.AppendElement(aRunnable);
|
||||
int ret = sBtInterface->set_adapter_property(&prop);
|
||||
|
||||
if (ret != BT_STATUS_SUCCESS)
|
||||
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetProperty"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -226,12 +226,14 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
|||
return actor->DoRequest(aRequest.get_DisconnectScoRequest());
|
||||
case Request::TIsScoConnectedRequest:
|
||||
return actor->DoRequest(aRequest.get_IsScoConnectedRequest());
|
||||
#ifdef MOZ_B2G_RIL
|
||||
case Request::TAnswerWaitingCallRequest:
|
||||
return actor->DoRequest(aRequest.get_AnswerWaitingCallRequest());
|
||||
case Request::TIgnoreWaitingCallRequest:
|
||||
return actor->DoRequest(aRequest.get_IgnoreWaitingCallRequest());
|
||||
case Request::TToggleCallsRequest:
|
||||
return actor->DoRequest(aRequest.get_ToggleCallsRequest());
|
||||
#endif
|
||||
case Request::TSendMetaDataRequest:
|
||||
return actor->DoRequest(aRequest.get_SendMetaDataRequest());
|
||||
case Request::TSendPlayStatusRequest:
|
||||
|
@ -581,6 +583,7 @@ BluetoothRequestParent::DoRequest(const IsScoConnectedRequest& aRequest)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const AnswerWaitingCallRequest& aRequest)
|
||||
{
|
||||
|
@ -613,6 +616,7 @@ BluetoothRequestParent::DoRequest(const ToggleCallsRequest& aRequest)
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const SendMetaDataRequest& aRequest)
|
||||
|
|
|
@ -190,6 +190,7 @@ protected:
|
|||
bool
|
||||
DoRequest(const IsScoConnectedRequest& aRequest);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool
|
||||
DoRequest(const AnswerWaitingCallRequest& aRequest);
|
||||
|
||||
|
@ -198,6 +199,7 @@ protected:
|
|||
|
||||
bool
|
||||
DoRequest(const ToggleCallsRequest& aRequest);
|
||||
#endif
|
||||
|
||||
bool
|
||||
DoRequest(const SendMetaDataRequest& aRequest);
|
||||
|
|
|
@ -328,6 +328,7 @@ BluetoothServiceChildProcess::IsScoConnected(BluetoothReplyRunnable* aRunnable)
|
|||
SendRequest(aRunnable, IsScoConnectedRequest());
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothServiceChildProcess::AnswerWaitingCall(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
|
@ -348,6 +349,7 @@ BluetoothServiceChildProcess::ToggleCalls(
|
|||
{
|
||||
SendRequest(aRunnable, ToggleCallsRequest());
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::SendMetaData(const nsAString& aTitle,
|
||||
|
|
|
@ -149,6 +149,7 @@ public:
|
|||
virtual void
|
||||
IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
virtual void
|
||||
AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -157,6 +158,7 @@ public:
|
|||
|
||||
virtual void
|
||||
ToggleCalls(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
virtual void
|
||||
SendMetaData(const nsAString& aTitle,
|
||||
|
|
|
@ -2627,6 +2627,7 @@ BluetoothDBusService::IsConnected(const uint16_t aServiceUuid)
|
|||
return profile->IsConnected();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
BluetoothDBusService::AnswerWaitingCall(BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
|
@ -2659,6 +2660,7 @@ BluetoothDBusService::ToggleCalls(BluetoothReplyRunnable* aRunnable)
|
|||
|
||||
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
class OnUpdateSdpRecordsRunnable : public nsRunnable
|
||||
{
|
||||
|
|
|
@ -135,6 +135,7 @@ public:
|
|||
virtual void
|
||||
IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
virtual void
|
||||
AnswerWaitingCall(BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
|
@ -143,6 +144,7 @@ public:
|
|||
|
||||
virtual void
|
||||
ToggleCalls(BluetoothReplyRunnable* aRunnable);
|
||||
#endif
|
||||
|
||||
virtual void
|
||||
SendMetaData(const nsAString& aTitle,
|
||||
|
|
|
@ -48,7 +48,7 @@ const ContentPanning = {
|
|||
// If we are using an AsyncPanZoomController for the parent frame,
|
||||
// it will handle subframe scrolling too. We don't need to listen for
|
||||
// these events.
|
||||
if (!this._asyncPanZoomForViewportFrame) {
|
||||
if (!docShell.asyncPanZoomEnabled) {
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
|
@ -155,23 +155,11 @@ const ContentPanning = {
|
|||
let oldTarget = this.target;
|
||||
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
||||
|
||||
// If we found a target, that means we have found a scrollable subframe. In
|
||||
// this case, and if we are using async panning and zooming on the parent
|
||||
// frame, inform the pan/zoom controller that it should not attempt to
|
||||
// handle any touch events it gets until the next batch (meaning the next
|
||||
// time we get a touch end).
|
||||
if (this.target != null && this._asyncPanZoomForViewportFrame) {
|
||||
this.detectingScrolling = true;
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'detect-scrollable-subframe', null);
|
||||
}
|
||||
|
||||
// If we have a pointer down target and we're not async
|
||||
// pan/zooming, we may need to fill in for EventStateManager in
|
||||
// setting the active state on the target element. Set a timer to
|
||||
// If we have a pointer down target, we may need to fill in for EventStateManager
|
||||
// in setting the active state on the target element. Set a timer to
|
||||
// ensure the pointer-down target is active. (If it's already
|
||||
// active, the timer is a no-op.)
|
||||
if (this.pointerDownTarget !== null && !this.detectingScrolling) {
|
||||
if (this.pointerDownTarget !== null) {
|
||||
// If there's no possibility this is a drag/pan, activate now.
|
||||
// Otherwise wait a little bit to see if the gesture isn't a
|
||||
// tap.
|
||||
|
@ -262,12 +250,6 @@ const ContentPanning = {
|
|||
this.pointerDownTarget = null;
|
||||
},
|
||||
|
||||
// True when there's an async pan-zoom controll watching the
|
||||
// outermost scrollable frame, and we're waiting to see whether
|
||||
// we're going to take over from it and synchronously scroll an
|
||||
// inner scrollable frame.
|
||||
detectingScrolling: false,
|
||||
|
||||
onTouchMove: function cp_onTouchMove(evt) {
|
||||
if (!this.dragging)
|
||||
return;
|
||||
|
@ -296,27 +278,7 @@ const ContentPanning = {
|
|||
}
|
||||
|
||||
let isPan = KineticPanning.isPan();
|
||||
if (!isPan && this.detectingScrolling) {
|
||||
// If panning distance is not large enough and we're waiting to
|
||||
// see whether we should use the sync scroll fallback or not,
|
||||
// don't attempt scrolling.
|
||||
return;
|
||||
}
|
||||
|
||||
let isScroll = this.scrollCallback(delta.scale(-1));
|
||||
|
||||
if (this.detectingScrolling) {
|
||||
this.detectingScrolling = false;
|
||||
// Stop async-pan-zooming if the user is panning the subframe.
|
||||
if (isScroll) {
|
||||
// We're going to drive synchronously scrolling an inner frame.
|
||||
Services.obs.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
|
||||
} else {
|
||||
// Let AsyncPanZoomController handle the scrolling gesture.
|
||||
this.scrollCallback = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.scrollCallback(delta.scale(-1));
|
||||
|
||||
// If we've detected a pan gesture, cancel the active state of the
|
||||
// current target.
|
||||
|
@ -392,13 +354,6 @@ const ContentPanning = {
|
|||
node = node.parentNode;
|
||||
}
|
||||
|
||||
if (ContentPanning._asyncPanZoomForViewportFrame &&
|
||||
nodeContent === content) {
|
||||
// The parent context is asynchronously panning and zooming our
|
||||
// root scrollable frame, so don't use our synchronous fallback.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
|
||||
return nodeContent;
|
||||
}
|
||||
|
@ -515,10 +470,6 @@ const ContentPanning = {
|
|||
this._domUtils.setContentState(elt, kStateActive);
|
||||
},
|
||||
|
||||
get _asyncPanZoomForViewportFrame() {
|
||||
return docShell.asyncPanZoomEnabled;
|
||||
},
|
||||
|
||||
_recvViewportChange: function(data) {
|
||||
let metrics = data.json;
|
||||
this._viewport = new Rect(metrics.x, metrics.y,
|
||||
|
@ -637,7 +588,6 @@ const ContentPanning = {
|
|||
_finishPanning: function() {
|
||||
this._resetActive();
|
||||
this.dragging = false;
|
||||
this.detectingScrolling = false;
|
||||
delete this.primaryPointerId;
|
||||
this._activationTimer.cancel();
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ enum {
|
|||
CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
|
||||
CAMERA_PARAM_FOCUSDISTANCEFAR,
|
||||
CAMERA_PARAM_EXPOSURECOMPENSATION,
|
||||
CAMERA_PARAM_THUMBNAILWIDTH,
|
||||
CAMERA_PARAM_THUMBNAILHEIGHT,
|
||||
CAMERA_PARAM_PICTURESIZE,
|
||||
CAMERA_PARAM_THUMBNAILSIZE,
|
||||
CAMERA_PARAM_THUMBNAILQUALITY,
|
||||
|
||||
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
|
||||
|
|
|
@ -254,6 +254,20 @@ CameraControlImpl::Get(nsICameraPreviewStateChange** aOnPreviewStateChange)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Set(uint32_t aKey, const idl::CameraSize& aSize)
|
||||
{
|
||||
SetParameter(aKey, aSize);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Get(uint32_t aKey, idl::CameraSize& aSize)
|
||||
{
|
||||
GetParameter(aKey, aSize);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<RecorderProfileManager>
|
||||
CameraControlImpl::GetRecorderProfileManager()
|
||||
{
|
||||
|
@ -407,7 +421,7 @@ CameraControlImpl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErr
|
|||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
CameraControlImpl::TakePicture(const CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
bool cancel = false;
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
nsresult StartPreview(DOMCameraPreview* aDOMPreview);
|
||||
void StopPreview();
|
||||
nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult TakePicture(idl::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult TakePicture(const idl::CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StopRecording();
|
||||
nsresult GetPreviewStreamVideoMode(idl::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
|
@ -73,6 +73,8 @@ public:
|
|||
nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange);
|
||||
nsresult Set(nsICameraPreviewStateChange* aOnPreviewStateChange);
|
||||
nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange);
|
||||
nsresult Set(uint32_t aKey, const idl::CameraSize& aSize);
|
||||
nsresult Get(uint32_t aKey, idl::CameraSize& aSize);
|
||||
|
||||
nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
|
||||
{
|
||||
|
@ -91,10 +93,12 @@ public:
|
|||
virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
|
||||
virtual double GetParameterDouble(uint32_t aKey) = 0;
|
||||
virtual void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions) = 0;
|
||||
virtual void GetParameter(uint32_t aKey, idl::CameraSize& aSize) = 0;
|
||||
virtual void SetParameter(const char* aKey, const char* aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, double aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const idl::CameraSize& aSize) = 0;
|
||||
virtual nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes) = 0;
|
||||
virtual nsresult PushParameters() = 0;
|
||||
virtual void Shutdown();
|
||||
|
@ -372,7 +376,7 @@ protected:
|
|||
class TakePictureTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
TakePictureTask(CameraControlImpl* aCameraControl, bool aCancel, idl::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
TakePictureTask(CameraControlImpl* aCameraControl, bool aCancel, const idl::CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mCancel(aCancel)
|
||||
, mSize(aSize)
|
||||
|
|
|
@ -199,6 +199,13 @@ DOMCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
|
|||
return DimensionListToNewObject(cx, aPictureSizes, CAMERA_PARAM_SUPPORTED_PICTURESIZES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval thumbnailSizes; */
|
||||
NS_IMETHODIMP
|
||||
DOMCameraCapabilities::GetThumbnailSizes(JSContext* cx, JS::Value* aThumbnailSizes)
|
||||
{
|
||||
return DimensionListToNewObject(cx, aThumbnailSizes, CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval fileFormats; */
|
||||
NS_IMETHODIMP
|
||||
DOMCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::idl;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(nsDOMCameraControl, mDOMCapabilities, mWindow)
|
||||
|
||||
|
@ -155,6 +156,83 @@ nsDOMCameraControl::SetFocusAreas(JSContext* cx, JS::Handle<JS::Value> aFocusAre
|
|||
aRv = mCameraControl->SetFocusAreas(cx, aFocusAreas);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetSize(JSContext* aCx, JS::Value* aValue, const CameraSize& aSize)
|
||||
{
|
||||
JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
|
||||
if (!o) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> v(aCx);
|
||||
|
||||
v = INT_TO_JSVAL(aSize.width);
|
||||
if (!JS_SetProperty(aCx, o, "width", v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
v = INT_TO_JSVAL(aSize.height);
|
||||
if (!JS_SetProperty(aCx, o, "height", v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aValue = JS::ObjectValue(*o);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute any pictureSize */
|
||||
JS::Value
|
||||
nsDOMCameraControl::GetPictureSize(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
|
||||
CameraSize size;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_PICTURESIZE, size);
|
||||
if (aRv.Failed()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
aRv = GetSize(cx, value.address(), size);
|
||||
return value;
|
||||
}
|
||||
void
|
||||
nsDOMCameraControl::SetPictureSize(JSContext* cx, JS::Handle<JS::Value> aSize, ErrorResult& aRv)
|
||||
{
|
||||
CameraSize size;
|
||||
aRv = size.Init(cx, aSize.address());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_PICTURESIZE, size);
|
||||
}
|
||||
|
||||
/* attribute any thumbnailSize */
|
||||
JS::Value
|
||||
nsDOMCameraControl::GetThumbnailSize(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
|
||||
CameraSize size;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_THUMBNAILSIZE, size);
|
||||
if (aRv.Failed()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
aRv = GetSize(cx, value.address(), size);
|
||||
return value;
|
||||
}
|
||||
void
|
||||
nsDOMCameraControl::SetThumbnailSize(JSContext* cx, JS::Handle<JS::Value> aSize, ErrorResult& aRv)
|
||||
{
|
||||
CameraSize size;
|
||||
aRv = size.Init(cx, aSize.address());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_THUMBNAILSIZE, size);
|
||||
}
|
||||
|
||||
double
|
||||
nsDOMCameraControl::GetFocalLength(ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,10 @@ public:
|
|||
void SetMeteringAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
|
||||
JS::Value GetFocusAreas(JSContext* aCx, ErrorResult& aRv);
|
||||
void SetFocusAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
|
||||
JS::Value GetPictureSize(JSContext* aCx, ErrorResult& aRv);
|
||||
void SetPictureSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv);
|
||||
JS::Value GetThumbnailSize(JSContext* aCx, ErrorResult& aRv);
|
||||
void SetThumbnailSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv);
|
||||
double GetFocalLength(ErrorResult& aRv);
|
||||
double GetFocusDistanceNear(ErrorResult& aRv);
|
||||
double GetFocusDistanceOptimum(ErrorResult& aRv);
|
||||
|
|
|
@ -25,10 +25,12 @@ public:
|
|||
const char* GetParameterConstChar(uint32_t aKey);
|
||||
double GetParameterDouble(uint32_t aKey);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
|
||||
void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
|
||||
void SetParameter(const char* aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, double aValue);
|
||||
void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions);
|
||||
void SetParameter(uint32_t aKey, const idl::CameraSize& aSize);
|
||||
nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes);
|
||||
nsresult PushParameters();
|
||||
|
||||
|
@ -104,6 +106,11 @@ nsFallbackCameraControl::GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsFallbackCameraControl::GetParameter(uint32_t aKey, idl::CameraSize& aSize)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsFallbackCameraControl::SetParameter(const char* aKey, const char* aValue)
|
||||
{
|
||||
|
@ -124,6 +131,11 @@ nsFallbackCameraControl::SetParameter(uint32_t aKey, const nsTArray<idl::CameraR
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsFallbackCameraControl::SetParameter(uint32_t aKey, const idl::CameraSize& aSize)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::PushParameters()
|
||||
{
|
||||
|
|
|
@ -95,10 +95,8 @@ static const char* getKeyText(uint32_t aKey)
|
|||
return CameraParameters::KEY_FOCUS_DISTANCES;
|
||||
case CAMERA_PARAM_EXPOSURECOMPENSATION:
|
||||
return CameraParameters::KEY_EXPOSURE_COMPENSATION;
|
||||
case CAMERA_PARAM_THUMBNAILWIDTH:
|
||||
return CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH;
|
||||
case CAMERA_PARAM_THUMBNAILHEIGHT:
|
||||
return CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT;
|
||||
case CAMERA_PARAM_PICTURESIZE:
|
||||
return CameraParameters::KEY_PICTURE_SIZE;
|
||||
case CAMERA_PARAM_THUMBNAILQUALITY:
|
||||
return CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY;
|
||||
|
||||
|
@ -211,6 +209,8 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraT
|
|||
, mHeight(0)
|
||||
, mLastPictureWidth(0)
|
||||
, mLastPictureHeight(0)
|
||||
, mLastThumbnailWidth(0)
|
||||
, mLastThumbnailHeight(0)
|
||||
#if !FORCE_PREVIEW_FORMAT_YUV420SP
|
||||
, mFormat(PREVIEW_FORMAT_UNKNOWN)
|
||||
#else
|
||||
|
@ -290,11 +290,22 @@ nsGonkCameraControl::Init()
|
|||
mExposureCompensationStep = mParams.getFloat(mParams.KEY_EXPOSURE_COMPENSATION_STEP);
|
||||
mMaxMeteringAreas = mParams.getInt(mParams.KEY_MAX_NUM_METERING_AREAS);
|
||||
mMaxFocusAreas = mParams.getInt(mParams.KEY_MAX_NUM_FOCUS_AREAS);
|
||||
mLastThumbnailWidth = mParams.getInt(mParams.KEY_JPEG_THUMBNAIL_WIDTH);
|
||||
mLastThumbnailHeight = mParams.getInt(mParams.KEY_JPEG_THUMBNAIL_HEIGHT);
|
||||
|
||||
int w;
|
||||
int h;
|
||||
mParams.getPictureSize(&w, &h);
|
||||
MOZ_ASSERT(w > 0 && h > 0); // make sure the driver returns sane values
|
||||
mLastPictureWidth = static_cast<uint32_t>(w);
|
||||
mLastPictureHeight = static_cast<uint32_t>(h);
|
||||
|
||||
DOM_CAMERA_LOGI(" - minimum exposure compensation: %f\n", mExposureCompensationMin);
|
||||
DOM_CAMERA_LOGI(" - exposure compensation step: %f\n", mExposureCompensationStep);
|
||||
DOM_CAMERA_LOGI(" - maximum metering areas: %d\n", mMaxMeteringAreas);
|
||||
DOM_CAMERA_LOGI(" - maximum focus areas: %d\n", mMaxFocusAreas);
|
||||
DOM_CAMERA_LOGI(" - default picture size: %u x %u\n", mLastPictureWidth, mLastPictureHeight);
|
||||
DOM_CAMERA_LOGI(" - default thumbnail size: %u x %u\n", mLastThumbnailWidth, mLastThumbnailHeight);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -507,6 +518,40 @@ nsGonkCameraControl::GetParameter(uint32_t aKey,
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::GetParameter(uint32_t aKey, idl::CameraSize& aSize)
|
||||
{
|
||||
if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
|
||||
// This is a special case--for some reason the thumbnail size
|
||||
// is accessed as two separate values instead of a tuple.
|
||||
RwAutoLockRead lock(mRwLock);
|
||||
|
||||
aSize.width = mParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
|
||||
aSize.height = mParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
|
||||
DOM_CAMERA_LOGI("thumbnail size --> value='%ux%u'\n", aSize.width, aSize.height);
|
||||
return;
|
||||
}
|
||||
|
||||
const char* key = getKeyText(aKey);
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
RwAutoLockRead lock(mRwLock);
|
||||
|
||||
const char* value = mParams.get(key);
|
||||
DOM_CAMERA_LOGI("key='%s' --> value='%s'\n", key, value);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
|
||||
DOM_CAMERA_LOGE("%s:%d : size tuple has bad format: '%s'\n", __func__, __LINE__, value);
|
||||
aSize.width = 0;
|
||||
aSize.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::PushParameters()
|
||||
{
|
||||
|
@ -522,7 +567,7 @@ nsGonkCameraControl::PushParameters()
|
|||
* we can proceed.
|
||||
*/
|
||||
if (NS_IsMainThread()) {
|
||||
DOM_CAMERA_LOGT("%s:%d - dispatching to main thread\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d - dispatching to camera thread\n", __func__, __LINE__);
|
||||
nsCOMPtr<nsIRunnable> pushParametersTask = NS_NewRunnableMethod(this, &nsGonkCameraControl::PushParametersImpl);
|
||||
return mCameraThread->Dispatch(pushParametersTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
@ -634,6 +679,39 @@ nsGonkCameraControl::SetParameter(uint32_t aKey, int aValue)
|
|||
PushParameters();
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::SetParameter(uint32_t aKey, const idl::CameraSize& aSize)
|
||||
{
|
||||
switch (aKey) {
|
||||
case CAMERA_PARAM_PICTURESIZE:
|
||||
DOM_CAMERA_LOGI("setting picture size to %ux%u\n", aSize.width, aSize.height);
|
||||
SetPictureSize(aSize.width, aSize.height);
|
||||
break;
|
||||
|
||||
case CAMERA_PARAM_THUMBNAILSIZE:
|
||||
DOM_CAMERA_LOGI("setting thumbnail size to %ux%u\n", aSize.width, aSize.height);
|
||||
SetThumbnailSize(aSize.width, aSize.height);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
const char* key = getKeyText(aKey);
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString s;
|
||||
s.AppendPrintf("%ux%u", aSize.width, aSize.height);
|
||||
DOM_CAMERA_LOGI("setting '%s' to %s\n", key, s.get());
|
||||
|
||||
RwAutoLockWrite lock(mRwLock);
|
||||
mParams.set(key, s.get());
|
||||
}
|
||||
break;
|
||||
}
|
||||
PushParameters();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream)
|
||||
{
|
||||
|
@ -727,42 +805,143 @@ nsGonkCameraControl::AutoFocusImpl(AutoFocusTask* aAutoFocus)
|
|||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::SetupThumbnail(uint32_t aPictureWidth, uint32_t aPictureHeight, uint32_t aPercentQuality)
|
||||
nsGonkCameraControl::SetThumbnailSize(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
/**
|
||||
* Use the smallest non-0x0 thumbnail size that matches
|
||||
* the aspect ratio of our parameters...
|
||||
* We keep a copy of the specified size so that if the picture size
|
||||
* changes, we can choose a new thumbnail size close to what was asked for
|
||||
* last time.
|
||||
*/
|
||||
uint32_t smallestArea = UINT_MAX;
|
||||
uint32_t smallestIndex = UINT_MAX;
|
||||
nsAutoTArray<idl::CameraSize, 8> thumbnailSizes;
|
||||
GetParameter(CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES, thumbnailSizes);
|
||||
mLastThumbnailWidth = aWidth;
|
||||
mLastThumbnailHeight = aHeight;
|
||||
|
||||
/**
|
||||
* If either of width or height is zero, set the other to zero as well.
|
||||
* This should disable inclusion of a thumbnail in the final picture.
|
||||
*/
|
||||
if (!aWidth || !aHeight) {
|
||||
DOM_CAMERA_LOGW("Requested thumbnail size %ux%u, disabling thumbnail\n", aWidth, aHeight);
|
||||
RwAutoLockWrite write(mRwLock);
|
||||
mParams.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
|
||||
mParams.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the supported thumbnail size that is closest to the specified size.
|
||||
* Some drivers will fail to take a picture if the thumbnail does not have
|
||||
* the same aspect ratio as the set picture size, so we need to enforce that
|
||||
* too.
|
||||
*/
|
||||
int smallestDelta = INT_MAX;
|
||||
uint32_t smallestDeltaIndex = UINT32_MAX;
|
||||
int targetArea = aWidth * aHeight;
|
||||
|
||||
nsAutoTArray<idl::CameraSize, 8> supportedSizes;
|
||||
GetParameter(CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES, supportedSizes);
|
||||
|
||||
for (uint32_t i = 0; i < supportedSizes.Length(); ++i) {
|
||||
int area = supportedSizes[i].width * supportedSizes[i].height;
|
||||
int delta = abs(area - targetArea);
|
||||
|
||||
for (uint32_t i = 0; i < thumbnailSizes.Length(); ++i) {
|
||||
uint32_t area = thumbnailSizes[i].width * thumbnailSizes[i].height;
|
||||
if (area != 0
|
||||
&& area < smallestArea
|
||||
&& thumbnailSizes[i].width * aPictureHeight / thumbnailSizes[i].height == aPictureWidth
|
||||
&& delta < smallestDelta
|
||||
&& supportedSizes[i].width * mLastPictureHeight / supportedSizes[i].height == mLastPictureWidth
|
||||
) {
|
||||
smallestArea = area;
|
||||
smallestIndex = i;
|
||||
smallestDelta = delta;
|
||||
smallestDeltaIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
aPercentQuality = clamped<uint32_t>(aPercentQuality, 1, 100);
|
||||
SetParameter(CAMERA_PARAM_THUMBNAILQUALITY, static_cast<int>(aPercentQuality));
|
||||
|
||||
if (smallestIndex != UINT_MAX) {
|
||||
uint32_t w = thumbnailSizes[smallestIndex].width;
|
||||
uint32_t h = thumbnailSizes[smallestIndex].height;
|
||||
DOM_CAMERA_LOGI("Using thumbnail size: %ux%u, quality: %u %%\n", w, h, aPercentQuality);
|
||||
if (w > INT_MAX || h > INT_MAX) {
|
||||
DOM_CAMERA_LOGE("Thumbnail dimension is too big, will use defaults\n");
|
||||
return;
|
||||
}
|
||||
SetParameter(CAMERA_PARAM_THUMBNAILWIDTH, static_cast<int>(w));
|
||||
SetParameter(CAMERA_PARAM_THUMBNAILHEIGHT, static_cast<int>(h));
|
||||
if (smallestDeltaIndex == UINT32_MAX) {
|
||||
DOM_CAMERA_LOGW("Unable to find a thumbnail size close to %ux%u\n", aWidth, aHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t w = supportedSizes[smallestDeltaIndex].width;
|
||||
uint32_t h = supportedSizes[smallestDeltaIndex].height;
|
||||
DOM_CAMERA_LOGI("Requested thumbnail size %ux%u --> using supported size %ux%u\n", aWidth, aHeight, w, h);
|
||||
if (w > INT32_MAX || h > INT32_MAX) {
|
||||
DOM_CAMERA_LOGE("Supported thumbnail size is too big, no change\n");
|
||||
return;
|
||||
}
|
||||
|
||||
RwAutoLockWrite write(mRwLock);
|
||||
mParams.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(w));
|
||||
mParams.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(h));
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::UpdateThumbnailSize()
|
||||
{
|
||||
SetThumbnailSize(mLastThumbnailWidth, mLastThumbnailHeight);
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::SetPictureSize(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
/**
|
||||
* Some drivers are less friendly about getting one of these set to zero,
|
||||
* so if either is not specified, ignore both and go with current or
|
||||
* default settings.
|
||||
*/
|
||||
if (!aWidth || !aHeight) {
|
||||
DOM_CAMERA_LOGW("Ignoring requested picture size of %ux%u\n", aWidth, aHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aWidth == mLastPictureWidth && aHeight == mLastPictureHeight) {
|
||||
DOM_CAMERA_LOGI("Requested picture size %ux%u unchanged\n", aWidth, aHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the supported picture size that is closest in area to the
|
||||
* specified size. Some drivers will fail to take a picture if the
|
||||
* thumbnail size is not the same aspect ratio, so we update that
|
||||
* as well to a size closest to the last user-requested one.
|
||||
*/
|
||||
int smallestDelta = INT_MAX;
|
||||
uint32_t smallestDeltaIndex = UINT32_MAX;
|
||||
int targetArea = aWidth * aHeight;
|
||||
|
||||
nsAutoTArray<idl::CameraSize, 8> supportedSizes;
|
||||
GetParameter(CAMERA_PARAM_SUPPORTED_PICTURESIZES, supportedSizes);
|
||||
|
||||
for (uint32_t i = 0; i < supportedSizes.Length(); ++i) {
|
||||
int area = supportedSizes[i].width * supportedSizes[i].height;
|
||||
int delta = abs(area - targetArea);
|
||||
|
||||
if (area != 0 && delta < smallestDelta) {
|
||||
smallestDelta = delta;
|
||||
smallestDeltaIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (smallestDeltaIndex == UINT32_MAX) {
|
||||
DOM_CAMERA_LOGW("Unable to find a picture size close to %ux%u\n", aWidth, aHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t w = supportedSizes[smallestDeltaIndex].width;
|
||||
uint32_t h = supportedSizes[smallestDeltaIndex].height;
|
||||
DOM_CAMERA_LOGI("Requested picture size %ux%u --> using supported size %ux%u\n", aWidth, aHeight, w, h);
|
||||
if (w > INT32_MAX || h > INT32_MAX) {
|
||||
DOM_CAMERA_LOGE("Supported picture size is too big, no change\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mLastPictureWidth = w;
|
||||
mLastPictureHeight = h;
|
||||
|
||||
{
|
||||
// We must release the write-lock before updating the thumbnail size
|
||||
RwAutoLockWrite write(mRwLock);
|
||||
mParams.setPictureSize(static_cast<int>(w), static_cast<int>(h));
|
||||
}
|
||||
|
||||
// Finally, update the thumbnail size
|
||||
UpdateThumbnailSize();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -782,25 +961,7 @@ nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
|
|||
// batch-update camera configuration
|
||||
mDeferConfigUpdate = true;
|
||||
|
||||
if (aTakePicture->mSize.width != mLastPictureWidth || aTakePicture->mSize.height != mLastPictureHeight) {
|
||||
/**
|
||||
* height and width: some drivers are less friendly about getting one of
|
||||
* these set to zero, so if either is not specified, ignore both and go
|
||||
* with current or default settings.
|
||||
*/
|
||||
if (aTakePicture->mSize.width && aTakePicture->mSize.height) {
|
||||
nsCString s;
|
||||
s.AppendPrintf("%ux%u", aTakePicture->mSize.width, aTakePicture->mSize.height);
|
||||
DOM_CAMERA_LOGI("setting picture size to '%s'\n", s.get());
|
||||
SetParameter(CameraParameters::KEY_PICTURE_SIZE, s.get());
|
||||
|
||||
// Choose an appropriate thumbnail size and quality (from 1..100)
|
||||
SetupThumbnail(aTakePicture->mSize.width, aTakePicture->mSize.height, 60);
|
||||
}
|
||||
|
||||
mLastPictureWidth = aTakePicture->mSize.width;
|
||||
mLastPictureHeight = aTakePicture->mSize.height;
|
||||
}
|
||||
SetPictureSize(aTakePicture->mSize.width, aTakePicture->mSize.height);
|
||||
|
||||
// Picture format -- need to keep it for the callback.
|
||||
mFileFormat = aTakePicture->mFileFormat;
|
||||
|
|
|
@ -55,11 +55,13 @@ public:
|
|||
double GetParameterDouble(uint32_t aKey);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraSize>& aSizes);
|
||||
void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
|
||||
void SetParameter(const char* aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, double aValue);
|
||||
void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions);
|
||||
void SetParameter(uint32_t aKey, int aValue);
|
||||
void SetParameter(uint32_t aKey, const idl::CameraSize& aSize);
|
||||
nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes);
|
||||
nsresult PushParameters();
|
||||
|
||||
|
@ -89,7 +91,9 @@ protected:
|
|||
nsresult SetupRecording(int aFd, int aRotation, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs);
|
||||
nsresult SetupVideoMode(const nsAString& aProfile);
|
||||
void SetPreviewSize(uint32_t aWidth, uint32_t aHeight);
|
||||
void SetupThumbnail(uint32_t aPictureWidth, uint32_t aPictureHeight, uint32_t aPercentQuality);
|
||||
void SetThumbnailSize(uint32_t aWidth, uint32_t aHeight);
|
||||
void UpdateThumbnailSize();
|
||||
void SetPictureSize(uint32_t aWidth, uint32_t aHeight);
|
||||
|
||||
android::sp<android::GonkCameraHardware> mCameraHw;
|
||||
double mExposureCompensationMin;
|
||||
|
@ -101,6 +105,8 @@ protected:
|
|||
uint32_t mHeight;
|
||||
uint32_t mLastPictureWidth;
|
||||
uint32_t mLastPictureHeight;
|
||||
uint32_t mLastThumbnailWidth;
|
||||
uint32_t mLastThumbnailHeight;
|
||||
|
||||
enum {
|
||||
PREVIEW_FORMAT_UNKNOWN,
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
|
||||
class DOMCameraPreview;
|
||||
class RecorderProfileManager;
|
||||
|
||||
|
@ -25,7 +24,7 @@ public:
|
|||
virtual nsresult StartPreview(DOMCameraPreview* aDOMPreview) = 0;
|
||||
virtual void StopPreview() = 0;
|
||||
virtual nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult TakePicture(idl::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult TakePicture(const idl::CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StopRecording() = 0;
|
||||
virtual nsresult GetPreviewStreamVideoMode(idl::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
|
@ -45,6 +44,8 @@ public:
|
|||
virtual nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange) = 0;
|
||||
virtual nsresult Set(nsICameraPreviewStateChange* aOnPreviewStateChange) = 0;
|
||||
virtual nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange) = 0;
|
||||
virtual nsresult Set(uint32_t aKey, const idl::CameraSize& aSize) = 0;
|
||||
virtual nsresult Get(uint32_t aKey, idl::CameraSize& aSize) = 0;
|
||||
virtual nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
virtual nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
virtual nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes) = 0;
|
||||
|
|
|
@ -36,7 +36,7 @@ dictionary CameraPosition {
|
|||
double timestamp;
|
||||
};
|
||||
|
||||
[scriptable, uuid(177472c9-f83d-48b5-8782-03b43b27f25d)]
|
||||
[scriptable, uuid(0711a4af-73c2-481d-85bc-0ba3ec36c004)]
|
||||
interface nsICameraCapabilities : nsISupports
|
||||
{
|
||||
/* an array of objects with 'height' and 'width' properties
|
||||
|
@ -49,6 +49,11 @@ interface nsICameraCapabilities : nsISupports
|
|||
[implicit_jscontext]
|
||||
readonly attribute jsval pictureSizes;
|
||||
|
||||
/* an array of objects with 'height' and 'width' properties
|
||||
supported for thumbnail sizes in taken pictures */
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval thumbnailSizes;
|
||||
|
||||
/* an array of strings, e.g. [ "jpeg", "rgb565" ] */
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval fileFormats;
|
||||
|
|
|
@ -176,18 +176,18 @@ function validateArrayField(data, createCb) {
|
|||
}
|
||||
};
|
||||
|
||||
if (data) {
|
||||
data = Array.isArray(data) ? data : [data];
|
||||
let filtered = [];
|
||||
for (let i = 0, n = data.length; i < n; ++i) {
|
||||
if (data === null || data === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
data = Array.isArray(data) ? data : [data];
|
||||
let filtered = [];
|
||||
for (let i = 0, n = data.length; i < n; ++i) {
|
||||
if (data[i]) {
|
||||
filtered.push(createCb(data[i]));
|
||||
}
|
||||
if (filtered.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return new Proxy(filtered, ArrayPropertyHandler);
|
||||
}
|
||||
return undefined;
|
||||
return new Proxy(filtered, ArrayPropertyHandler);
|
||||
}
|
||||
|
||||
// We need this to create a copy of the mozContact object in ContactManager.save
|
||||
|
|
|
@ -264,7 +264,7 @@ function removeAndroidDefaultCategory(category) {
|
|||
|
||||
function checkArrayField(array1, array2, func, msg) {
|
||||
if (!!array1 ^ !!array2) {
|
||||
ok(false, "Expected both arrays to be either present or absent");
|
||||
ok(false, "Expected both arrays to be either present or absent: " + JSON.stringify(array1) + " vs. " + JSON.stringify(array2) + ". (" + msg + ")");
|
||||
return;
|
||||
}
|
||||
if (!array1 && !array2) {
|
||||
|
@ -1523,17 +1523,11 @@ var steps = [
|
|||
},
|
||||
function () {
|
||||
ok(true, "Adding contact with invalid data");
|
||||
var input = document.createElement("input");
|
||||
var obj = {
|
||||
honorificPrefix: [],
|
||||
honorificSuffix: [{foo: "bar"}],
|
||||
sex: 17,
|
||||
genderIdentity: 18,
|
||||
email: input,
|
||||
adr: input,
|
||||
tel: input,
|
||||
impp: input,
|
||||
url: input
|
||||
genderIdentity: 18
|
||||
};
|
||||
obj.honorificPrefix.__defineGetter__('0',(function() {
|
||||
var c = 0;
|
||||
|
@ -1668,6 +1662,38 @@ var steps = [
|
|||
}
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
ok(true, "Undefined strings should be treated as null");
|
||||
var c = new mozContact({
|
||||
adr: [{value: undefined}],
|
||||
email: [{value: undefined}],
|
||||
url: [{value: undefined}],
|
||||
impp: [{value: undefined}],
|
||||
tel: [{value: undefined}],
|
||||
});
|
||||
is(c.adr[0].type, null, "adr is null");
|
||||
is(c.email[0].type, null, "email is null");
|
||||
is(c.url[0].type, null, "url is null");
|
||||
is(c.impp[0].type, null, "impp is null");
|
||||
is(c.tel[0].type, null, "tel is null");
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
ok(true, "Setting array properties to an empty array should work");
|
||||
var c = new mozContact();
|
||||
function testArrayProp(prop) {
|
||||
is(c[prop], null, "property is initially null");
|
||||
c[prop] = [];
|
||||
ok(Array.isArray(c[prop]), "property is an array after setting");
|
||||
is(c[prop].length, 0, "property has length 0 after setting");
|
||||
}
|
||||
testArrayProp("email");
|
||||
testArrayProp("adr");
|
||||
testArrayProp("tel");
|
||||
testArrayProp("impp");
|
||||
testArrayProp("url");
|
||||
next();
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
clearTemps();
|
||||
|
|
|
@ -1233,7 +1233,6 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(const nsString& aName,
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBlob);
|
||||
MOZ_ASSERT(mRemoteBlob);
|
||||
MOZ_ASSERT(aLength);
|
||||
MOZ_ASSERT(aLastModifiedDate != UINT64_MAX);
|
||||
|
||||
ToConcreteBlob(mBlob)->SetLazyData(aName, aContentType,
|
||||
|
@ -1252,7 +1251,6 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(const nsString& aContentType,
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBlob);
|
||||
MOZ_ASSERT(mRemoteBlob);
|
||||
MOZ_ASSERT(aLength);
|
||||
|
||||
nsString voidString;
|
||||
voidString.SetIsVoid(true);
|
||||
|
|
|
@ -88,10 +88,8 @@ NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
|
|||
|
||||
static const CSSSize kDefaultViewportSize(980, 480);
|
||||
|
||||
static const char CANCEL_DEFAULT_PAN_ZOOM[] = "cancel-default-pan-zoom";
|
||||
static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
|
||||
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
|
||||
static const char DETECT_SCROLLABLE_SUBFRAME[] = "detect-scrollable-subframe";
|
||||
|
||||
static bool sCpowsEnabled = false;
|
||||
|
||||
|
@ -354,13 +352,7 @@ TabChild::Observe(nsISupports *aSubject,
|
|||
const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
if (!strcmp(aTopic, CANCEL_DEFAULT_PAN_ZOOM)) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
mRemoteFrame->CancelDefaultPanZoom();
|
||||
}
|
||||
} else if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
|
||||
if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
|
@ -409,12 +401,6 @@ TabChild::Observe(nsISupports *aSubject,
|
|||
HandlePossibleViewportChange();
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(aTopic, DETECT_SCROLLABLE_SUBFRAME)) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
mRemoteFrame->DetectScrollableSubframe();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2120,10 +2106,8 @@ TabChild::RecvDestroy()
|
|||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
|
||||
observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM);
|
||||
observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
|
||||
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
|
||||
observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME);
|
||||
|
||||
const InfallibleTArray<PIndexedDBChild*>& idbActors =
|
||||
ManagedPIndexedDBChild();
|
||||
|
@ -2258,18 +2242,12 @@ TabChild::InitRenderingState()
|
|||
mozilla::services::GetObserverService();
|
||||
|
||||
if (observerService) {
|
||||
observerService->AddObserver(this,
|
||||
CANCEL_DEFAULT_PAN_ZOOM,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
BROWSER_ZOOM_TO_RECT,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
BEFORE_FIRST_PAINT,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
DETECT_SCROLLABLE_SUBFRAME,
|
||||
false);
|
||||
}
|
||||
|
||||
// This state can't really change during the lifetime of the child.
|
||||
|
|
|
@ -22,7 +22,7 @@ XPIDL_SOURCES += [
|
|||
'nsIWapPushApplication.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIRilMobileMessageDatabaseService.idl',
|
||||
]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "android/MobileMessageDatabaseService.h"
|
||||
#include "android/SmsService.h"
|
||||
#include "android/MmsService.h"
|
||||
#elif defined(MOZ_B2G_RIL)
|
||||
#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
#include "gonk/SmsService.h"
|
||||
#else
|
||||
#include "fallback/MmsService.h"
|
||||
|
@ -47,7 +47,7 @@ SmsServicesFactory::CreateMobileMessageDatabaseService()
|
|||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
mobileMessageDBService = new SmsIPCService();
|
||||
} else {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
mobileMessageDBService = do_GetService(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
||||
#else
|
||||
mobileMessageDBService = new MobileMessageDatabaseService();
|
||||
|
@ -65,7 +65,7 @@ SmsServicesFactory::CreateMmsService()
|
|||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
mmsService = new SmsIPCService();
|
||||
} else {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
mmsService = do_CreateInstance(RIL_MMSSERVICE_CONTRACTID);
|
||||
#else
|
||||
mmsService = new MmsService();
|
||||
|
|
|
@ -37,21 +37,28 @@ const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
|||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||
const kMobileMessageDeletedObserverTopic = "mobile-message-deleted";
|
||||
|
||||
const kPrefRilMmsc = "ril.mms.mmsc";
|
||||
const kPrefRilMmsProxy = "ril.mms.mmsproxy";
|
||||
const kPrefRilMmsPort = "ril.mms.mmsport";
|
||||
const kPrefRilRadioDisabled = "ril.radio.disabled";
|
||||
|
||||
// HTTP status codes:
|
||||
// @see http://tools.ietf.org/html/rfc2616#page-39
|
||||
const HTTP_STATUS_OK = 200;
|
||||
|
||||
// Non-standard HTTP status for internal use.
|
||||
const _HTTP_STATUS_ACQUIRE_CONNECTION_SUCCESS = 0;
|
||||
const _HTTP_STATUS_USER_CANCELLED = -1;
|
||||
const _HTTP_STATUS_RADIO_DISABLED = -2;
|
||||
const _HTTP_STATUS_NO_SIM_CARD = -3;
|
||||
const _HTTP_STATUS_ACQUIRE_TIMEOUT = 4;
|
||||
const _HTTP_STATUS_ACQUIRE_CONNECTION_SUCCESS = 0;
|
||||
const _HTTP_STATUS_USER_CANCELLED = -1;
|
||||
const _HTTP_STATUS_RADIO_DISABLED = -2;
|
||||
const _HTTP_STATUS_NO_SIM_CARD = -3;
|
||||
const _HTTP_STATUS_ACQUIRE_TIMEOUT = -4;
|
||||
|
||||
// Non-standard MMS status for internal use.
|
||||
const _MMS_ERROR_MESSAGE_DELETED = -1;
|
||||
const _MMS_ERROR_RADIO_DISABLED = -2;
|
||||
const _MMS_ERROR_NO_SIM_CARD = -3;
|
||||
const _MMS_ERROR_MESSAGE_DELETED = -1;
|
||||
const _MMS_ERROR_RADIO_DISABLED = -2;
|
||||
const _MMS_ERROR_NO_SIM_CARD = -3;
|
||||
const _MMS_ERROR_SHUTDOWN = -4;
|
||||
const _MMS_ERROR_USER_CANCELLED_NO_REASON = -5;
|
||||
|
||||
const CONFIG_SEND_REPORT_NEVER = 0;
|
||||
const CONFIG_SEND_REPORT_DEFAULT_NO = 1;
|
||||
|
@ -156,10 +163,10 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
radioDisabled: false,
|
||||
|
||||
proxyInfo: null,
|
||||
settings: ["ril.mms.mmsc",
|
||||
"ril.mms.mmsproxy",
|
||||
"ril.mms.mmsport",
|
||||
"ril.radio.disabled"],
|
||||
settings: [kPrefRilMmsc,
|
||||
kPrefRilMmsProxy,
|
||||
kPrefRilMmsPort,
|
||||
kPrefRilRadioDisabled],
|
||||
connected: false,
|
||||
|
||||
//A queue to buffer the MMS HTTP requests when the MMS network
|
||||
|
@ -206,9 +213,9 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
}, this);
|
||||
|
||||
try {
|
||||
this.mmsc = Services.prefs.getCharPref("ril.mms.mmsc");
|
||||
this.proxy = Services.prefs.getCharPref("ril.mms.mmsproxy");
|
||||
this.port = Services.prefs.getIntPref("ril.mms.mmsport");
|
||||
this.mmsc = Services.prefs.getCharPref(kPrefRilMmsc);
|
||||
this.proxy = Services.prefs.getCharPref(kPrefRilMmsProxy);
|
||||
this.port = Services.prefs.getIntPref(kPrefRilMmsPort);
|
||||
this.updateProxyInfo();
|
||||
} catch (e) {
|
||||
if (DEBUG) debug("Unable to initialize the MMS proxy settings from " +
|
||||
|
@ -218,7 +225,7 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
}
|
||||
|
||||
try {
|
||||
this.radioDisabled = Services.prefs.getBoolPref("ril.radio.disabled");
|
||||
this.radioDisabled = Services.prefs.getBoolPref(kPrefRilRadioDisabled);
|
||||
} catch (e) {
|
||||
if (DEBUG) debug("Getting preference 'ril.radio.disabled' fails.");
|
||||
this.radioDisabled = false;
|
||||
|
@ -373,9 +380,9 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
break;
|
||||
}
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: {
|
||||
if (data == "ril.radio.disabled") {
|
||||
if (data == kPrefRilRadioDisabled) {
|
||||
try {
|
||||
this.radioDisabled = Services.prefs.getBoolPref("ril.radio.disabled");
|
||||
this.radioDisabled = Services.prefs.getBoolPref(kPrefRilRadioDisabled);
|
||||
} catch (e) {
|
||||
if (DEBUG) debug("Updating preference 'ril.radio.disabled' fails.");
|
||||
this.radioDisabled = false;
|
||||
|
@ -385,15 +392,15 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
|
||||
try {
|
||||
switch (data) {
|
||||
case "ril.mms.mmsc":
|
||||
this.mmsc = Services.prefs.getCharPref("ril.mms.mmsc");
|
||||
case kPrefRilMmsc:
|
||||
this.mmsc = Services.prefs.getCharPref(kPrefRilMmsc);
|
||||
break;
|
||||
case "ril.mms.mmsproxy":
|
||||
this.proxy = Services.prefs.getCharPref("ril.mms.mmsproxy");
|
||||
case kPrefRilMmsProxy:
|
||||
this.proxy = Services.prefs.getCharPref(kPrefRilMmsProxy);
|
||||
this.updateProxyInfo();
|
||||
break;
|
||||
case "ril.mms.mmsport":
|
||||
this.port = Services.prefs.getIntPref("ril.mms.mmsport");
|
||||
case kPrefRilMmsPort:
|
||||
this.port = Services.prefs.getIntPref(kPrefRilMmsPort);
|
||||
this.updateProxyInfo();
|
||||
break;
|
||||
default:
|
||||
|
@ -671,10 +678,12 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
|||
return true;
|
||||
},
|
||||
|
||||
translateHttpStatusToMmsStatus: function translateHttpStatusToMmsStatus(httpStatus, defaultStatus) {
|
||||
translateHttpStatusToMmsStatus: function translateHttpStatusToMmsStatus(httpStatus,
|
||||
cancelledReason,
|
||||
defaultStatus) {
|
||||
switch(httpStatus) {
|
||||
case _HTTP_STATUS_USER_CANCELLED:
|
||||
return _MMS_ERROR_MESSAGE_DELETED;
|
||||
return cancelledReason;
|
||||
case _HTTP_STATUS_RADIO_DISABLED:
|
||||
return _MMS_ERROR_RADIO_DISABLED;
|
||||
case _HTTP_STATUS_NO_SIM_CARD:
|
||||
|
@ -756,10 +765,13 @@ CancellableTransaction.prototype = {
|
|||
|
||||
isObserversAdded: false,
|
||||
|
||||
cancelledReason: _MMS_ERROR_USER_CANCELLED_NO_REASON,
|
||||
|
||||
registerRunCallback: function registerRunCallback(callback) {
|
||||
if (!this.isObserversAdded) {
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
Services.obs.addObserver(this, kMobileMessageDeletedObserverTopic, false);
|
||||
Services.prefs.addObserver(kPrefRilRadioDisabled, this, false);
|
||||
this.isObserversAdded = true;
|
||||
}
|
||||
|
||||
|
@ -771,6 +783,7 @@ CancellableTransaction.prototype = {
|
|||
if (this.isObserversAdded) {
|
||||
Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
Services.obs.removeObserver(this, kMobileMessageDeletedObserverTopic);
|
||||
Services.prefs.removeObserver(kPrefRilRadioDisabled, this);
|
||||
this.isObserversAdded = false;
|
||||
}
|
||||
},
|
||||
|
@ -788,15 +801,16 @@ CancellableTransaction.prototype = {
|
|||
// |gMmsTransactionHelper.sendRequest(...)|.
|
||||
cancellable: null,
|
||||
|
||||
cancelRunning: function cancelRunning() {
|
||||
cancelRunning: function cancelRunning(reason) {
|
||||
this.isCancelled = true;
|
||||
this.cancelledReason = reason;
|
||||
|
||||
if (this.timer) {
|
||||
// The sending or retrieving process is waiting for the next retry.
|
||||
// What we only need to do is to cancel the timer.
|
||||
this.timer.cancel();
|
||||
this.timer = null;
|
||||
this.runCallbackIfValid(_MMS_ERROR_MESSAGE_DELETED, null);
|
||||
this.runCallbackIfValid(reason, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -813,7 +827,7 @@ CancellableTransaction.prototype = {
|
|||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case NS_XPCOM_SHUTDOWN_OBSERVER_ID: {
|
||||
this.cancelRunning();
|
||||
this.cancelRunning(_MMS_ERROR_SHUTDOWN);
|
||||
break;
|
||||
}
|
||||
case kMobileMessageDeletedObserverTopic: {
|
||||
|
@ -822,7 +836,20 @@ CancellableTransaction.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this.cancelRunning();
|
||||
this.cancelRunning(_MMS_ERROR_MESSAGE_DELETED);
|
||||
break;
|
||||
}
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: {
|
||||
if (data == kPrefRilRadioDisabled) {
|
||||
try {
|
||||
let radioDisabled = Services.prefs.getBoolPref(kPrefRilRadioDisabled);
|
||||
if (radioDisabled) {
|
||||
this.cancelRunning(_MMS_ERROR_RADIO_DISABLED);
|
||||
}
|
||||
} catch (e) {
|
||||
if (DEBUG) debug("Failed to get preference of 'ril.radio.disabled'.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -891,6 +918,7 @@ RetrieveTransaction.prototype = Object.create(CancellableTransaction.prototype,
|
|||
(function (httpStatus, data) {
|
||||
let mmsStatus = gMmsTransactionHelper
|
||||
.translateHttpStatusToMmsStatus(httpStatus,
|
||||
this.cancelledReason,
|
||||
MMS.MMS_PDU_STATUS_DEFERRED);
|
||||
if (mmsStatus != MMS.MMS_PDU_ERROR_OK) {
|
||||
callback(mmsStatus, null);
|
||||
|
@ -952,7 +980,12 @@ function SendTransaction(cancellableId, msg, requestDeliveryReport) {
|
|||
msg.headers["x-mms-message-class"] = "personal";
|
||||
msg.headers["x-mms-expiry"] = 7 * 24 * 60 * 60;
|
||||
msg.headers["x-mms-priority"] = 129;
|
||||
msg.headers["x-mms-read-report"] = true;
|
||||
try {
|
||||
msg.headers["x-mms-read-report"] =
|
||||
Services.prefs.getBoolPref("dom.mms.requestReadReport");
|
||||
} catch (e) {
|
||||
msg.headers["x-mms-read-report"] = true;
|
||||
}
|
||||
msg.headers["x-mms-delivery-report"] = requestDeliveryReport;
|
||||
|
||||
if (!gMmsTransactionHelper.checkMaxValuesParameters(msg)) {
|
||||
|
@ -1120,9 +1153,10 @@ SendTransaction.prototype = Object.create(CancellableTransaction.prototype, {
|
|||
this.cancellable =
|
||||
gMmsTransactionHelper.sendRequest("POST", gMmsConnection.mmsc,
|
||||
this.istream,
|
||||
function (httpStatus, data) {
|
||||
(function (httpStatus, data) {
|
||||
let mmsStatus = gMmsTransactionHelper.
|
||||
translateHttpStatusToMmsStatus(httpStatus,
|
||||
this.cancelledReason,
|
||||
MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE);
|
||||
if (httpStatus != HTTP_STATUS_OK) {
|
||||
callback(mmsStatus, null);
|
||||
|
@ -1142,7 +1176,7 @@ SendTransaction.prototype = Object.create(CancellableTransaction.prototype, {
|
|||
|
||||
let responseStatus = response.headers["x-mms-response-status"];
|
||||
callback(responseStatus, response);
|
||||
});
|
||||
}).bind(this));
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
|
|
|
@ -19,7 +19,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
|||
'android/MobileMessageDatabaseService.cpp',
|
||||
'android/SmsService.cpp',
|
||||
]
|
||||
elif CONFIG['MOZ_B2G_RIL']:
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
EXTRA_JS_MODULES = [
|
||||
'gonk/mms_consts.js',
|
||||
'gonk/MmsPduHelper.jsm',
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_smsdatabaseservice.xul \
|
||||
$(NULL)
|
||||
endif
|
||||
|
|
|
@ -1,876 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Test MobileMessageDatabaseService by SMS"
|
||||
onload="run_test();">
|
||||
<title>Test MobileMessageDatabaseService by SMS</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
function run_test() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
let gTests = [];
|
||||
|
||||
function add_test(func) {
|
||||
gTests.push(func);
|
||||
}
|
||||
|
||||
function run_next_test() {
|
||||
let func = gTests.shift();
|
||||
if (!func) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
SimpleTest.executeSoon(func);
|
||||
}
|
||||
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let gMobileMessageDatabaseService = Cc["@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1"]
|
||||
.getService(Ci.nsIMobileMessageDatabaseService);
|
||||
|
||||
let gRegistrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
|
||||
let SmsRequestManagerImpl = {
|
||||
notifySmsSent: function notifySmsSent(requestId, message) {
|
||||
ok(false, "Unexpected notifySmsSent.");
|
||||
},
|
||||
notifySmsSendFailed: function notifySmsSendFailed(requestId, error) {
|
||||
ok(false, "Unexpected notifySmsSendFailed.");
|
||||
},
|
||||
notifyGotSms: function notifyGotSms(requestId, message) {
|
||||
ok(false, "Unexpected notifyGotSms.");
|
||||
},
|
||||
notifyGetSmsFailed: function notifyGetSmsFailed(requestId, error) {
|
||||
ok(false, "Unexpected notifyGetSmsFailed." + k);
|
||||
},
|
||||
notifySmsDeleted: function notifySmsDeleted(requestId, message) {
|
||||
ok(false, "Unexpected notifySmsSent.");
|
||||
},
|
||||
notifySmsDeleteFailed: function notifySmsDeleteFailed(requestId, error) {
|
||||
ok(false, "Unexpected notifySmsDeleteFailed.");
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(false, "Unexpected notifyNoMessageInList.");
|
||||
},
|
||||
noitfyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
ok(false, "Unexpected notifyCreateMessageList.");
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId, message) {
|
||||
ok(false, "Unexpected notifyGotNextMessage.");
|
||||
},
|
||||
notifyReadMessageListFailed: function notifyReadMessageListFailed(requestId, error) {
|
||||
ok(false, "Unexpected notifyReadMessageListFailed.");
|
||||
}
|
||||
};
|
||||
|
||||
let FakeSmsRequestManagerService = {
|
||||
contractID: "@mozilla.org/sms/smsrequestmanager;1",
|
||||
//get CID() { return gRegistrar.contractIDToCID(this.contractID); },
|
||||
CID: Components.ID("{a97a3129-1e0b-45da-a385-cfe5b0b1c48f}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISmsRequestManager,
|
||||
Ci.nsIFactory]),
|
||||
createInstance: function createInstance(outer, iid) {
|
||||
if (outer != null) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
__proto__: SmsRequestManagerImpl
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and register a new fake nsISmsRequestManager service.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* fakeSmsRequestManager({
|
||||
* notifySmsSent: function notifySmsSent() {
|
||||
* ...
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function fakeSmsRequestManager(obj) {
|
||||
let service = FakeSmsRequestManagerService;
|
||||
|
||||
// Clean previous methods from the service, then copy new ones onto it.
|
||||
for (let name in SmsRequestManagerImpl) {
|
||||
delete service[name];
|
||||
}
|
||||
for (let name in obj) {
|
||||
service[name] = obj[name];
|
||||
}
|
||||
|
||||
// Register service
|
||||
let oldFactory = Components.manager.getClassObject(Cc[service.contractID],
|
||||
Ci.nsIFactory);
|
||||
gRegistrar.unregisterFactory(service.CID, oldFactory);
|
||||
gRegistrar.registerFactory(service.CID,
|
||||
"Fake SmsRequestManager",
|
||||
service.contractID,
|
||||
service);
|
||||
}
|
||||
|
||||
const DB_NAME = "sms";
|
||||
const DB_VERSION = 2;
|
||||
const STORE_NAME = "sms";
|
||||
const MAX_SMS = 3;
|
||||
const LONG_MAX = 2147483647;
|
||||
|
||||
let _db;
|
||||
function ensureDB(callback) {
|
||||
if (_db) {
|
||||
callback(_db);
|
||||
return;
|
||||
}
|
||||
let request;
|
||||
try {
|
||||
request = indexedDB.open(DB_NAME, DB_VERSION);
|
||||
} catch (ex) {
|
||||
ok(false, ex);
|
||||
}
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
_db = request.result;
|
||||
callback(_db);
|
||||
};
|
||||
request.onerror =
|
||||
request.onupgradeneeded =
|
||||
request.onblocked = function onerror(event) {
|
||||
ok(false, "Opening DB failed: " + request.errorCode);
|
||||
};
|
||||
};
|
||||
|
||||
function checkDB(callback) {
|
||||
ensureDB(function (db) {
|
||||
let txn = db.transaction([STORE_NAME], "readwrite");
|
||||
let store = txn.objectStore(STORE_NAME);
|
||||
txn.oncomplete = run_next_test;
|
||||
txn.onerror = function onerror(event) {
|
||||
ok(false, "Transaction failed: " + event.target.errorCode);
|
||||
};
|
||||
callback(store);
|
||||
});
|
||||
}
|
||||
|
||||
function newRandomId() {
|
||||
return Math.floor(Math.random() * LONG_MAX);
|
||||
};
|
||||
|
||||
let sms = [
|
||||
{
|
||||
type: "sms",
|
||||
sender: "+34666000000",
|
||||
receiver: "+34666111000",
|
||||
body: "message 0",
|
||||
messageClass: "normal",
|
||||
timestamp: 1329999861762
|
||||
},
|
||||
{
|
||||
type: "sms",
|
||||
sender: "+34666000111",
|
||||
receiver: "+34666111111",
|
||||
body: "message 1",
|
||||
messageClass: "normal",
|
||||
timestamp: 1329999861763
|
||||
},
|
||||
{
|
||||
type: "sms",
|
||||
sender: "+34666000222",
|
||||
receiver: "+34666111222",
|
||||
body: "message 2",
|
||||
messageClass: "normal",
|
||||
timestamp: 1329999861764
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.saveReceivedMessage
|
||||
*/
|
||||
add_test(function test_saveReceivedMessage() {
|
||||
info("test_saveReceivedMessage");
|
||||
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]);
|
||||
checkDB(function (store) {
|
||||
let request = store.get(messageId);
|
||||
request.onsuccess = function onsuccess() {
|
||||
let data = request.result;
|
||||
isnot(data, null);
|
||||
is(data.id, messageId);
|
||||
is(data.sender, sms[0].sender);
|
||||
is(data.receiver, null);
|
||||
is(data.body, sms[0].body);
|
||||
is(data.timestamp, sms[0].timestamp);
|
||||
is(data.read, false);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.saveSentMessage
|
||||
*/
|
||||
add_test(function test_saveSentMessage() {
|
||||
info("test_saveSentMessage");
|
||||
let messageId = gMobileMessageDatabaseService.saveSentMessage(sms[1].receiver,
|
||||
sms[1].body,
|
||||
sms[1].timestamp);
|
||||
|
||||
checkDB(function (store) {
|
||||
let request = store.get(messageId);
|
||||
request.onsuccess = function onsuccess() {
|
||||
let data = request.result;
|
||||
isnot(data, null);
|
||||
is(data.id, messageId);
|
||||
is(data.sender, null);
|
||||
is(data.receiver, sms[1].receiver);
|
||||
is(data.body, sms[1].body);
|
||||
is(data.timestamp, sms[1].timestamp);
|
||||
is(data.read, true);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.getMessage
|
||||
*/
|
||||
add_test(function test_getMessage_success() {
|
||||
info("test_getMessage_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyGotSms: function notifyGotSms(requestId, message) {
|
||||
is(requestId, fakeRequestId);
|
||||
ok(message instanceof Ci.nsIDOMMozSmsMessage);
|
||||
is(message.id, messageId);
|
||||
is(message.delivery, "received");
|
||||
is(message.sender, sms[2].sender);
|
||||
is(message.receiver, null);
|
||||
is(message.body, sms[2].body);
|
||||
is(message.read, false);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]);
|
||||
SimpleTest.executeSoon(function () {
|
||||
gMobileMessageDatabaseService.getMessage(messageId, fakeRequestId);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_getMessage_failed() {
|
||||
info("test_getMessage_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyGetSmsFailed: function notifyGetSmsFailed(requestId, error) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(error, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
gMobileMessageDatabaseService.getMessage(-1, fakeRequestId);
|
||||
});
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.createMessageList
|
||||
*/
|
||||
function checkReceivedSms(message, i) {
|
||||
ok(message instanceof Ci.nsIDOMMozSmsMessage);
|
||||
is(message.sender, sms[i].sender);
|
||||
is(message.receiver, null);
|
||||
is(message.body, sms[i].body);
|
||||
is(message.timestamp.getTime(), sms[i].timestamp);
|
||||
is(message.read, false);
|
||||
}
|
||||
|
||||
function checkSentSms(message, i) {
|
||||
ok(message instanceof Ci.nsIDOMMozSmsMessage);
|
||||
is(message.sender, null);
|
||||
is(message.receiver, sms[i].receiver);
|
||||
is(message.body, sms[i].body);
|
||||
is(message.timestamp.getTime(), sms[i].timestamp);
|
||||
is(message.read, true);
|
||||
}
|
||||
|
||||
add_test(function test_createMessageList_empty_filter() {
|
||||
info("test_createMessageList_empty_filter");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let i = 0;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, i);
|
||||
auxListId = listId;
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
ok(message instanceof Ci.nsIDOMMozSmsMessage);
|
||||
i % 2 ? checkSentSms(message, i) : checkReceivedSms(message, i);
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(i, MAX_SMS);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_empty_filter_reverse() {
|
||||
info("test_createMessageList_empty_filter_reverse");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let i = 2;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, i);
|
||||
auxListId = listId;
|
||||
i -= 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
ok(message instanceof Ci.nsIDOMMozSmsMessage);
|
||||
i % 2 ? checkSentSms(message, i) : checkReceivedSms(message, i);
|
||||
i -= 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(i, -1);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
gMobileMessageDatabaseService.createMessageList(filter, true, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_complete_filter_one_result() {
|
||||
info("test_createMessageList_complete_filter_one_result");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
ok(false, "No more messages expected");
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[0].timestamp);
|
||||
filter.endDate = new Date(sms[0].timestamp);
|
||||
filter.numbers = [sms[0].sender];
|
||||
filter.delivery = "received";
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_complete_filter_multi_result() {
|
||||
info("test_createMessageList_complete_filter_multi_result");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let secondMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
auxListId = listId;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId, message) {
|
||||
ok(!secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 2);
|
||||
secondMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[0].timestamp);
|
||||
filter.endDate = new Date(sms[2].timestamp);
|
||||
filter.numbers = [sms[0].sender, sms[2].sender];
|
||||
filter.delivery = "received";
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_complete_filter_no_result() {
|
||||
info("test_createMessageList_complete_filter_no_result");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
},
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[0].timestamp);
|
||||
filter.endDate = new Date(sms[0].timestamp);
|
||||
filter.numbers = [sms[0].sender];
|
||||
filter.delivery = "sent";
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_delivery_sent_filter_success() {
|
||||
info("test_createMessageList_delivery_sent_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkSentSms(message, 1);
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.delivery = "sent";
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_delivery_received_filter_success() {
|
||||
info("test_createMessageList_delivery_received_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let secondMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
auxListId = listId;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId, message) {
|
||||
ok(!secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 2);
|
||||
secondMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.delivery = "received";
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_startDate_filter_success() {
|
||||
info("test_createMessageList_startDate_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let i = 0;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, i);
|
||||
auxListId = listId;
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
i % 2 ? checkSentSms(message, i) : checkReceivedSms(message, i);
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(i, MAX_SMS);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[0].timestamp);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_startDate_filter_failed() {
|
||||
info("test_createMessageList_startDate_filter_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
},
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[2].timestamp + 1);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_endDate_filter_success() {
|
||||
info("test_createMessageList_endDate_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let i = 0;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, i);
|
||||
auxListId = listId;
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
i % 2 ? checkSentSms(message, i) : checkReceivedSms(message, i);
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(i, MAX_SMS);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.endDate = new Date(sms[2].timestamp);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_endDate_filter_failed() {
|
||||
info("test_createMessageList_endDate_filter_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.endDate = new Date(sms[0].timestamp - 1);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_fullDate_filter_success() {
|
||||
info("test_createMessageList_fullDate_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let i = 0;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, i);
|
||||
auxListId = listId;
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
i % 2 ? checkSentSms(message, i) : checkReceivedSms(message, i);
|
||||
i += 1;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(i, MAX_SMS);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[0].timestamp);
|
||||
filter.endDate = new Date(sms[MAX_SMS - 1].timestamp);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_fullDate_filter_failed() {
|
||||
info("test_createMessageList_fullDate_filter_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.startDate = new Date(sms[MAX_SMS - 1] + 1);
|
||||
filter.endDate = new Date(sms[MAX_SMS - 1] + 1);
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_single_number_success() {
|
||||
info("test_createMessageList_single_number_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let firstMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(firstMessage, false);
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
firstMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(firstMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.numbers = [sms[0].sender];
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_single_number_failed() {
|
||||
info("test_createMessageList_single_number_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.numbers = ["00000000000"];
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_multi_number_success() {
|
||||
info("test_createMessageList_multi_number_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let auxListId;
|
||||
let secondMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
auxListId = listId;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId, message) {
|
||||
ok(!secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
checkSentSms(message, 1);
|
||||
secondMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(auxListId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.numbers = [sms[0].sender, sms[1].receiver];
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_multi_number_wrong_number_success() {
|
||||
info("test_createMessageList_multi_number_wrong_number_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let firstMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(firstMessage, false);
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
firstMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(firstMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.numbers = ["00000000000", sms[0].sender];
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_createMessageList_multi_number_failed() {
|
||||
info("test_createMessageList_multi_number_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let filter = new MozSmsFilter();
|
||||
filter.numbers = ["00000000000", "11111111111"];
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
|
||||
|
||||
add_test(function test_createMessageList_read_filter_success() {
|
||||
info("test_createMessageList_read_filter_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
let lId;
|
||||
let secondMessage = false;
|
||||
fakeSmsRequestManager({
|
||||
notifyCreateMessageList: function notifyCreateMessageList(requestId,
|
||||
listId,
|
||||
message) {
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 0);
|
||||
lId = listId;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(listId, requestId);
|
||||
},
|
||||
notifyGotNextMessage: function notifyGotNextMessage(requestId, message) {
|
||||
ok(!secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
checkReceivedSms(message, 2);
|
||||
secondMessage = true;
|
||||
gMobileMessageDatabaseService.getNextMessageInList(lId, requestId);
|
||||
},
|
||||
notifyNoMessageInList: function notifyNoMessageInList(requestId) {
|
||||
ok(secondMessage);
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
SimpleTest.executeSoon(function () {
|
||||
let filter = new MozSmsFilter();
|
||||
filter.read = false;
|
||||
gMobileMessageDatabaseService.createMessageList(filter, false, fakeRequestId);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.getNextMessageInList
|
||||
*/
|
||||
add_test(function test_getNextMessageInList_unknown_list() {
|
||||
info("test_getNextMessageInList_unknown_list");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyReadMessageListFailed:
|
||||
function notifyReadMessageListFailed(requestId) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
gMobileMessageDatabaseService.getNextMessageInList(-1, fakeRequestId);
|
||||
});
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService.deleteMessage
|
||||
*/
|
||||
add_test(function test_deleteMessage_success() {
|
||||
info("test_deleteMessage_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifySmsDeleted: function notifySmsDeleted(requestId, deleted) {
|
||||
is(requestId, fakeRequestId);
|
||||
ok(deleted);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]);
|
||||
SimpleTest.executeSoon(function () {
|
||||
gMobileMessageDatabaseService.deleteMessage(messageId, fakeRequestId);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_deleteMessage_failed() {
|
||||
info("test_deleteMessage_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifySmsDeleted: function notifySmsDeleted(requestId, deleted) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(deleted, false);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
gMobileMessageDatabaseService.deleteMessage(-1, fakeRequestId);
|
||||
});
|
||||
|
||||
add_test(function test_markMessageRead_success() {
|
||||
info("test_markMessageRead_success");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyMarkedMessageRead: function notifyMarkedMessageRead(requestId, read) {
|
||||
is(requestId, fakeRequestId);
|
||||
is(read, true);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]);
|
||||
SimpleTest.executeSoon(function () {
|
||||
gMobileMessageDatabaseService.markMessageRead(messageId, true, fakeRequestId);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_markMessageRead_failed() {
|
||||
info("test_markMessageRead_failed");
|
||||
let fakeRequestId = newRandomId();
|
||||
fakeSmsRequestManager({
|
||||
notifyMarkMessageReadFailed: function notifyMarkMessageReadFailed(requestId, error) {
|
||||
is(requestId, fakeRequestId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
SimpleTest.executeSoon(function () {
|
||||
gMobileMessageDatabaseService.markMessageRead(-1, true, fakeRequestId);
|
||||
});
|
||||
});
|
||||
|
||||
]]></script>
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</window>
|
|
@ -3,7 +3,6 @@ head = header_helpers.js
|
|||
tail =
|
||||
support-files =
|
||||
test_sms_basics.html
|
||||
test_smsdatabaseservice.xul
|
||||
test_smsfilter.html
|
||||
|
||||
[test_smsservice_createsmsmessage.js]
|
||||
|
|
|
@ -72,7 +72,6 @@ PARALLEL_DIRS += [
|
|||
'camera',
|
||||
'audiochannel',
|
||||
'promise',
|
||||
'wappush',
|
||||
'telephony',
|
||||
'inputmethod',
|
||||
'webidl',
|
||||
|
@ -81,12 +80,15 @@ PARALLEL_DIRS += [
|
|||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
PARALLEL_DIRS += ['plugins/ipc/hangui']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
PARALLEL_DIRS += ['wifi']
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
PARALLEL_DIRS += [
|
||||
'wifi',
|
||||
'icc',
|
||||
'cellbroadcast',
|
||||
'voicemail',
|
||||
'wappush',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PAY']:
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMConnection.idl',
|
||||
'nsIDOMDataErrorEvent.idl',
|
||||
'nsIDOMTCPServerSocket.idl',
|
||||
'nsIDOMTCPSocket.idl',
|
||||
'nsIDOMUSSDReceivedEvent.idl',
|
||||
'nsIMozNavigatorNetwork.idl',
|
||||
'nsITCPServerSocketChild.idl',
|
||||
'nsITCPServerSocketParent.idl',
|
||||
|
@ -20,12 +18,18 @@ XPIDL_SOURCES += [
|
|||
if CONFIG['MOZ_B2G_RIL']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMCFStateChangeEvent.idl',
|
||||
'nsIDOMDataErrorEvent.idl',
|
||||
'nsIDOMMobileConnection.idl',
|
||||
'nsIDOMMozEmergencyCbModeEvent.idl',
|
||||
'nsIDOMMozOtaStatusEvent.idl',
|
||||
'nsIDOMUSSDReceivedEvent.idl',
|
||||
'nsIMobileConnectionProvider.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMNetworkStats.idl',
|
||||
'nsIDOMNetworkStatsManager.idl',
|
||||
'nsIMobileConnectionProvider.idl',
|
||||
'nsINetworkStatsServiceProxy.idl',
|
||||
]
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ interface nsIDOMMozMobileConnectionInfo;
|
|||
interface nsIDOMMozMobileNetworkInfo;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(f1878629-4151-4e02-a22a-8cec3d7eddee)]
|
||||
[scriptable, uuid(f02c50d5-9d34-4f24-80eb-527a280e31fa)]
|
||||
interface nsIMobileConnectionListener : nsISupports
|
||||
{
|
||||
void notifyVoiceChanged();
|
||||
|
@ -27,13 +27,14 @@ interface nsIMobileConnectionListener : nsISupports
|
|||
void notifyEmergencyCbModeChanged(in boolean active,
|
||||
in unsigned long timeoutMs);
|
||||
void notifyOtaStatusChanged(in DOMString status);
|
||||
void notifyIccChanged();
|
||||
};
|
||||
|
||||
/**
|
||||
* XPCOM component (in the content process) that provides the mobile
|
||||
* network information.
|
||||
*/
|
||||
[scriptable, uuid(c66652e0-0628-11e3-8ffd-0800200c9a66)]
|
||||
[scriptable, uuid(84278a49-0f05-4585-b3f4-c74882ae5719)]
|
||||
interface nsIMobileConnectionProvider : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -41,47 +42,71 @@ interface nsIMobileConnectionProvider : nsISupports
|
|||
* RadioInterfaceLayer in the chrome process. Only a content process that has
|
||||
* the 'mobileconnection' permission is allowed to register.
|
||||
*/
|
||||
void registerMobileConnectionMsg(in nsIMobileConnectionListener listener);
|
||||
void unregisterMobileConnectionMsg(in nsIMobileConnectionListener listener);
|
||||
void registerMobileConnectionMsg(in unsigned long clientId,
|
||||
in nsIMobileConnectionListener listener);
|
||||
void unregisterMobileConnectionMsg(in unsigned long clientId,
|
||||
in nsIMobileConnectionListener listener);
|
||||
|
||||
readonly attribute nsIDOMMozMobileConnectionInfo voiceConnectionInfo;
|
||||
readonly attribute nsIDOMMozMobileConnectionInfo dataConnectionInfo;
|
||||
readonly attribute DOMString networkSelectionMode;
|
||||
nsIDOMMozMobileConnectionInfo getVoiceConnectionInfo(in unsigned long clientId);
|
||||
nsIDOMMozMobileConnectionInfo getDataConnectionInfo(in unsigned long clientId);
|
||||
DOMString getIccId(in unsigned long clientId);
|
||||
DOMString getNetworkSelectionMode(in unsigned long clientId);
|
||||
|
||||
nsIDOMDOMRequest getNetworks(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest selectNetwork(in nsIDOMWindow window, in nsIDOMMozMobileNetworkInfo network);
|
||||
nsIDOMDOMRequest selectNetworkAutomatically(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest getNetworks(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest selectNetwork(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in nsIDOMMozMobileNetworkInfo network);
|
||||
nsIDOMDOMRequest selectNetworkAutomatically(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest setRoamingPreference(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest setRoamingPreference(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in DOMString mode);
|
||||
nsIDOMDOMRequest getRoamingPreference(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest getRoamingPreference(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest setVoicePrivacyMode(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest setVoicePrivacyMode(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in bool enabled);
|
||||
nsIDOMDOMRequest getVoicePrivacyMode(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest getVoicePrivacyMode(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest sendMMI(in nsIDOMWindow window, in DOMString mmi);
|
||||
nsIDOMDOMRequest cancelMMI(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest sendMMI(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in DOMString mmi);
|
||||
nsIDOMDOMRequest cancelMMI(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest getCallForwardingOption(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest getCallForwardingOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in unsigned short reason);
|
||||
nsIDOMDOMRequest setCallForwardingOption(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest setCallForwardingOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in nsIDOMMozMobileCFInfo CFInfo);
|
||||
|
||||
nsIDOMDOMRequest getCallBarringOption(in nsIDOMWindow window,
|
||||
in jsval option);
|
||||
nsIDOMDOMRequest setCallBarringOption(in nsIDOMWindow window,
|
||||
in jsval option);
|
||||
nsIDOMDOMRequest changeCallBarringPassword(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest getCallBarringOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in jsval option);
|
||||
nsIDOMDOMRequest setCallBarringOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in jsval option);
|
||||
nsIDOMDOMRequest changeCallBarringPassword(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in jsval info);
|
||||
|
||||
nsIDOMDOMRequest setCallWaitingOption(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest setCallWaitingOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in bool enabled);
|
||||
nsIDOMDOMRequest getCallWaitingOption(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest getCallWaitingOption(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest setCallingLineIdRestriction(in nsIDOMWindow window,
|
||||
nsIDOMDOMRequest setCallingLineIdRestriction(in unsigned long clientId,
|
||||
in nsIDOMWindow window,
|
||||
in unsigned short clirMode);
|
||||
nsIDOMDOMRequest getCallingLineIdRestriction(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest getCallingLineIdRestriction(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
|
||||
nsIDOMDOMRequest exitEmergencyCbMode(in nsIDOMWindow window);
|
||||
nsIDOMDOMRequest exitEmergencyCbMode(in unsigned long clientId,
|
||||
in nsIDOMWindow window);
|
||||
};
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* 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 "MobileConnection.h"
|
||||
#include "mozilla/dom/network/MobileConnection.h"
|
||||
|
||||
#include "GeneratedEvents.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsDOMEvent.h"
|
||||
|
@ -82,6 +83,9 @@ MobileConnection::MobileConnection()
|
|||
mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
mWindow = nullptr;
|
||||
|
||||
// TODO: Bug 814629 - WebMobileConnection API: support multiple sim cards
|
||||
mClientId = 0;
|
||||
|
||||
// Not being able to acquire the provider isn't fatal since we check
|
||||
// for it explicitly below.
|
||||
if (!mProvider) {
|
||||
|
@ -100,7 +104,7 @@ MobileConnection::Init(nsPIDOMWindow* aWindow)
|
|||
|
||||
if (!CheckPermission("mobilenetwork") &&
|
||||
CheckPermission("mobileconnection")) {
|
||||
DebugOnly<nsresult> rv = mProvider->RegisterMobileConnectionMsg(mListener);
|
||||
DebugOnly<nsresult> rv = mProvider->RegisterMobileConnectionMsg(mClientId, mListener);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"Failed registering mobile connection messages with provider");
|
||||
|
||||
|
@ -113,7 +117,7 @@ MobileConnection::Shutdown()
|
|||
{
|
||||
if (mProvider && mListener) {
|
||||
mListener->Disconnect();
|
||||
mProvider->UnregisterMobileConnectionMsg(mListener);
|
||||
mProvider->UnregisterMobileConnectionMsg(mClientId, mListener);
|
||||
mProvider = nullptr;
|
||||
mListener = nullptr;
|
||||
}
|
||||
|
@ -172,7 +176,7 @@ MobileConnection::GetVoice(nsIDOMMozMobileConnectionInfo** voice)
|
|||
if (!mProvider || !CheckPermission("mobileconnection")) {
|
||||
return NS_OK;
|
||||
}
|
||||
return mProvider->GetVoiceConnectionInfo(voice);
|
||||
return mProvider->GetVoiceConnectionInfo(mClientId, voice);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -183,7 +187,7 @@ MobileConnection::GetData(nsIDOMMozMobileConnectionInfo** data)
|
|||
if (!mProvider || !CheckPermission("mobileconnection")) {
|
||||
return NS_OK;
|
||||
}
|
||||
return mProvider->GetDataConnectionInfo(data);
|
||||
return mProvider->GetDataConnectionInfo(mClientId, data);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -194,7 +198,7 @@ MobileConnection::GetNetworkSelectionMode(nsAString& networkSelectionMode)
|
|||
if (!mProvider || !CheckPermission("mobileconnection")) {
|
||||
return NS_OK;
|
||||
}
|
||||
return mProvider->GetNetworkSelectionMode(networkSelectionMode);
|
||||
return mProvider->GetNetworkSelectionMode(mClientId, networkSelectionMode);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -210,7 +214,7 @@ MobileConnection::GetNetworks(nsIDOMDOMRequest** request)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetNetworks(GetOwner(), request);
|
||||
return mProvider->GetNetworks(mClientId, GetOwner(), request);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -226,7 +230,7 @@ MobileConnection::SelectNetwork(nsIDOMMozMobileNetworkInfo* network, nsIDOMDOMRe
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SelectNetwork(GetOwner(), network, request);
|
||||
return mProvider->SelectNetwork(mClientId, GetOwner(), network, request);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -242,7 +246,7 @@ MobileConnection::SelectNetworkAutomatically(nsIDOMDOMRequest** request)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SelectNetworkAutomatically(GetOwner(), request);
|
||||
return mProvider->SelectNetworkAutomatically(mClientId, GetOwner(), request);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -258,7 +262,7 @@ MobileConnection::SetRoamingPreference(const nsAString& aMode, nsIDOMDOMRequest*
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetRoamingPreference(GetOwner(), aMode, aDomRequest);
|
||||
return mProvider->SetRoamingPreference(mClientId, GetOwner(), aMode, aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -274,7 +278,7 @@ MobileConnection::GetRoamingPreference(nsIDOMDOMRequest** aDomRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetRoamingPreference(GetOwner(), aDomRequest);
|
||||
return mProvider->GetRoamingPreference(mClientId, GetOwner(), aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -290,7 +294,7 @@ MobileConnection::SetVoicePrivacyMode(bool aEnabled, nsIDOMDOMRequest** aDomRequ
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetVoicePrivacyMode(GetOwner(), aEnabled, aDomRequest);
|
||||
return mProvider->SetVoicePrivacyMode(mClientId, GetOwner(), aEnabled, aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -306,7 +310,7 @@ MobileConnection::GetVoicePrivacyMode(nsIDOMDOMRequest** aDomRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetVoicePrivacyMode(GetOwner(), aDomRequest);
|
||||
return mProvider->GetVoicePrivacyMode(mClientId, GetOwner(), aDomRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -321,7 +325,7 @@ MobileConnection::SendMMI(const nsAString& aMMIString,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SendMMI(GetOwner(), aMMIString, aRequest);
|
||||
return mProvider->SendMMI(mClientId, GetOwner(), aMMIString, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -335,7 +339,7 @@ MobileConnection::CancelMMI(nsIDOMDOMRequest** aRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->CancelMMI(GetOwner(), aRequest);
|
||||
return mProvider->CancelMMI(mClientId, GetOwner(),aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -352,7 +356,7 @@ MobileConnection::GetCallForwardingOption(uint16_t aReason,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetCallForwardingOption(GetOwner(), aReason, aRequest);
|
||||
return mProvider->GetCallForwardingOption(mClientId, GetOwner(), aReason, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -369,7 +373,7 @@ MobileConnection::SetCallForwardingOption(nsIDOMMozMobileCFInfo* aCFInfo,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetCallForwardingOption(GetOwner(), aCFInfo, aRequest);
|
||||
return mProvider->SetCallForwardingOption(mClientId, GetOwner(), aCFInfo, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -386,7 +390,7 @@ MobileConnection::GetCallBarringOption(const JS::Value& aOption,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetCallBarringOption(GetOwner(), aOption, aRequest);
|
||||
return mProvider->GetCallBarringOption(mClientId, GetOwner(), aOption, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -403,7 +407,7 @@ MobileConnection::SetCallBarringOption(const JS::Value& aOption,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetCallBarringOption(GetOwner(), aOption, aRequest);
|
||||
return mProvider->SetCallBarringOption(mClientId, GetOwner(), aOption, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -420,7 +424,7 @@ MobileConnection::ChangeCallBarringPassword(const JS::Value& aInfo,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->ChangeCallBarringPassword(GetOwner(), aInfo, aRequest);
|
||||
return mProvider->ChangeCallBarringPassword(mClientId, GetOwner(), aInfo, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -436,7 +440,7 @@ MobileConnection::GetCallWaitingOption(nsIDOMDOMRequest** aRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetCallWaitingOption(GetOwner(), aRequest);
|
||||
return mProvider->GetCallWaitingOption(mClientId, GetOwner(), aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -453,7 +457,7 @@ MobileConnection::SetCallWaitingOption(bool aEnabled,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetCallWaitingOption(GetOwner(), aEnabled, aRequest);
|
||||
return mProvider->SetCallWaitingOption(mClientId, GetOwner(), aEnabled, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -469,7 +473,7 @@ MobileConnection::GetCallingLineIdRestriction(nsIDOMDOMRequest** aRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->GetCallingLineIdRestriction(GetOwner(), aRequest);
|
||||
return mProvider->GetCallingLineIdRestriction(mClientId, GetOwner(), aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -486,7 +490,7 @@ MobileConnection::SetCallingLineIdRestriction(unsigned short aClirMode,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->SetCallingLineIdRestriction(GetOwner(), aClirMode, aRequest);
|
||||
return mProvider->SetCallingLineIdRestriction(mClientId, GetOwner(), aClirMode, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -502,7 +506,7 @@ MobileConnection::ExitEmergencyCbMode(nsIDOMDOMRequest** aRequest)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mProvider->ExitEmergencyCbMode(GetOwner(), aRequest);
|
||||
return mProvider->ExitEmergencyCbMode(mClientId, GetOwner(), aRequest);
|
||||
}
|
||||
|
||||
// nsIMobileConnectionListener
|
||||
|
@ -630,3 +634,11 @@ MobileConnection::NotifyOtaStatusChanged(const nsAString& aStatus)
|
|||
|
||||
return DispatchTrustedEvent(ce);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileConnection::NotifyIccChanged()
|
||||
{
|
||||
// TODO: Bug 814629 - WebMobileConnection API: support multiple sim cards
|
||||
// Return NS_OK for now, will be implemented in Bug 814629.
|
||||
return NS_OK;
|
||||
}
|
|
@ -48,6 +48,8 @@ private:
|
|||
nsRefPtr<Listener> mListener;
|
||||
nsWeakPtr mWindow;
|
||||
|
||||
uint32_t mClientId;
|
||||
|
||||
bool CheckPermission(const char* type);
|
||||
};
|
||||
|
||||
|
|
|
@ -46,12 +46,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
|||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gRadioInterface", function () {
|
||||
let ril = Cc["@mozilla.org/ril;1"].getService(Ci["nsIRadioInterfaceLayer"]);
|
||||
// TODO: Bug 923382 - B2G Multi-SIM: support multiple SIM cards for network metering.
|
||||
return ril.getRadioInterface(0);
|
||||
});
|
||||
|
||||
this.NetworkStatsService = {
|
||||
init: function() {
|
||||
debug("Service started");
|
||||
|
@ -202,10 +196,13 @@ this.NetworkStatsService = {
|
|||
|
||||
let id = '0';
|
||||
if (aNetwork.type == NET_TYPE_MOBILE) {
|
||||
// Bug 904542 will provide the serviceId to map the iccId with the
|
||||
// nsINetworkInterface of the NetworkManager. Now, lets assume that
|
||||
// network is mapped with the current iccId of the single SIM.
|
||||
id = gRadioInterface.rilContext.iccInfo.iccid;
|
||||
if (!(aNetwork instanceof Ci.nsIRilNetworkInterface)) {
|
||||
debug("Error! Mobile network should be an nsIRilNetworkInterface!");
|
||||
return null;
|
||||
}
|
||||
|
||||
let rilNetwork = aNetwork.QueryInterface(Ci.nsIRilNetworkInterface);
|
||||
id = rilNetwork.iccId;
|
||||
}
|
||||
|
||||
let netId = this.getNetworkId(id, aNetwork.type);
|
||||
|
@ -271,12 +268,13 @@ this.NetworkStatsService = {
|
|||
debug("getstats for network " + network.id + " of type " + network.type);
|
||||
debug("appId: " + appId + " from manifestURL: " + manifestURL);
|
||||
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, network, start, end, appId, manifestURL);
|
||||
|
||||
});
|
||||
this.updateCachedAppStats(function onAppStatsUpdated(aResult, aMessage) {
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, network, start, end, appId, manifestURL);
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
clearInterfaceStats: function clearInterfaceStats(mm, msg) {
|
||||
|
@ -564,6 +562,10 @@ this.NetworkStatsService = {
|
|||
let stats = Object.keys(this.cachedAppStats);
|
||||
if (stats.length == 0) {
|
||||
// |cachedAppStats| is empty, no need to update.
|
||||
if (aCallback) {
|
||||
aCallback(true, "no need to update");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,14 @@ SOURCES += [
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
EXPORTS.mozilla.dom.network += [
|
||||
'MobileConnection.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'MobileConnection.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
EXTRA_JS_MODULES = [
|
||||
'NetworkStatsDB.jsm',
|
||||
'NetworkStatsService.jsm',
|
||||
|
@ -40,7 +45,7 @@ EXTRA_PP_COMPONENTS += [
|
|||
'TCPSocket.js',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
EXTRA_COMPONENTS += [
|
||||
'NetworkStatsManager.js',
|
||||
'NetworkStatsManager.manifest',
|
||||
|
|
|
@ -9,7 +9,7 @@ MOCHITEST_FILES = \
|
|||
test_tcpsocket_enabled_with_perm.html \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_FILES = \
|
||||
test_networkstats_basics.html \
|
||||
test_networkstats_disabled.html \
|
||||
|
|
|
@ -44,7 +44,8 @@ this.PhoneNumberUtils = {
|
|||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Get network mcc
|
||||
let voice = mobileConnection.voiceConnectionInfo;
|
||||
// TODO: Bug 926740 - PhoneNumberUtils for multisim
|
||||
let voice = mobileConnection.getVoiceConnectionInfo(0);
|
||||
if (voice && voice.network && voice.network.mcc) {
|
||||
mcc = voice.network.mcc;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ public:
|
|||
JSContext* aCx)
|
||||
{
|
||||
MOZ_ASSERT(!aID.IsEmpty());
|
||||
MOZ_ASSERT(!aTitle.IsEmpty());
|
||||
|
||||
NotificationOptions options;
|
||||
options.mDir = Notification::StringToDirection(nsString(aDir));
|
||||
|
|
|
@ -18,19 +18,21 @@
|
|||
#include <hardware/gps.h>
|
||||
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
#include "SystemWorkerManager.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsGeoPosition.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsINetworkManager.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsIDOMIccInfo.h"
|
||||
#include "nsIDOMMobileConnection.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIDOMIccInfo.h"
|
||||
#include "nsIDOMMobileConnection.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#endif
|
||||
|
||||
#ifdef AGPS_TYPE_INVALID
|
||||
#define AGPS_HAVE_DUAL_APN
|
||||
#endif
|
||||
|
@ -44,10 +46,15 @@ static const int kDefaultPeriod = 1000; // ms
|
|||
// While most methods of GonkGPSGeolocationProvider should only be
|
||||
// called from main thread, we deliberately put the Init and ShutdownGPS
|
||||
// methods off main thread to avoid blocking.
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_IMPL_ISUPPORTS3(GonkGPSGeolocationProvider,
|
||||
nsIGeolocationProvider,
|
||||
nsIRILDataCallback,
|
||||
nsISettingsServiceCallback)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider,
|
||||
nsIGeolocationProvider)
|
||||
#endif
|
||||
|
||||
/* static */ GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton = nullptr;
|
||||
GpsCallbacks GonkGPSGeolocationProvider::mCallbacks = {
|
||||
|
@ -65,6 +72,7 @@ GpsCallbacks GonkGPSGeolocationProvider::mCallbacks = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
AGpsCallbacks
|
||||
GonkGPSGeolocationProvider::mAGPSCallbacks = {
|
||||
AGPSStatusCallback,
|
||||
|
@ -77,6 +85,7 @@ GonkGPSGeolocationProvider::mAGPSRILCallbacks = {
|
|||
AGPSRILRefLocCallback,
|
||||
CreateThreadCallback,
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
|
||||
|
@ -146,8 +155,10 @@ GonkGPSGeolocationProvider::SetCapabilitiesCallback(uint32_t capabilities)
|
|||
GonkGPSGeolocationProvider::GetSingleton();
|
||||
|
||||
provider->mSupportsScheduling = mCapabilities & GPS_CAPABILITY_SCHEDULING;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
provider->mSupportsMSB = mCapabilities & GPS_CAPABILITY_MSB;
|
||||
provider->mSupportsMSA = mCapabilities & GPS_CAPABILITY_MSA;
|
||||
#endif
|
||||
provider->mSupportsSingleShot = mCapabilities & GPS_CAPABILITY_SINGLE_SHOT;
|
||||
#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
|
||||
provider->mSupportsTimeInjection = mCapabilities & GPS_CAPABILITY_ON_DEMAND_TIME;
|
||||
|
@ -196,6 +207,7 @@ GonkGPSGeolocationProvider::RequestUtcTimeCallback()
|
|||
{
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
GonkGPSGeolocationProvider::AGPSStatusCallback(AGpsStatus* status)
|
||||
{
|
||||
|
@ -267,12 +279,15 @@ GonkGPSGeolocationProvider::AGPSRILRefLocCallback(uint32_t flags)
|
|||
NS_DispatchToMainThread(new RequestRefLocEvent());
|
||||
}
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
|
||||
: mStarted(false)
|
||||
, mSupportsScheduling(false)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
, mSupportsMSB(false)
|
||||
, mSupportsMSA(false)
|
||||
#endif
|
||||
, mSupportsSingleShot(false)
|
||||
, mSupportsTimeInjection(false)
|
||||
, mGpsInterface(nullptr)
|
||||
|
@ -320,6 +335,7 @@ GonkGPSGeolocationProvider::GetGPSInterface()
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
int32_t
|
||||
GonkGPSGeolocationProvider::GetDataConnectionState()
|
||||
{
|
||||
|
@ -507,6 +523,7 @@ GonkGPSGeolocationProvider::SetReferenceLocation()
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
GonkGPSGeolocationProvider::Init()
|
||||
|
@ -523,6 +540,7 @@ GonkGPSGeolocationProvider::Init()
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
mAGpsInterface =
|
||||
static_cast<const AGpsInterface*>(mGpsInterface->get_extension(AGPS_INTERFACE));
|
||||
if (mAGpsInterface) {
|
||||
|
@ -534,6 +552,7 @@ GonkGPSGeolocationProvider::Init()
|
|||
if (mAGpsRilInterface) {
|
||||
mAGpsRilInterface->init(&mAGPSRILCallbacks);
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::StartGPS));
|
||||
}
|
||||
|
@ -546,19 +565,23 @@ GonkGPSGeolocationProvider::StartGPS()
|
|||
|
||||
int32_t update = Preferences::GetInt("geo.default.update", kDefaultPeriod);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (mSupportsMSA || mSupportsMSB) {
|
||||
SetupAGPS();
|
||||
}
|
||||
#endif
|
||||
|
||||
int positionMode = GPS_POSITION_MODE_STANDALONE;
|
||||
bool singleShot = false;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// XXX: If we know this is a single shot request, use MSA can be faster.
|
||||
if (singleShot && mSupportsMSA) {
|
||||
positionMode = GPS_POSITION_MODE_MS_ASSISTED;
|
||||
} else if (mSupportsMSB) {
|
||||
positionMode = GPS_POSITION_MODE_MS_BASED;
|
||||
}
|
||||
#endif
|
||||
if (!mSupportsScheduling) {
|
||||
update = kDefaultPeriod;
|
||||
}
|
||||
|
@ -574,6 +597,7 @@ GonkGPSGeolocationProvider::StartGPS()
|
|||
mGpsInterface->start();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void
|
||||
GonkGPSGeolocationProvider::SetupAGPS()
|
||||
{
|
||||
|
@ -599,9 +623,8 @@ GonkGPSGeolocationProvider::SetupAGPS()
|
|||
mRadioInterface->RegisterDataCallCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Startup()
|
||||
|
@ -643,9 +666,11 @@ GonkGPSGeolocationProvider::Shutdown()
|
|||
}
|
||||
mStarted = false;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (mRadioInterface) {
|
||||
mRadioInterface->UnregisterDataCallCallback(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
mInitThread->Dispatch(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::ShutdownGPS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
@ -670,6 +695,7 @@ GonkGPSGeolocationProvider::SetHighAccuracy(bool)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/** nsIRILDataCallback interface **/
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -721,3 +747,4 @@ GonkGPSGeolocationProvider::HandleError(const nsAString& aErrorMessage)
|
|||
{
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
#include <hardware/gps.h> // for GpsInterface
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIGeolocationProvider.h"
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsString.h"
|
||||
#include "nsISettingsService.h"
|
||||
#endif
|
||||
|
||||
class nsIThread;
|
||||
|
||||
|
@ -33,14 +34,18 @@ class nsIThread;
|
|||
"@mozilla.org/gonk-gps-geolocation-provider;1"
|
||||
|
||||
class GonkGPSGeolocationProvider : public nsIGeolocationProvider
|
||||
#ifdef MOZ_B2G_RIL
|
||||
, public nsIRILDataCallback
|
||||
, public nsISettingsServiceCallback
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIGEOLOCATIONPROVIDER
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DECL_NSIRILDATACALLBACK
|
||||
NS_DECL_NSISETTINGSSERVICECALLBACK
|
||||
#endif
|
||||
|
||||
static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
|
||||
|
||||
|
@ -61,25 +66,31 @@ private:
|
|||
static void ReleaseWakelockCallback();
|
||||
static pthread_t CreateThreadCallback(const char* name, void (*start)(void*), void* arg);
|
||||
static void RequestUtcTimeCallback();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
static void AGPSStatusCallback(AGpsStatus* status);
|
||||
static void AGPSRILSetIDCallback(uint32_t flags);
|
||||
static void AGPSRILRefLocCallback(uint32_t flags);
|
||||
#endif
|
||||
|
||||
static GpsCallbacks mCallbacks;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
static AGpsCallbacks mAGPSCallbacks;
|
||||
static AGpsRilCallbacks mAGPSRILCallbacks;
|
||||
#endif
|
||||
|
||||
int32_t GetDataConnectionState();
|
||||
void SetAGpsDataConn(nsAString& aApn);
|
||||
void RequestSettingValue(char* aKey);
|
||||
void Init();
|
||||
void SetupAGPS();
|
||||
void StartGPS();
|
||||
void ShutdownGPS();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void SetupAGPS();
|
||||
int32_t GetDataConnectionState();
|
||||
void SetAGpsDataConn(nsAString& aApn);
|
||||
void RequestDataConnection();
|
||||
void ReleaseDataConnection();
|
||||
void RequestSettingValue(char* aKey);
|
||||
void RequestSetID(uint32_t flags);
|
||||
void SetReferenceLocation();
|
||||
#endif
|
||||
|
||||
const GpsInterface* GetGPSInterface();
|
||||
|
||||
|
@ -88,17 +99,21 @@ private:
|
|||
bool mStarted;
|
||||
|
||||
bool mSupportsScheduling;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mSupportsMSB;
|
||||
bool mSupportsMSA;
|
||||
#endif
|
||||
bool mSupportsSingleShot;
|
||||
bool mSupportsTimeInjection;
|
||||
|
||||
const GpsInterface* mGpsInterface;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
const AGpsInterface* mAGpsInterface;
|
||||
const AGpsRilInterface* mAGpsRilInterface;
|
||||
nsCOMPtr<nsIRadioInterface> mRadioInterface;
|
||||
#endif
|
||||
nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
|
||||
nsCOMPtr<nsIThread> mInitThread;
|
||||
nsCOMPtr<nsIRadioInterface> mRadioInterface;
|
||||
};
|
||||
|
||||
#endif /* GonkGPSGeolocationProvider_h */
|
||||
|
|
|
@ -133,8 +133,10 @@ function defineLazyRegExp(obj, name, pattern) {
|
|||
function NetworkManager() {
|
||||
this.networkInterfaces = {};
|
||||
Services.obs.addObserver(this, TOPIC_INTERFACE_STATE_CHANGED, true);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, true);
|
||||
Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, true);
|
||||
#endif
|
||||
Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
|
||||
Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
|
||||
|
||||
|
@ -229,6 +231,7 @@ NetworkManager.prototype = {
|
|||
debug("Network " + network.name + " changed state to " + network.state);
|
||||
switch (network.state) {
|
||||
case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Add host route for data calls
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
|
||||
|
@ -238,16 +241,19 @@ NetworkManager.prototype = {
|
|||
}
|
||||
// Add extra host route. For example, mms proxy or mmsc.
|
||||
this.setExtraHostRoute(network);
|
||||
#endif
|
||||
// Remove pre-created default route and let setAndConfigureActive()
|
||||
// to set default route only on preferred network
|
||||
this.removeDefaultRoute(network.name);
|
||||
this.setAndConfigureActive();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Update data connection when Wifi connected/disconnected
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
|
||||
this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
this.onConnectionChanged(network);
|
||||
|
||||
|
@ -255,6 +261,7 @@ NetworkManager.prototype = {
|
|||
CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
|
||||
break;
|
||||
case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Remove host route for data calls
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
|
||||
|
@ -263,24 +270,30 @@ NetworkManager.prototype = {
|
|||
}
|
||||
// Remove extra host route. For example, mms proxy or mmsc.
|
||||
this.removeExtraHostRoute(network);
|
||||
#endif
|
||||
// Remove routing table in /proc/net/route
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
this.resetRoutingTable(network);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
} else if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
this.removeDefaultRoute(network.name);
|
||||
#endif
|
||||
}
|
||||
// Abort ongoing captive portal detection on the wifi interface
|
||||
CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
|
||||
this.setAndConfigureActive();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Update data connection when Wifi connected/disconnected
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
|
||||
this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
case TOPIC_INTERFACE_REGISTERED:
|
||||
let regNetwork = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
// Add extra host route. For example, mms proxy or mmsc.
|
||||
|
@ -291,6 +304,7 @@ NetworkManager.prototype = {
|
|||
// Remove extra host route. For example, mms proxy or mmsc.
|
||||
this.removeExtraHostRoute(unregNetwork);
|
||||
break;
|
||||
#endif
|
||||
case TOPIC_MOZSETTINGS_CHANGED:
|
||||
let setting = JSON.parse(data);
|
||||
this.handle(setting.key, setting.value);
|
||||
|
@ -303,8 +317,10 @@ NetworkManager.prototype = {
|
|||
case TOPIC_XPCOM_SHUTDOWN:
|
||||
Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
|
||||
Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
|
||||
Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
|
||||
#endif
|
||||
Services.obs.removeObserver(this, TOPIC_INTERFACE_STATE_CHANGED);
|
||||
break;
|
||||
}
|
||||
|
@ -313,15 +329,19 @@ NetworkManager.prototype = {
|
|||
receiveMessage: function receiveMessage(aMsg) {
|
||||
switch (aMsg.name) {
|
||||
case "NetworkInterfaceList:ListInterface": {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
let excludeMms = aMsg.json.exculdeMms;
|
||||
let excludeSupl = aMsg.json.exculdeSupl;
|
||||
#endif
|
||||
let interfaces = [];
|
||||
|
||||
for each (let i in this.networkInterfaces) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if ((i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL && excludeSupl)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
interfaces.push({
|
||||
state: i.state,
|
||||
type: i.type,
|
||||
|
@ -353,12 +373,14 @@ NetworkManager.prototype = {
|
|||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
this.networkInterfaces[network.name] = network;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Add host route for data calls
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
|
||||
this.addHostRoute(network);
|
||||
}
|
||||
#endif
|
||||
// Remove pre-created default route and let setAndConfigureActive()
|
||||
// to set default route only on preferred network
|
||||
this.removeDefaultRoute(network.name);
|
||||
|
@ -377,12 +399,14 @@ NetworkManager.prototype = {
|
|||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
delete this.networkInterfaces[network.name];
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Remove host route for data calls
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
|
||||
this.removeHostRoute(network);
|
||||
}
|
||||
#endif
|
||||
this.setAndConfigureActive();
|
||||
Services.obs.notifyObservers(network, TOPIC_INTERFACE_UNREGISTERED, null);
|
||||
debug("Network '" + network.name + "' unregistered.");
|
||||
|
@ -397,8 +421,12 @@ NetworkManager.prototype = {
|
|||
return this._preferredNetworkType;
|
||||
},
|
||||
set preferredNetworkType(val) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
|
||||
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE].indexOf(val) == -1) {
|
||||
#else
|
||||
if (val != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
#endif
|
||||
throw "Invalid network type";
|
||||
}
|
||||
this._preferredNetworkType = val;
|
||||
|
@ -411,10 +439,12 @@ NetworkManager.prototype = {
|
|||
_activeInfo: null,
|
||||
|
||||
overrideActive: function overrideActive(network) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
|
||||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
|
||||
throw "Invalid network type";
|
||||
}
|
||||
#endif
|
||||
this._overriddenActive = network;
|
||||
this.setAndConfigureActive();
|
||||
},
|
||||
|
@ -486,6 +516,7 @@ NetworkManager.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
setExtraHostRoute: function setExtraHostRoute(network) {
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
|
||||
debug("Network '" + network.name + "' registered, adding mmsproxy and/or mmsc route");
|
||||
|
@ -505,6 +536,7 @@ NetworkManager.prototype = {
|
|||
this.removeHostRouteWithResolve(network, mmsHosts);
|
||||
}
|
||||
},
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
/**
|
||||
* Determine the active interface and configure it.
|
||||
|
@ -512,7 +544,6 @@ NetworkManager.prototype = {
|
|||
setAndConfigureActive: function setAndConfigureActive() {
|
||||
debug("Evaluating whether active network needs to be changed.");
|
||||
let oldActive = this.active;
|
||||
let defaultDataNetwork;
|
||||
|
||||
if (this._overriddenActive) {
|
||||
debug("We have an override for the active network: " +
|
||||
|
@ -538,13 +569,18 @@ NetworkManager.prototype = {
|
|||
// Find a suitable network interface to activate.
|
||||
this.active = null;
|
||||
this._activeInfo = Object.create(null);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
let defaultDataNetwork;
|
||||
#endif
|
||||
for each (let network in this.networkInterfaces) {
|
||||
if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
|
||||
continue;
|
||||
}
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
defaultDataNetwork = network;
|
||||
}
|
||||
#endif
|
||||
this.active = network;
|
||||
this._activeInfo = {name:network.name, ip:network.ip, netmask:network.netmask};
|
||||
if (network.type == this.preferredNetworkType) {
|
||||
|
@ -553,6 +589,7 @@ NetworkManager.prototype = {
|
|||
}
|
||||
}
|
||||
if (this.active) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Give higher priority to default data APN than seconary APN.
|
||||
// If default data APN is not connected, we still set default route
|
||||
// and DNS on seconary APN.
|
||||
|
@ -567,8 +604,11 @@ NetworkManager.prototype = {
|
|||
this.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
|
||||
this.setDNS(this.active);
|
||||
} else {
|
||||
#endif // MOZ_B2G_RIL
|
||||
this.setDefaultRouteAndDNS(oldActive);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
}
|
||||
#endif
|
||||
if (this.active != oldActive) {
|
||||
Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
|
||||
}
|
||||
|
@ -593,6 +633,7 @@ NetworkManager.prototype = {
|
|||
this.worker.postMessage(options);
|
||||
},
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
setDNS: function setDNS(networkInterface) {
|
||||
debug("Going DNS to " + networkInterface.name);
|
||||
let options = {
|
||||
|
@ -603,6 +644,7 @@ NetworkManager.prototype = {
|
|||
};
|
||||
this.worker.postMessage(options);
|
||||
},
|
||||
#endif
|
||||
|
||||
setDefaultRouteAndDNS: function setDefaultRouteAndDNS(oldInterface) {
|
||||
debug("Going to change route and DNS to " + this.active.name);
|
||||
|
@ -627,6 +669,7 @@ NetworkManager.prototype = {
|
|||
this.worker.postMessage(options);
|
||||
},
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
addHostRoute: function addHostRoute(network) {
|
||||
debug("Going to add host route on " + network.name);
|
||||
let options = {
|
||||
|
@ -706,6 +749,7 @@ NetworkManager.prototype = {
|
|||
};
|
||||
this.worker.postMessage(options);
|
||||
},
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
setNetworkProxy: function setNetworkProxy(network) {
|
||||
try {
|
||||
|
@ -1224,9 +1268,11 @@ let CaptivePortalDetectionHelper = (function() {
|
|||
};
|
||||
}());
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
XPCOMUtils.defineLazyServiceGetter(NetworkManager.prototype, "mRIL",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
#endif
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
|
||||
|
||||
|
|
|
@ -82,13 +82,13 @@ const RIL_IPC_MSG_NAMES = [
|
|||
"RIL:StkCommand",
|
||||
"RIL:StkSessionEnd",
|
||||
"RIL:DataError",
|
||||
"RIL:SetCallForwardingOption",
|
||||
"RIL:GetCallForwardingOption",
|
||||
"RIL:SetCallBarringOption",
|
||||
"RIL:GetCallBarringOption",
|
||||
"RIL:SetCallForwardingOptions",
|
||||
"RIL:GetCallForwardingOptions",
|
||||
"RIL:SetCallBarringOptions",
|
||||
"RIL:GetCallBarringOptions",
|
||||
"RIL:ChangeCallBarringPassword",
|
||||
"RIL:SetCallWaitingOption",
|
||||
"RIL:GetCallWaitingOption",
|
||||
"RIL:SetCallWaitingOptions",
|
||||
"RIL:GetCallWaitingOptions",
|
||||
"RIL:SetCallingLineIdRestriction",
|
||||
"RIL:GetCallingLineIdRestriction",
|
||||
"RIL:CellBroadcastReceived",
|
||||
|
@ -380,13 +380,13 @@ CellBroadcastEtwsInfo.prototype = {
|
|||
popup: null
|
||||
};
|
||||
|
||||
function CallBarringOption(option) {
|
||||
this.program = option.program;
|
||||
this.enabled = option.enabled;
|
||||
this.password = option.password;
|
||||
this.serviceClass = option.serviceClass;
|
||||
function CallBarringOptions(options) {
|
||||
this.program = options.program;
|
||||
this.enabled = options.enabled;
|
||||
this.password = options.password;
|
||||
this.serviceClass = options.serviceClass;
|
||||
}
|
||||
CallBarringOption.prototype = {
|
||||
CallBarringOptions.prototype = {
|
||||
__exposedProps__ : {program: 'r',
|
||||
enabled: 'r',
|
||||
password: 'r',
|
||||
|
@ -447,18 +447,30 @@ IccCardLockError.prototype = {
|
|||
function RILContentHelper() {
|
||||
this.updateDebugFlag();
|
||||
|
||||
this.rilContext = {
|
||||
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
|
||||
networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
|
||||
iccInfo: null,
|
||||
voiceConnectionInfo: new MobileConnectionInfo(),
|
||||
dataConnectionInfo: new MobileConnectionInfo()
|
||||
};
|
||||
this.numClients = gNumRadioInterfaces;
|
||||
debug("Number of clients: " + this.numClients);
|
||||
|
||||
this.rilContexts = [];
|
||||
for (let clientId = 0; clientId < this.numClients; clientId++) {
|
||||
this.rilContexts[clientId] = {
|
||||
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
|
||||
networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
|
||||
iccInfo: null,
|
||||
voiceConnectionInfo: new MobileConnectionInfo(),
|
||||
dataConnectionInfo: new MobileConnectionInfo()
|
||||
};
|
||||
}
|
||||
|
||||
this.voicemailInfo = new VoicemailInfo();
|
||||
this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
|
||||
|
||||
this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
|
||||
this._windowsMap = [];
|
||||
this._selectingNetworks = [];
|
||||
this._mobileConnectionListeners = [];
|
||||
this._cellBroadcastListeners = [];
|
||||
this._voicemailListeners = [];
|
||||
this._iccListeners = [];
|
||||
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
|
||||
|
@ -535,88 +547,119 @@ RILContentHelper.prototype = {
|
|||
* 1. Should clear iccInfo to null if there is no card detected.
|
||||
* 2. Need to create corresponding object based on iccType.
|
||||
*/
|
||||
updateIccInfo: function updateIccInfo(newInfo) {
|
||||
updateIccInfo: function updateIccInfo(clientId, newInfo) {
|
||||
let rilContext = this.rilContexts[clientId];
|
||||
|
||||
// Card is not detected, clear iccInfo to null.
|
||||
if (!newInfo || !newInfo.iccType) {
|
||||
this.rilContext.iccInfo = null;
|
||||
if (rilContext.iccInfo) {
|
||||
rilContext.iccInfo = null;
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyIccChanged",
|
||||
null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If iccInfo is null, new corresponding object based on iccType.
|
||||
if (!this.rilContext.iccInfo) {
|
||||
if (!rilContext.iccInfo) {
|
||||
if (newInfo.iccType === "ruim" || newInfo.iccType === "csim") {
|
||||
this.rilContext.iccInfo = new CdmaIccInfo();
|
||||
rilContext.iccInfo = new CdmaIccInfo();
|
||||
} else {
|
||||
this.rilContext.iccInfo = new GsmIccInfo();
|
||||
rilContext.iccInfo = new GsmIccInfo();
|
||||
}
|
||||
}
|
||||
let changed = (rilContext.iccInfo.iccid != newInfo.iccid) ?
|
||||
true : false;
|
||||
|
||||
this.updateInfo(newInfo, this.rilContext.iccInfo);
|
||||
this.updateInfo(newInfo, rilContext.iccInfo);
|
||||
|
||||
// Deliver event after info is updated.
|
||||
if (changed) {
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyIccChanged",
|
||||
null);
|
||||
}
|
||||
},
|
||||
|
||||
_windowsMap: null,
|
||||
|
||||
rilContext: null,
|
||||
rilContexts: null,
|
||||
|
||||
getRilContext: function getRilContext() {
|
||||
// Update ril context by sending IPC message to chrome only when the first
|
||||
getRilContext: function getRilContext(clientId) {
|
||||
// Update ril contexts by sending IPC message to chrome only when the first
|
||||
// time we require it. The information will be updated by following info
|
||||
// changed messages.
|
||||
this.getRilContext = function getRilContext() {
|
||||
return this.rilContext;
|
||||
this.getRilContext = function getRilContext(clientId) {
|
||||
return this.rilContexts[clientId];
|
||||
};
|
||||
|
||||
let rilContext =
|
||||
cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: 0})[0];
|
||||
if (!rilContext) {
|
||||
debug("Received null rilContext from chrome process.");
|
||||
return;
|
||||
for (let cId = 0; cId < this.numClients; cId++) {
|
||||
let rilContext =
|
||||
cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: cId})[0];
|
||||
if (!rilContext) {
|
||||
debug("Received null rilContext from chrome process.");
|
||||
continue;
|
||||
}
|
||||
this.rilContexts[cId].cardState = rilContext.cardState;
|
||||
this.rilContexts[cId].networkSelectionMode = rilContext.networkSelectionMode;
|
||||
this.updateIccInfo(cId, rilContext.iccInfo);
|
||||
this.updateConnectionInfo(rilContext.voice, this.rilContexts[cId].voiceConnectionInfo);
|
||||
this.updateConnectionInfo(rilContext.data, this.rilContexts[cId].dataConnectionInfo);
|
||||
}
|
||||
this.rilContext.cardState = rilContext.cardState;
|
||||
this.rilContext.networkSelectionMode = rilContext.networkSelectionMode;
|
||||
this.updateIccInfo(rilContext.iccInfo);
|
||||
this.updateConnectionInfo(rilContext.voice, this.rilContext.voiceConnectionInfo);
|
||||
this.updateConnectionInfo(rilContext.data, this.rilContext.dataConnectionInfo);
|
||||
|
||||
return this.rilContext;
|
||||
return this.rilContexts[clientId];
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIccProvider
|
||||
*/
|
||||
|
||||
get iccInfo() {
|
||||
//TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
|
||||
let context = this.getRilContext(0);
|
||||
return context && context.iccInfo;
|
||||
},
|
||||
|
||||
get cardState() {
|
||||
//TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
|
||||
let context = this.getRilContext(0);
|
||||
return context && context.cardState;
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIMobileConnectionProvider
|
||||
*/
|
||||
|
||||
get iccInfo() {
|
||||
let context = this.getRilContext();
|
||||
return context && context.iccInfo;
|
||||
},
|
||||
|
||||
get voiceConnectionInfo() {
|
||||
let context = this.getRilContext();
|
||||
getVoiceConnectionInfo: function getVoiceConnectionInfo(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.voiceConnectionInfo;
|
||||
},
|
||||
|
||||
get dataConnectionInfo() {
|
||||
let context = this.getRilContext();
|
||||
getDataConnectionInfo: function getDataConnectionInfo(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.dataConnectionInfo;
|
||||
},
|
||||
|
||||
get cardState() {
|
||||
let context = this.getRilContext();
|
||||
return context && context.cardState;
|
||||
getIccId: function getIccId(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.iccInfo && context.iccInfo.iccid;
|
||||
},
|
||||
|
||||
get networkSelectionMode() {
|
||||
let context = this.getRilContext();
|
||||
getNetworkSelectionMode: function getNetworkSelectionMode(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.networkSelectionMode;
|
||||
},
|
||||
|
||||
/**
|
||||
* The network that is currently trying to be selected (or "automatic").
|
||||
* This helps ensure that only one network is selected at a time.
|
||||
* The networks that are currently trying to be selected (or "automatic").
|
||||
* This helps ensure that only one network per client is selected at a time.
|
||||
*/
|
||||
_selectingNetwork: null,
|
||||
_selectingNetworks: null,
|
||||
|
||||
getNetworks: function getNetworks(window) {
|
||||
getNetworks: function getNetworks(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -626,7 +669,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -634,14 +677,14 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
selectNetwork: function selectNetwork(window, network) {
|
||||
selectNetwork: function selectNetwork(clientId, window, network) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
if (this._selectingNetwork) {
|
||||
throw new Error("Already selecting a network: " + this._selectingNetwork);
|
||||
if (this._selectingNetworks[clientId]) {
|
||||
throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
|
||||
}
|
||||
|
||||
if (!network) {
|
||||
|
@ -659,8 +702,8 @@ RILContentHelper.prototype = {
|
|||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
|
||||
if (this.rilContext.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
|
||||
this.rilContext.voiceConnectionInfo.network === network) {
|
||||
if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
|
||||
this.rilContexts[clientId].voiceConnectionInfo.network === network) {
|
||||
|
||||
// Already manually selected this network, so schedule
|
||||
// onsuccess to be fired on the next tick
|
||||
|
@ -668,10 +711,10 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
}
|
||||
|
||||
this._selectingNetwork = network;
|
||||
this._selectingNetworks[clientId] = network;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SelectNetwork", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
mnc: network.mnc,
|
||||
|
@ -682,30 +725,30 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
selectNetworkAutomatically: function selectNetworkAutomatically(window) {
|
||||
selectNetworkAutomatically: function selectNetworkAutomatically(clientId, window) {
|
||||
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
if (this._selectingNetwork) {
|
||||
throw new Error("Already selecting a network: " + this._selectingNetwork);
|
||||
if (this._selectingNetworks[clientId]) {
|
||||
throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
|
||||
}
|
||||
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
|
||||
if (this.rilContext.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
|
||||
if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
|
||||
// Already using automatic selection mode, so schedule
|
||||
// onsuccess to be be fired on the next tick
|
||||
this.dispatchFireRequestSuccess(requestId, null);
|
||||
return request;
|
||||
}
|
||||
|
||||
this._selectingNetwork = "automatic";
|
||||
this._selectingNetworks[clientId] = "automatic";
|
||||
cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -713,7 +756,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setRoamingPreference: function setRoamingPreference(window, mode) {
|
||||
setRoamingPreference: function setRoamingPreference(clientId, window, mode) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -729,7 +772,7 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetRoamingPreference", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
mode: mode
|
||||
|
@ -738,7 +781,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getRoamingPreference: function getRoamingPreference(window) {
|
||||
getRoamingPreference: function getRoamingPreference(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -748,7 +791,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetRoamingPreference", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -756,7 +799,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setVoicePrivacyMode: function setVoicePrivacyMode(window, enabled) {
|
||||
setVoicePrivacyMode: function setVoicePrivacyMode(clientId, window, enabled) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -766,7 +809,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetVoicePrivacyMode", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
enabled: enabled
|
||||
|
@ -775,7 +818,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getVoicePrivacyMode: function getVoicePrivacyMode(window) {
|
||||
getVoicePrivacyMode: function getVoicePrivacyMode(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -785,7 +828,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetVoicePrivacyMode", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -861,7 +904,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
sendMMI: function sendMMI(window, mmi) {
|
||||
sendMMI: function sendMMI(clientId, window, mmi) {
|
||||
debug("Sending MMI " + mmi);
|
||||
if (!window) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
|
@ -874,7 +917,7 @@ RILContentHelper.prototype = {
|
|||
this._windowsMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SendMMI", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
mmi: mmi,
|
||||
requestId: requestId
|
||||
|
@ -883,7 +926,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
cancelMMI: function cancelMMI(window) {
|
||||
cancelMMI: function cancelMMI(clientId, window) {
|
||||
debug("Cancel MMI");
|
||||
if (!window) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
|
@ -892,7 +935,7 @@ RILContentHelper.prototype = {
|
|||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
cpmm.sendAsyncMessage("RIL:CancelMMI", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -1086,7 +1129,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getCallForwardingOption: function getCallForwardingOption(window, reason) {
|
||||
getCallForwardingOption: function getCallForwardingOption(clientId, window, reason) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1100,8 +1143,8 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCallForwardingOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:GetCallForwardingOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
reason: reason
|
||||
|
@ -1111,7 +1154,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setCallForwardingOption: function setCallForwardingOption(window, cfInfo) {
|
||||
setCallForwardingOption: function setCallForwardingOption(clientId, window, cfInfo) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1127,8 +1170,8 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetCallForwardingOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:SetCallForwardingOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
active: cfInfo.active,
|
||||
|
@ -1142,7 +1185,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getCallBarringOption: function getCallBarringOption(window, option) {
|
||||
getCallBarringOption: function getCallBarringOption(clientId, window, option) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1151,14 +1194,14 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
if (DEBUG) debug("getCallBarringOption: " + JSON.stringify(option));
|
||||
if (!this._isValidCallBarringOption(option)) {
|
||||
if (!this._isValidCallBarringOptions(option)) {
|
||||
this.dispatchFireRequestError(requestId,
|
||||
RIL.GECKO_ERROR_INVALID_PARAMETER);
|
||||
return request;
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCallBarringOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:GetCallBarringOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
program: option.program,
|
||||
|
@ -1169,7 +1212,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setCallBarringOption: function setCallBarringOption(window, option) {
|
||||
setCallBarringOption: function setCallBarringOption(clientId, window, option) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1178,14 +1221,14 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
if (DEBUG) debug("setCallBarringOption: " + JSON.stringify(option));
|
||||
if (!this._isValidCallBarringOption(option, true)) {
|
||||
if (!this._isValidCallBarringOptions(option, true)) {
|
||||
this.dispatchFireRequestError(requestId,
|
||||
RIL.GECKO_ERROR_INVALID_PARAMETER);
|
||||
return request;
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetCallBarringOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:SetCallBarringOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
program: option.program,
|
||||
|
@ -1197,7 +1240,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
changeCallBarringPassword: function changeCallBarringPassword(window, info) {
|
||||
changeCallBarringPassword: function changeCallBarringPassword(clientId, window, info) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1215,14 +1258,14 @@ RILContentHelper.prototype = {
|
|||
if (DEBUG) debug("changeCallBarringPassword: " + JSON.stringify(info));
|
||||
info.requestId = requestId;
|
||||
cpmm.sendAsyncMessage("RIL:ChangeCallBarringPassword", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: info
|
||||
});
|
||||
|
||||
return request;
|
||||
},
|
||||
|
||||
getCallWaitingOption: function getCallWaitingOption(window) {
|
||||
getCallWaitingOption: function getCallWaitingOption(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1230,8 +1273,8 @@ RILContentHelper.prototype = {
|
|||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCallWaitingOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:GetCallWaitingOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -1240,7 +1283,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setCallWaitingOption: function setCallWaitingOption(window, enabled) {
|
||||
setCallWaitingOption: function setCallWaitingOption(clientId, window, enabled) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1248,8 +1291,8 @@ RILContentHelper.prototype = {
|
|||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetCallWaitingOption", {
|
||||
clientId: 0,
|
||||
cpmm.sendAsyncMessage("RIL:SetCallWaitingOptions", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
enabled: enabled
|
||||
|
@ -1259,7 +1302,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getCallingLineIdRestriction: function getCallingLineIdRestriction(window) {
|
||||
getCallingLineIdRestriction: function getCallingLineIdRestriction(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1268,7 +1311,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCallingLineIdRestriction", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
|
@ -1278,7 +1321,7 @@ RILContentHelper.prototype = {
|
|||
},
|
||||
|
||||
setCallingLineIdRestriction:
|
||||
function setCallingLineIdRestriction(window, clirMode) {
|
||||
function setCallingLineIdRestriction(clientId, window, clirMode) {
|
||||
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
|
@ -1288,7 +1331,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetCallingLineIdRestriction", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
clirMode: clirMode
|
||||
|
@ -1298,7 +1341,7 @@ RILContentHelper.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
exitEmergencyCbMode: function exitEmergencyCbMode(window) {
|
||||
exitEmergencyCbMode: function exitEmergencyCbMode(clientId, window) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
@ -1307,7 +1350,7 @@ RILContentHelper.prototype = {
|
|||
let requestId = this.getRequestId(request);
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:ExitEmergencyCbMode", {
|
||||
clientId: 0,
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
}
|
||||
|
@ -1357,10 +1400,13 @@ RILContentHelper.prototype = {
|
|||
return this.getVoicemailInfo().displayName;
|
||||
},
|
||||
|
||||
registerListener: function registerListener(listenerType, listener) {
|
||||
let listeners = this[listenerType];
|
||||
registerListener: function registerListener(listenerType, clientId, listener) {
|
||||
if (!this[listenerType]) {
|
||||
return;
|
||||
}
|
||||
let listeners = this[listenerType][clientId];
|
||||
if (!listeners) {
|
||||
listeners = this[listenerType] = [];
|
||||
listeners = this[listenerType][clientId] = [];
|
||||
}
|
||||
|
||||
if (listeners.indexOf(listener) != -1) {
|
||||
|
@ -1371,8 +1417,11 @@ RILContentHelper.prototype = {
|
|||
if (DEBUG) debug("Registered " + listenerType + " listener: " + listener);
|
||||
},
|
||||
|
||||
unregisterListener: function unregisterListener(listenerType, listener) {
|
||||
let listeners = this[listenerType];
|
||||
unregisterListener: function unregisterListener(listenerType, clientId, listener) {
|
||||
if (!this[listenerType]) {
|
||||
return;
|
||||
}
|
||||
let listeners = this[listenerType][clientId];
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
@ -1384,44 +1433,50 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
registerMobileConnectionMsg: function registerMobileConnectionMsg(listener) {
|
||||
registerMobileConnectionMsg: function registerMobileConnectionMsg(clientId, listener) {
|
||||
debug("Registering for mobile connection related messages");
|
||||
this.registerListener("_mobileConnectionListeners", listener);
|
||||
this.registerListener("_mobileConnectionListeners", clientId, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterMobileConnectionMsg");
|
||||
},
|
||||
|
||||
unregisterMobileConnectionMsg: function unregisteMobileConnectionMsg(listener) {
|
||||
this.unregisterListener("_mobileConnectionListeners", listener);
|
||||
unregisterMobileConnectionMsg: function unregisteMobileConnectionMsg(clientId, listener) {
|
||||
this.unregisterListener("_mobileConnectionListeners", clientId, listener);
|
||||
},
|
||||
|
||||
registerVoicemailMsg: function registerVoicemailMsg(listener) {
|
||||
debug("Registering for voicemail-related messages");
|
||||
this.registerListener("_voicemailListeners", listener);
|
||||
//TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
|
||||
this.registerListener("_voicemailListeners", 0, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
|
||||
},
|
||||
|
||||
unregisterVoicemailMsg: function unregisteVoicemailMsg(listener) {
|
||||
this.unregisterListener("_voicemailListeners", listener);
|
||||
//TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
|
||||
this.unregisterListener("_voicemailListeners", 0, listener);
|
||||
},
|
||||
|
||||
registerCellBroadcastMsg: function registerCellBroadcastMsg(listener) {
|
||||
debug("Registering for Cell Broadcast related messages");
|
||||
this.registerListener("_cellBroadcastListeners", listener);
|
||||
//TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
|
||||
this.registerListener("_cellBroadcastListeners", 0, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterCellBroadcastMsg");
|
||||
},
|
||||
|
||||
unregisterCellBroadcastMsg: function unregisterCellBroadcastMsg(listener) {
|
||||
this.unregisterListener("_cellBroadcastListeners", listener);
|
||||
//TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
|
||||
this.unregisterListener("_cellBroadcastListeners", 0, listener);
|
||||
},
|
||||
|
||||
registerIccMsg: function registerIccMsg(listener) {
|
||||
debug("Registering for ICC related messages");
|
||||
this.registerListener("_iccListeners", listener);
|
||||
//TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
|
||||
this.registerListener("_iccListeners", 0, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
|
||||
},
|
||||
|
||||
unregisterIccMsg: function unregisterIccMsg(listener) {
|
||||
this.unregisterListener("_iccListeners", listener);
|
||||
//TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
|
||||
this.unregisterListener("_iccListeners", 0, listener);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
@ -1511,35 +1566,43 @@ RILContentHelper.prototype = {
|
|||
debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
|
||||
|
||||
let data = msg.json.data;
|
||||
let clientId = msg.json.clientId;
|
||||
switch (msg.name) {
|
||||
case "RIL:CardStateChanged":
|
||||
if (this.rilContext.cardState != data.cardState) {
|
||||
this.rilContext.cardState = data.cardState;
|
||||
this._deliverEvent("_iccListeners",
|
||||
if (this.rilContexts[clientId].cardState != data.cardState) {
|
||||
this.rilContexts[clientId].cardState = data.cardState;
|
||||
this._deliverEvent(clientId,
|
||||
"_iccListeners",
|
||||
"notifyCardStateChanged",
|
||||
null);
|
||||
}
|
||||
break;
|
||||
case "RIL:IccInfoChanged":
|
||||
this.updateIccInfo(data);
|
||||
this._deliverEvent("_iccListeners", "notifyIccInfoChanged", null);
|
||||
this.updateIccInfo(clientId, data);
|
||||
this._deliverEvent(clientId,
|
||||
"_iccListeners",
|
||||
"notifyIccInfoChanged",
|
||||
null);
|
||||
break;
|
||||
case "RIL:VoiceInfoChanged":
|
||||
this.updateConnectionInfo(data,
|
||||
this.rilContext.voiceConnectionInfo);
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this.rilContexts[clientId].voiceConnectionInfo);
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyVoiceChanged",
|
||||
null);
|
||||
break;
|
||||
case "RIL:DataInfoChanged":
|
||||
this.updateConnectionInfo(data,
|
||||
this.rilContext.dataConnectionInfo);
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this.rilContexts[clientId].dataConnectionInfo);
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyDataChanged",
|
||||
null);
|
||||
break;
|
||||
case "RIL:OtaStatusChanged":
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyOtaStatusChanged",
|
||||
[data]);
|
||||
break;
|
||||
|
@ -1547,18 +1610,18 @@ RILContentHelper.prototype = {
|
|||
this.handleGetAvailableNetworks(data);
|
||||
break;
|
||||
case "RIL:NetworkSelectionModeChanged":
|
||||
this.rilContext.networkSelectionMode = data.mode;
|
||||
this.rilContexts[clientId].networkSelectionMode = data.mode;
|
||||
break;
|
||||
case "RIL:SelectNetwork":
|
||||
this.handleSelectNetwork(data,
|
||||
this.handleSelectNetwork(clientId, data,
|
||||
RIL.GECKO_NETWORK_SELECTION_MANUAL);
|
||||
break;
|
||||
case "RIL:SelectNetworkAuto":
|
||||
this.handleSelectNetwork(data,
|
||||
this.handleSelectNetwork(clientId, data,
|
||||
RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
|
||||
break;
|
||||
case "RIL:VoicemailNotification":
|
||||
this.handleVoicemailNotification(data);
|
||||
this.handleVoicemailNotification(clientId, data);
|
||||
break;
|
||||
case "RIL:VoicemailInfoChanged":
|
||||
this.updateInfo(data, this.voicemailInfo);
|
||||
|
@ -1593,7 +1656,8 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
break;
|
||||
case "RIL:USSDReceived":
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyUssdReceived",
|
||||
[data.message, data.sessionEnded]);
|
||||
break;
|
||||
|
@ -1602,11 +1666,11 @@ RILContentHelper.prototype = {
|
|||
this.handleSendCancelMMI(data);
|
||||
break;
|
||||
case "RIL:StkCommand":
|
||||
this._deliverEvent("_iccListeners", "notifyStkCommand",
|
||||
this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
|
||||
[JSON.stringify(data)]);
|
||||
break;
|
||||
case "RIL:StkSessionEnd":
|
||||
this._deliverEvent("_iccListeners", "notifyStkSessionEnd", null);
|
||||
this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
|
||||
break;
|
||||
case "RIL:IccOpenChannel":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg,
|
||||
|
@ -1625,34 +1689,35 @@ RILContentHelper.prototype = {
|
|||
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
|
||||
break;
|
||||
case "RIL:DataError":
|
||||
this.updateConnectionInfo(data, this.rilContext.dataConnectionInfo);
|
||||
this._deliverEvent("_mobileConnectionListeners", "notifyDataError",
|
||||
this.updateConnectionInfo(data, this.rilContexts[clientId].dataConnectionInfo);
|
||||
this._deliverEvent(clientId, "_mobileConnectionListeners", "notifyDataError",
|
||||
[data.errorMsg]);
|
||||
break;
|
||||
case "RIL:GetCallForwardingOption":
|
||||
this.handleGetCallForwardingOption(data);
|
||||
case "RIL:GetCallForwardingOptions":
|
||||
this.handleGetCallForwardingOptions(data);
|
||||
break;
|
||||
case "RIL:SetCallForwardingOption":
|
||||
case "RIL:SetCallForwardingOptions":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
|
||||
break;
|
||||
case "RIL:GetCallBarringOption":
|
||||
this.handleGetCallBarringOption(data);
|
||||
case "RIL:GetCallBarringOptions":
|
||||
this.handleGetCallBarringOptions(data);
|
||||
break;
|
||||
case "RIL:SetCallBarringOption":
|
||||
case "RIL:SetCallBarringOptions":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
|
||||
break;
|
||||
case "RIL:ChangeCallBarringPassword":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
|
||||
break;
|
||||
case "RIL:GetCallWaitingOption":
|
||||
case "RIL:GetCallWaitingOptions":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg,
|
||||
data.enabled);
|
||||
break;
|
||||
case "RIL:SetCallWaitingOption":
|
||||
case "RIL:SetCallWaitingOptions":
|
||||
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
|
||||
break;
|
||||
case "RIL:CfStateChanged":
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyCFStateChange",
|
||||
[data.success, data.action,
|
||||
data.reason, data.number,
|
||||
|
@ -1666,7 +1731,8 @@ RILContentHelper.prototype = {
|
|||
break;
|
||||
case "RIL:CellBroadcastReceived": {
|
||||
let message = new CellBroadcastMessage(data);
|
||||
this._deliverEvent("_cellBroadcastListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_cellBroadcastListeners",
|
||||
"notifyMessageReceived",
|
||||
[message]);
|
||||
break;
|
||||
|
@ -1682,7 +1748,8 @@ RILContentHelper.prototype = {
|
|||
this.handleExitEmergencyCbMode(data);
|
||||
break;
|
||||
case "RIL:EmergencyCbModeChanged":
|
||||
this._deliverEvent("_mobileConnectionListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_mobileConnectionListeners",
|
||||
"notifyEmergencyCbModeChanged",
|
||||
[data.active, data.timeoutMs]);
|
||||
break;
|
||||
|
@ -1723,9 +1790,9 @@ RILContentHelper.prototype = {
|
|||
this.fireRequestSuccess(message.requestId, networks);
|
||||
},
|
||||
|
||||
handleSelectNetwork: function handleSelectNetwork(message, mode) {
|
||||
this._selectingNetwork = null;
|
||||
this.rilContext.networkSelectionMode = mode;
|
||||
handleSelectNetwork: function handleSelectNetwork(clientId, message, mode) {
|
||||
this._selectingNetworks[clientId] = null;
|
||||
this.rilContexts[clientId].networkSelectionMode = mode;
|
||||
|
||||
if (message.errorMsg) {
|
||||
this.fireRequestError(message.requestId, message.errorMsg);
|
||||
|
@ -1773,7 +1840,8 @@ RILContentHelper.prototype = {
|
|||
this.fireRequestSuccess(message.requestId, result);
|
||||
},
|
||||
|
||||
handleVoicemailNotification: function handleVoicemailNotification(message) {
|
||||
handleVoicemailNotification: function handleVoicemailNotification(clientId, message) {
|
||||
// Bug 814634 - WebVoicemail API: support multiple sim cards
|
||||
let changed = false;
|
||||
if (!this.voicemailStatus) {
|
||||
this.voicemailStatus = new VoicemailStatus();
|
||||
|
@ -1803,7 +1871,8 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
this._deliverEvent("_voicemailListeners",
|
||||
this._deliverEvent(clientId,
|
||||
"_voicemailListeners",
|
||||
"notifyStatusChanged",
|
||||
[this.voicemailStatus]);
|
||||
}
|
||||
|
@ -1818,7 +1887,7 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
handleGetCallForwardingOption: function handleGetCallForwardingOption(message) {
|
||||
handleGetCallForwardingOptions: function handleGetCallForwardingOptions(message) {
|
||||
if (message.errorMsg) {
|
||||
this.fireRequestError(message.requestId, message.errorMsg);
|
||||
return;
|
||||
|
@ -1828,12 +1897,12 @@ RILContentHelper.prototype = {
|
|||
this.fireRequestSuccess(message.requestId, message.rules);
|
||||
},
|
||||
|
||||
handleGetCallBarringOption: function handleGetCallBarringOption(message) {
|
||||
handleGetCallBarringOptions: function handleGetCallBarringOptions(message) {
|
||||
if (!message.success) {
|
||||
this.fireRequestError(message.requestId, message.errorMsg);
|
||||
} else {
|
||||
let option = new CallBarringOption(message);
|
||||
this.fireRequestSuccess(message.requestId, option);
|
||||
let options = new CallBarringOptions(message);
|
||||
this.fireRequestSuccess(message.requestId, options);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1909,8 +1978,11 @@ RILContentHelper.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_deliverEvent: function _deliverEvent(listenerType, name, args) {
|
||||
let thisListeners = this[listenerType];
|
||||
_deliverEvent: function _deliverEvent(clientId, listenerType, name, args) {
|
||||
if (!this[listenerType]) {
|
||||
return;
|
||||
}
|
||||
let thisListeners = this[listenerType][clientId];
|
||||
if (!thisListeners) {
|
||||
return;
|
||||
}
|
||||
|
@ -1981,18 +2053,18 @@ RILContentHelper.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Helper for guarding us against invalid option for call barring.
|
||||
* Helper for guarding us against invalid options for call barring.
|
||||
*/
|
||||
_isValidCallBarringOption:
|
||||
function _isValidCallBarringOption(option, usedForSetting) {
|
||||
if (!option ||
|
||||
option.serviceClass == null ||
|
||||
!this._isValidCallBarringProgram(option.program)) {
|
||||
_isValidCallBarringOptions:
|
||||
function _isValidCallBarringOptions(options, usedForSetting) {
|
||||
if (!options ||
|
||||
options.serviceClass == null ||
|
||||
!this._isValidCallBarringProgram(options.program)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For setting callbarring option, |enabled| and |password| are required.
|
||||
if (usedForSetting && (option.enabled == null || option.password == null)) {
|
||||
// For setting callbarring options, |enabled| and |password| are required.
|
||||
if (usedForSetting && (options.enabled == null || options.password == null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,13 +94,13 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
|
|||
"RIL:SendMMI",
|
||||
"RIL:CancelMMI",
|
||||
"RIL:RegisterMobileConnectionMsg",
|
||||
"RIL:SetCallForwardingOption",
|
||||
"RIL:GetCallForwardingOption",
|
||||
"RIL:SetCallBarringOption",
|
||||
"RIL:GetCallBarringOption",
|
||||
"RIL:SetCallForwardingOptions",
|
||||
"RIL:GetCallForwardingOptions",
|
||||
"RIL:SetCallBarringOptions",
|
||||
"RIL:GetCallBarringOptions",
|
||||
"RIL:ChangeCallBarringPassword",
|
||||
"RIL:SetCallWaitingOption",
|
||||
"RIL:GetCallWaitingOption",
|
||||
"RIL:SetCallWaitingOptions",
|
||||
"RIL:GetCallWaitingOptions",
|
||||
"RIL:SetCallingLineIdRestriction",
|
||||
"RIL:GetCallingLineIdRestriction",
|
||||
"RIL:SetRoamingPreference",
|
||||
|
@ -946,25 +946,25 @@ RadioInterface.prototype = {
|
|||
case "RIL:UpdateIccContact":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "updateICCContact");
|
||||
break;
|
||||
case "RIL:SetCallForwardingOption":
|
||||
this.setCallForwardingOption(msg.target, msg.json.data);
|
||||
case "RIL:SetCallForwardingOptions":
|
||||
this.setCallForwardingOptions(msg.target, msg.json.data);
|
||||
break;
|
||||
case "RIL:GetCallForwardingOption":
|
||||
case "RIL:GetCallForwardingOptions":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "queryCallForwardStatus");
|
||||
break;
|
||||
case "RIL:SetCallBarringOption":
|
||||
case "RIL:SetCallBarringOptions":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "setCallBarring");
|
||||
break;
|
||||
case "RIL:GetCallBarringOption":
|
||||
case "RIL:GetCallBarringOptions":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "queryCallBarringStatus");
|
||||
break;
|
||||
case "RIL:ChangeCallBarringPassword":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "changeCallBarringPassword");
|
||||
break;
|
||||
case "RIL:SetCallWaitingOption":
|
||||
case "RIL:SetCallWaitingOptions":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "setCallWaiting");
|
||||
break;
|
||||
case "RIL:GetCallWaitingOption":
|
||||
case "RIL:GetCallWaitingOptions":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "queryCallWaiting");
|
||||
break;
|
||||
case "RIL:SetCallingLineIdRestriction":
|
||||
|
@ -2200,13 +2200,28 @@ RadioInterface.prototype = {
|
|||
break;
|
||||
case kNetworkInterfaceStateChangedTopic:
|
||||
let network = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
|
||||
// Check SNTP when we have data connection, this may not take
|
||||
// effect immediately before the setting get enabled.
|
||||
if (this._sntp.isExpired()) {
|
||||
this._sntp.request();
|
||||
if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// SNTP can only update when we have mobile or Wifi connections.
|
||||
if (network.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
|
||||
network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the network comes from RIL, make sure the RIL service is matched.
|
||||
if (subject instanceof Ci.nsIRilNetworkInterface) {
|
||||
network = subject.QueryInterface(Ci.nsIRilNetworkInterface);
|
||||
if (network.serviceId != this.clientId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// SNTP won't update unless the SNTP is already expired.
|
||||
if (this._sntp.isExpired()) {
|
||||
this._sntp.request();
|
||||
}
|
||||
break;
|
||||
case kScreenStateChangedTopic:
|
||||
this.workerMessenger.send("setScreenState", { on: (data === "on") });
|
||||
|
@ -2418,12 +2433,12 @@ RadioInterface.prototype = {
|
|||
}).bind(this));
|
||||
},
|
||||
|
||||
setCallForwardingOption: function setCallForwardingOption(target, message) {
|
||||
if (DEBUG) this.debug("setCallForwardingOption: " + JSON.stringify(message));
|
||||
setCallForwardingOptions: function setCallForwardingOptions(target, message) {
|
||||
if (DEBUG) this.debug("setCallForwardingOptions: " + JSON.stringify(message));
|
||||
message.serviceClass = RIL.ICC_SERVICE_CLASS_VOICE;
|
||||
this.workerMessenger.send("setCallForward", message, (function(response) {
|
||||
this._sendCfStateChanged(response);
|
||||
target.sendAsyncMessage("RIL:SetCallForwardingOption", {
|
||||
target.sendAsyncMessage("RIL:SetCallForwardingOptions", {
|
||||
clientId: this.clientId,
|
||||
data: response
|
||||
});
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "mozilla/ipc/Netd.h"
|
||||
#include "AutoMounter.h"
|
||||
#include "TimeZoneSettingObserver.h"
|
||||
#include "AudioManager.h"
|
||||
#endif
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
#endif
|
||||
#include "mozilla/ipc/KeyStore.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsCxPusher.h"
|
||||
|
@ -44,9 +44,7 @@ USING_WORKERS_NAMESPACE
|
|||
|
||||
using namespace mozilla::dom::gonk;
|
||||
using namespace mozilla::ipc;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
using namespace mozilla::system;
|
||||
#endif
|
||||
|
||||
#define NS_NETWORKMANAGER_CID \
|
||||
{ 0x33901e46, 0x33b8, 0x11e1, \
|
||||
|
@ -60,107 +58,6 @@ NS_DEFINE_CID(kNetworkManagerCID, NS_NETWORKMANAGER_CID);
|
|||
// Doesn't carry a reference, we're owned by services.
|
||||
SystemWorkerManager *gInstance = nullptr;
|
||||
|
||||
class ConnectWorkerToRIL : public WorkerTask
|
||||
{
|
||||
public:
|
||||
ConnectWorkerToRIL()
|
||||
{ }
|
||||
|
||||
virtual bool RunTask(JSContext *aCx);
|
||||
};
|
||||
|
||||
class SendRilSocketDataTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SendRilSocketDataTask(unsigned long aClientId,
|
||||
UnixSocketRawData *aRawData)
|
||||
: mRawData(aRawData)
|
||||
, mClientId(aClientId)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
SystemWorkerManager::SendRilRawData(mClientId, mRawData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
UnixSocketRawData *mRawData;
|
||||
unsigned long mClientId;
|
||||
};
|
||||
|
||||
bool
|
||||
PostToRIL(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
|
||||
|
||||
if (argc != 2) {
|
||||
JS_ReportError(cx, "Expecting two arguments with the RIL message");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Value cv = JS_ARGV(cx, vp)[0];
|
||||
int clientId = cv.toInt32();
|
||||
|
||||
JS::Value v = JS_ARGV(cx, vp)[1];
|
||||
|
||||
JSAutoByteString abs;
|
||||
void *data;
|
||||
size_t size;
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
JSString *str = JSVAL_TO_STRING(v);
|
||||
if (!abs.encodeUtf8(cx, str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data = abs.ptr();
|
||||
size = abs.length();
|
||||
} else if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_IsTypedArrayObject(obj)) {
|
||||
JS_ReportError(cx, "Object passed in wasn't a typed array");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t type = JS_GetArrayBufferViewType(obj);
|
||||
if (type != js::ArrayBufferView::TYPE_INT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
|
||||
JS_ReportError(cx, "Typed array data is not octets");
|
||||
return false;
|
||||
}
|
||||
|
||||
size = JS_GetTypedArrayByteLength(obj);
|
||||
data = JS_GetArrayBufferViewData(obj);
|
||||
} else {
|
||||
JS_ReportError(cx,
|
||||
"Incorrect argument. Expecting a string or a typed array");
|
||||
return false;
|
||||
}
|
||||
|
||||
UnixSocketRawData* raw = new UnixSocketRawData(data, size);
|
||||
|
||||
nsRefPtr<SendRilSocketDataTask> task = new SendRilSocketDataTask(clientId, raw);
|
||||
NS_DispatchToMainThread(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ConnectWorkerToRIL::RunTask(JSContext *aCx)
|
||||
{
|
||||
// Set up the postRILMessage on the function for worker -> RIL thread
|
||||
// communication.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
|
||||
NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
|
||||
JSObject *workerGlobal = JS::CurrentGlobalOrNull(aCx);
|
||||
|
||||
return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage", PostToRIL, 1,
|
||||
0);
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
|
||||
bool
|
||||
DoNetdCommand(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
|
@ -306,8 +203,6 @@ NetdReceiver::DispatchNetdEvent::RunTask(JSContext *aCx)
|
|||
argv, argv);
|
||||
}
|
||||
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
SystemWorkerManager::SystemWorkerManager()
|
||||
|
@ -345,14 +240,12 @@ SystemWorkerManager::Init()
|
|||
|
||||
InitKeyStore(cx);
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
InitAutoMounter();
|
||||
InitializeTimeZoneSettingObserver();
|
||||
rv = InitNetd(cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIAudioManager> audioManager =
|
||||
do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
|
@ -376,21 +269,14 @@ SystemWorkerManager::Shutdown()
|
|||
|
||||
mShutdown = true;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
ShutdownAutoMounter();
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
RilConsumer::Shutdown();
|
||||
#endif
|
||||
|
||||
for (unsigned long i = 0; i < mRilConsumers.Length(); i++) {
|
||||
if (mRilConsumers[i]) {
|
||||
mRilConsumers[i]->Shutdown();
|
||||
mRilConsumers[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
StopNetd();
|
||||
mNetdWorker = nullptr;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
|
||||
if (wifi) {
|
||||
|
@ -433,20 +319,6 @@ SystemWorkerManager::GetInterfaceRequestor()
|
|||
return gInstance;
|
||||
}
|
||||
|
||||
bool
|
||||
SystemWorkerManager::SendRilRawData(unsigned long aClientId,
|
||||
UnixSocketRawData* aRaw)
|
||||
{
|
||||
if ((gInstance->mRilConsumers.Length() <= aClientId) ||
|
||||
!gInstance->mRilConsumers[aClientId] ||
|
||||
gInstance->mRilConsumers[aClientId]->GetConnectionStatus() != SOCKET_CONNECTED) {
|
||||
// Probably shuting down.
|
||||
delete aRaw;
|
||||
return true;
|
||||
}
|
||||
return gInstance->mRilConsumers[aClientId]->SendSocketData(aRaw);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
|
||||
{
|
||||
|
@ -457,12 +329,10 @@ SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
|
|||
reinterpret_cast<nsIWifi**>(aResult));
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (aIID.Equals(NS_GET_IID(nsINetworkManager))) {
|
||||
return CallQueryInterface(mNetdWorker,
|
||||
reinterpret_cast<nsINetworkManager**>(aResult));
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_WARNING("Got nothing for the requested IID!");
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
@ -473,15 +343,11 @@ SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
|
|||
const JS::Value& aWorker,
|
||||
JSContext *aCx)
|
||||
{
|
||||
#ifndef MOZ_B2G_RIL
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aWorker), NS_ERROR_UNEXPECTED);
|
||||
|
||||
mRilConsumers.EnsureLengthAtLeast(aClientId + 1);
|
||||
|
||||
if (mRilConsumers[aClientId]) {
|
||||
NS_WARNING("RilConsumer already registered");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(aCx, JSVAL_TO_OBJECT(aWorker));
|
||||
|
||||
WorkerCrossThreadDispatcher *wctd =
|
||||
|
@ -491,18 +357,10 @@ SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
|
||||
if (!wctd->PostTask(connection)) {
|
||||
NS_WARNING("Failed to connect worker to ril");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Now that we're set up, connect ourselves to the RIL thread.
|
||||
mRilConsumers[aClientId] = new RilConsumer(aClientId, wctd);
|
||||
return NS_OK;
|
||||
return RilConsumer::Register(aClientId, wctd);
|
||||
#endif // MOZ_B2G_RIL
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult
|
||||
SystemWorkerManager::InitNetd(JSContext *cx)
|
||||
{
|
||||
|
@ -535,7 +393,6 @@ SystemWorkerManager::InitNetd(JSContext *cx)
|
|||
mNetdWorker = worker;
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
SystemWorkerManager::InitWifi(JSContext *cx)
|
||||
|
|
|
@ -23,18 +23,13 @@
|
|||
#include "nsIObserver.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h" // For XRE_GetProcessType
|
||||
|
||||
class nsIWorkerHolder;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class RilConsumer;
|
||||
class UnixSocketRawData;
|
||||
class KeyStore;
|
||||
}
|
||||
|
||||
|
@ -60,25 +55,17 @@ public:
|
|||
static nsIInterfaceRequestor*
|
||||
GetInterfaceRequestor();
|
||||
|
||||
static bool SendRilRawData(unsigned long aClientId,
|
||||
ipc::UnixSocketRawData* aRaw);
|
||||
|
||||
private:
|
||||
SystemWorkerManager();
|
||||
~SystemWorkerManager();
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult InitNetd(JSContext *cx);
|
||||
#endif
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
nsresult InitKeyStore(JSContext *cx);
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsIWorkerHolder> mNetdWorker;
|
||||
#endif
|
||||
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
|
||||
|
||||
nsTArray<nsRefPtr<ipc::RilConsumer> > mRilConsumers;
|
||||
nsRefPtr<ipc::KeyStore> mKeyStore;
|
||||
|
||||
bool mShutdown;
|
||||
|
|
|
@ -18,7 +18,6 @@ XPIDL_SOURCES += [
|
|||
'nsIAudioManager.idl',
|
||||
'nsINetworkInterfaceListService.idl',
|
||||
'nsINetworkManager.idl',
|
||||
'nsIRadioInterfaceLayer.idl',
|
||||
'nsISystemWorkerManager.idl',
|
||||
'nsIVolume.idl',
|
||||
'nsIVolumeMountLock.idl',
|
||||
|
@ -31,55 +30,61 @@ XPIDL_MODULE = 'dom_system_gonk'
|
|||
|
||||
MODULE = 'dom'
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
EXPORTS += [
|
||||
'GonkGPSGeolocationProvider.h',
|
||||
'nsVolume.h',
|
||||
'nsVolumeService.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'AudioChannelManager.cpp',
|
||||
'AudioManager.cpp',
|
||||
'AutoMounter.cpp',
|
||||
'AutoMounterSetting.cpp',
|
||||
'GonkGPSGeolocationProvider.cpp',
|
||||
'nsVolume.cpp',
|
||||
'nsVolumeMountLock.cpp',
|
||||
'nsVolumeService.cpp',
|
||||
'nsVolumeStat.cpp',
|
||||
'OpenFileFinder.cpp',
|
||||
'TimeZoneSettingObserver.cpp',
|
||||
'Volume.cpp',
|
||||
'VolumeCommand.cpp',
|
||||
'VolumeManager.cpp',
|
||||
'VolumeServiceIOThread.cpp',
|
||||
'VolumeServiceTest.cpp',
|
||||
]
|
||||
EXPORTS += [
|
||||
'GonkGPSGeolocationProvider.h',
|
||||
'nsVolume.h',
|
||||
'nsVolumeService.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'AudioChannelManager.cpp',
|
||||
'AudioManager.cpp',
|
||||
'AutoMounter.cpp',
|
||||
'AutoMounterSetting.cpp',
|
||||
'GonkGPSGeolocationProvider.cpp',
|
||||
'nsVolume.cpp',
|
||||
'nsVolumeMountLock.cpp',
|
||||
'nsVolumeService.cpp',
|
||||
'nsVolumeStat.cpp',
|
||||
'OpenFileFinder.cpp',
|
||||
'SystemWorkerManager.cpp',
|
||||
'TimeZoneSettingObserver.cpp',
|
||||
'Volume.cpp',
|
||||
'VolumeCommand.cpp',
|
||||
'VolumeManager.cpp',
|
||||
'VolumeServiceIOThread.cpp',
|
||||
'VolumeServiceTest.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
|
||||
|
||||
SOURCES += [
|
||||
'SystemWorkerManager.cpp',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'NetworkInterfaceListService.js',
|
||||
'NetworkInterfaceListService.manifest',
|
||||
'NetworkManager.js',
|
||||
'NetworkManager.manifest',
|
||||
'RadioInterfaceLayer.js',
|
||||
'RadioInterfaceLayer.manifest',
|
||||
'RILContentHelper.js',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'NetworkManager.js',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'net_worker.js',
|
||||
'ril_consts.js',
|
||||
'ril_worker.js',
|
||||
'systemlibs.js',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIRadioInterfaceLayer.idl',
|
||||
]
|
||||
EXTRA_COMPONENTS += [
|
||||
'RadioInterfaceLayer.js',
|
||||
'RadioInterfaceLayer.manifest',
|
||||
'RILContentHelper.js',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'ril_consts.js',
|
||||
'ril_worker.js',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
|
|
@ -14,8 +14,7 @@ elif toolkit == 'cocoa':
|
|||
DIRS += ['mac']
|
||||
elif toolkit == 'android':
|
||||
DIRS += ['android']
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
elif toolkit == 'gonk':
|
||||
DIRS += ['gonk']
|
||||
|
||||
TEST_DIRS += ['tests']
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/telephony/TelephonyFactory.h"
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
#include "nsIGonkTelephonyProvider.h"
|
||||
#endif
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
@ -20,7 +20,7 @@ TelephonyFactory::CreateTelephonyProvider()
|
|||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
provider = new TelephonyIPCProvider();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
} else {
|
||||
provider = do_CreateInstance(GONK_TELEPHONY_PROVIDER_CONTRACTID);
|
||||
#endif
|
||||
|
|
|
@ -45,7 +45,7 @@ IPDL_SOURCES += [
|
|||
'ipc/TelephonyTypes.ipdlh'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIGonkTelephonyProvider.idl',
|
||||
]
|
||||
|
|
|
@ -5,3 +5,4 @@ support-files =
|
|||
|
||||
[test_notification_basics.html]
|
||||
[test_notification_storage.html]
|
||||
[test_bug931307.html]
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 931307</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
new Notification("");
|
||||
var promise = Notification.get();
|
||||
promise.then(
|
||||
function onSuccess() {
|
||||
ok(true, "No crash!");
|
||||
SimpleTest.finish();
|
||||
},
|
||||
function onFailure() {
|
||||
ok(false, "Should not get an error in promise callback");
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -5,5 +5,5 @@
|
|||
|
||||
PARALLEL_DIRS += ['interfaces', 'src']
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL'] and CONFIG['ENABLE_TESTS']:
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# 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/.
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
EXTRA_JS_MODULES = [
|
||||
'gonk/CpPduHelper.jsm',
|
||||
'gonk/SiPduHelper.jsm',
|
||||
|
|
|
@ -136,6 +136,22 @@ interface CameraControl {
|
|||
attribute CameraRecorderStateChange? onRecorderStateChange;
|
||||
attribute CameraPreviewStateChange? onPreviewStateChange;
|
||||
|
||||
/* the size of the picture to be returned by a call to takePicture();
|
||||
an object with 'height' and 'width' properties that corresponds to
|
||||
one of the options returned by capabilities.pictureSizes. */
|
||||
[Throws]
|
||||
attribute any pictureSize;
|
||||
|
||||
/* the size of the thumbnail to be included in the picture returned
|
||||
by a call to takePicture(), assuming the chose fileFormat supports
|
||||
one; an object with 'height' and 'width' properties that corresponds
|
||||
to one of the options returned by capabilities.pictureSizes.
|
||||
|
||||
this setting should be considered a hint: the implementation will
|
||||
respect it when possible, and override it if necessary. */
|
||||
[Throws]
|
||||
attribute any thumbnailSize;
|
||||
|
||||
/* tell the camera to attempt to focus the image */
|
||||
[Throws]
|
||||
void autoFocus(CameraAutoFocusCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
[ChromeOnly, Constructor, JSImplementation="@mozilla.org/contactAddress;1"]
|
||||
interface ContactAddress {
|
||||
attribute object? type; // DOMString[]
|
||||
attribute DOMString? streetAddress;
|
||||
attribute DOMString? locality;
|
||||
attribute DOMString? region;
|
||||
attribute DOMString? postalCode;
|
||||
attribute DOMString? countryName;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? streetAddress;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? locality;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? region;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? postalCode;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? countryName;
|
||||
attribute boolean? pref;
|
||||
|
||||
[ChromeOnly]
|
||||
|
@ -26,19 +26,19 @@ interface ContactAddress {
|
|||
|
||||
dictionary ContactAddressInit {
|
||||
sequence<DOMString>? type;
|
||||
DOMString? streetAddress;
|
||||
DOMString? locality;
|
||||
DOMString? region;
|
||||
DOMString? postalCode;
|
||||
DOMString? countryName;
|
||||
boolean? pref;
|
||||
DOMString? streetAddress;
|
||||
DOMString? locality;
|
||||
DOMString? region;
|
||||
DOMString? postalCode;
|
||||
DOMString? countryName;
|
||||
boolean? pref;
|
||||
};
|
||||
|
||||
|
||||
[ChromeOnly, Constructor, JSImplementation="@mozilla.org/contactField;1"]
|
||||
interface ContactField {
|
||||
attribute object? type; // DOMString[]
|
||||
attribute DOMString? value;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? value;
|
||||
attribute boolean? pref;
|
||||
|
||||
[ChromeOnly]
|
||||
|
@ -56,7 +56,7 @@ dictionary ContactFieldInit {
|
|||
|
||||
[ChromeOnly, Constructor, JSImplementation="@mozilla.org/contactTelField;1"]
|
||||
interface ContactTelField : ContactField {
|
||||
attribute DOMString? carrier;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? carrier;
|
||||
|
||||
[ChromeOnly]
|
||||
void initialize(optional sequence<DOMString>? type,
|
||||
|
@ -111,8 +111,8 @@ interface mozContact {
|
|||
attribute Date? bday;
|
||||
attribute Date? anniversary;
|
||||
|
||||
attribute DOMString? sex;
|
||||
attribute DOMString? genderIdentity;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? sex;
|
||||
[TreatUndefinedAs=Null] attribute DOMString? genderIdentity;
|
||||
|
||||
attribute object? photo;
|
||||
|
||||
|
|
|
@ -255,11 +255,6 @@ partial interface Navigator {
|
|||
};
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
partial interface Navigator {
|
||||
[Throws, Func="Navigator::HasTelephonySupport"]
|
||||
readonly attribute Telephony? mozTelephony;
|
||||
};
|
||||
|
||||
// nsIMozNavigatorMobileConnection
|
||||
interface MozMobileConnection;
|
||||
partial interface Navigator {
|
||||
|
@ -285,6 +280,11 @@ partial interface Navigator {
|
|||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
partial interface Navigator {
|
||||
[Throws, Func="Navigator::HasTelephonySupport"]
|
||||
readonly attribute Telephony? mozTelephony;
|
||||
};
|
||||
|
||||
#ifdef MOZ_GAMEPAD
|
||||
// https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
|
||||
partial interface Navigator {
|
||||
|
|
|
@ -470,12 +470,6 @@ if CONFIG['MOZ_GAMEPAD']:
|
|||
'Gamepad.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
WEBIDL_FILES += [
|
||||
'MozStkCommandEvent.webidl',
|
||||
'MozVoicemail.webidl',
|
||||
]
|
||||
|
||||
WEBIDL_FILES += [
|
||||
'CloseEvent.webidl',
|
||||
'CustomEvent.webidl',
|
||||
|
@ -518,10 +512,16 @@ if CONFIG['MOZ_B2G_RIL']:
|
|||
'MozCellBroadcastEvent.webidl',
|
||||
'MozEmergencyCbModeEvent.webidl',
|
||||
'MozOtaStatusEvent.webidl',
|
||||
'MozStkCommandEvent.webidl',
|
||||
'MozVoicemail.webidl',
|
||||
'MozVoicemailEvent.webidl',
|
||||
'USSDReceivedEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
WEBIDL_FILES += [
|
||||
'MozWifiConnectionInfoEvent.webidl',
|
||||
'MozWifiStatusChangeEvent.webidl',
|
||||
'USSDReceivedEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH']:
|
||||
|
|
|
@ -104,6 +104,12 @@ SharedSurface_Gralloc::Create(GLContext* prodGL,
|
|||
GLuint prodTex = 0;
|
||||
prodGL->fGenTextures(1, &prodTex);
|
||||
ScopedBindTexture autoTex(prodGL, prodTex);
|
||||
|
||||
prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
|
||||
|
||||
egl->fDestroyImage(display, image);
|
||||
|
|
|
@ -467,24 +467,6 @@ APZCTreeManager::UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->CancelDefaultPanZoom();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::DetectScrollableSubframe(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->DetectScrollableSubframe();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
|
||||
const CSSRect& aRect)
|
||||
|
|
|
@ -181,22 +181,6 @@ public:
|
|||
void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
||||
const ScreenIntRect& aCompositionBounds);
|
||||
|
||||
/**
|
||||
* We are scrolling a subframe, so disable our machinery until we hit
|
||||
* a touch end or a new touch start. This prevents us from accidentally
|
||||
* panning both the subframe and the parent frame.
|
||||
*
|
||||
* XXX/bug 775452: We should eventually be supporting async scrollable
|
||||
* subframes.
|
||||
*/
|
||||
void CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid);
|
||||
|
||||
/**
|
||||
* We have found a scrollable subframe, so we need to delay the scrolling
|
||||
* gesture executed and let subframe do the scrolling first.
|
||||
*/
|
||||
void DetectScrollableSubframe(const ScrollableLayerGuid& aGuid);
|
||||
|
||||
/**
|
||||
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
||||
* in. The actual animation is done on the compositor thread after being set
|
||||
|
|
|
@ -279,9 +279,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
|||
mLastAsyncScrollOffset(0, 0),
|
||||
mCurrentAsyncScrollOffset(0, 0),
|
||||
mAsyncScrollTimeoutTask(nullptr),
|
||||
mDisableNextTouchBatch(false),
|
||||
mHandlingTouchQueue(false),
|
||||
mDelayPanning(false),
|
||||
mTreeManager(aTreeManager)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||
|
@ -395,29 +393,12 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
|
|||
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||
|
||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener && !mDisableNextTouchBatch) {
|
||||
if (listener) {
|
||||
rv = listener->HandleInputEvent(aEvent);
|
||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mDelayPanning && aEvent.mInputType == MULTITOUCH_INPUT) {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_MOVE) {
|
||||
// Let BrowserElementScrolling perform panning gesture first.
|
||||
SetState(WAITING_LISTENERS);
|
||||
mTouchQueue.AppendElement(multiTouchInput);
|
||||
|
||||
if (!mTouchListenerTimeoutTask) {
|
||||
mTouchListenerTimeoutTask =
|
||||
NewRunnableMethod(this, &AsyncPanZoomController::TimeoutTouchListeners);
|
||||
|
||||
PostDelayedTask(mTouchListenerTimeoutTask, gTouchListenerTimeout);
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
switch (aEvent.mInputType) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
|
@ -503,10 +484,6 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) {
|
||||
APZC_LOG("%p got a touch-move in state %d\n", this, mState);
|
||||
if (mDisableNextTouchBatch) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case FLING:
|
||||
case NOTHING:
|
||||
|
@ -553,11 +530,6 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
|
||||
APZC_LOG("%p got a touch-end in state %d\n", this, mState);
|
||||
if (mDisableNextTouchBatch) {
|
||||
mDisableNextTouchBatch = false;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
SendAsyncScrollEvent();
|
||||
|
@ -1364,18 +1336,6 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo
|
|||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
||||
mDisableNextTouchBatch = true;
|
||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
listener->CancelGesture();
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::DetectScrollableSubframe() {
|
||||
mDelayPanning = true;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
||||
SetState(ANIMATING_ZOOM);
|
||||
|
||||
|
@ -1455,7 +1415,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
|||
}
|
||||
|
||||
void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
||||
if (!mFrameMetrics.mMayHaveTouchListeners && !mDelayPanning) {
|
||||
if (!mFrameMetrics.mMayHaveTouchListeners) {
|
||||
mTouchQueue.Clear();
|
||||
return;
|
||||
}
|
||||
|
@ -1467,21 +1427,12 @@ void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
|||
|
||||
if (mState == WAITING_LISTENERS) {
|
||||
if (!aPreventDefault) {
|
||||
// Delayed scrolling gesture is pending at TOUCHING state.
|
||||
if (mDelayPanning) {
|
||||
SetState(TOUCHING);
|
||||
} else {
|
||||
SetState(NOTHING);
|
||||
}
|
||||
SetState(NOTHING);
|
||||
}
|
||||
|
||||
mHandlingTouchQueue = true;
|
||||
|
||||
while (!mTouchQueue.IsEmpty()) {
|
||||
// we need to reset mDelayPanning before handling scrolling gesture.
|
||||
if (!aPreventDefault && mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_MOVE) {
|
||||
mDelayPanning = false;
|
||||
}
|
||||
if (!aPreventDefault) {
|
||||
HandleInputEvent(mTouchQueue[0]);
|
||||
}
|
||||
|
|
|
@ -111,22 +111,6 @@ public:
|
|||
*/
|
||||
void UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds);
|
||||
|
||||
/**
|
||||
* We are scrolling a subframe, so disable our machinery until we hit
|
||||
* a touch end or a new touch start. This prevents us from accidentally
|
||||
* panning both the subframe and the parent frame.
|
||||
*
|
||||
* XXX/bug 775452: We should eventually be supporting async scrollable
|
||||
* subframes.
|
||||
*/
|
||||
void CancelDefaultPanZoom();
|
||||
|
||||
/**
|
||||
* We have found a scrollable subframe, so we need to delay the scrolling
|
||||
* gesture executed and let subframe do the scrolling first.
|
||||
*/
|
||||
void DetectScrollableSubframe();
|
||||
|
||||
/**
|
||||
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
||||
* in. The actual animation is done on the compositor thread after being set
|
||||
|
@ -615,22 +599,12 @@ private:
|
|||
// ensures the last mozbrowserasyncscroll event is always been fired.
|
||||
CancelableTask* mAsyncScrollTimeoutTask;
|
||||
|
||||
// Flag used to determine whether or not we should disable handling of the
|
||||
// next batch of touch events. This is used for sync scrolling of subframes.
|
||||
bool mDisableNextTouchBatch;
|
||||
|
||||
// Flag used to determine whether or not we should try to enter the
|
||||
// WAITING_LISTENERS state. This is used in the case that we are processing a
|
||||
// queued up event block. If set, this means that we are handling this queue
|
||||
// and we don't want to queue the events back up again.
|
||||
bool mHandlingTouchQueue;
|
||||
|
||||
// Flag used to determine whether or not we should try scrolling by
|
||||
// BrowserElementScrolling first. If set, we delay delivering
|
||||
// touchmove events to GestureListener until BrowserElementScrolling
|
||||
// decides whether it wants to handle panning for this touch series.
|
||||
bool mDelayPanning;
|
||||
|
||||
friend class Axis;
|
||||
|
||||
/* The functions and members in this section are used to build a tree
|
||||
|
|
|
@ -226,7 +226,7 @@ DBusWatcher::Poll()
|
|||
if (mPollData[i].fd == mControlFdR.get()) {
|
||||
char data;
|
||||
res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &data, sizeof(data)));
|
||||
NS_ENSURE_TRUE(res > 0, NS_OK);
|
||||
NS_ENSURE_TRUE(res > 0, false);
|
||||
|
||||
switch (data) {
|
||||
case DBUS_EVENT_LOOP_EXIT:
|
||||
|
@ -253,18 +253,19 @@ DBusWatcher::Poll()
|
|||
}
|
||||
} else {
|
||||
short events = mPollData[i].revents;
|
||||
unsigned int flags = UnixEventsToDBusFlags(events);
|
||||
dbus_watch_handle(mWatchData[i], flags);
|
||||
mPollData[i].revents = 0;
|
||||
|
||||
dbus_watch_handle(mWatchData[i], UnixEventsToDBusFlags(events));
|
||||
|
||||
DBusDispatchStatus dbusDispatchStatus;
|
||||
do {
|
||||
dbusDispatchStatus = dbus_connection_dispatch(GetConnection());
|
||||
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
|
||||
|
||||
// Break at this point since we don't know if the operation
|
||||
// was destructive
|
||||
break;
|
||||
}
|
||||
|
||||
DBusDispatchStatus dbusDispatchStatus;
|
||||
do {
|
||||
dbusDispatchStatus = dbus_connection_dispatch(GetConnection());
|
||||
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
|
||||
}
|
||||
|
||||
++i;
|
||||
|
|
|
@ -53,59 +53,16 @@ protected:
|
|||
DBusMessageRefPtr mMessage;
|
||||
};
|
||||
|
||||
class DBusConnectionSendSyncRunnable : public DBusConnectionSendRunnableBase
|
||||
{
|
||||
public:
|
||||
bool WaitForCompletion()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
MonitorAutoLock autoLock(mCompletedMonitor);
|
||||
while (!mCompleted) {
|
||||
mCompletedMonitor.Wait();
|
||||
}
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
protected:
|
||||
DBusConnectionSendSyncRunnable(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage)
|
||||
: DBusConnectionSendRunnableBase(aConnection, aMessage),
|
||||
mCompletedMonitor("DBusConnectionSendSyncRunnable.mCompleted"),
|
||||
mCompleted(false),
|
||||
mSuccess(false)
|
||||
{ }
|
||||
|
||||
virtual ~DBusConnectionSendSyncRunnable()
|
||||
{ }
|
||||
|
||||
// Call this function at the end of Run() to notify waiting
|
||||
// threads.
|
||||
void Completed(bool aSuccess)
|
||||
{
|
||||
MonitorAutoLock autoLock(mCompletedMonitor);
|
||||
MOZ_ASSERT(!mCompleted);
|
||||
mSuccess = aSuccess;
|
||||
mCompleted = true;
|
||||
mCompletedMonitor.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
Monitor mCompletedMonitor;
|
||||
bool mCompleted;
|
||||
bool mSuccess;
|
||||
};
|
||||
|
||||
//
|
||||
// Sends a message and returns the message's serial number to the
|
||||
// disaptching thread. Only run it in DBus thread.
|
||||
//
|
||||
class DBusConnectionSendRunnable : public DBusConnectionSendSyncRunnable
|
||||
class DBusConnectionSendRunnable : public DBusConnectionSendRunnableBase
|
||||
{
|
||||
public:
|
||||
DBusConnectionSendRunnable(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage)
|
||||
: DBusConnectionSendSyncRunnable(aConnection, aMessage)
|
||||
: DBusConnectionSendRunnableBase(aConnection, aMessage)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
|
@ -113,7 +70,6 @@ public:
|
|||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
dbus_bool_t success = dbus_connection_send(mConnection, mMessage, nullptr);
|
||||
Completed(success == TRUE);
|
||||
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -220,95 +176,6 @@ private:
|
|||
int mTimeout;
|
||||
};
|
||||
|
||||
//
|
||||
// Legacy interface, don't use in new code
|
||||
//
|
||||
// Sends a message and waits for the reply. Only run it in DBus thread.
|
||||
//
|
||||
class DBusConnectionSendAndBlockRunnable : public DBusConnectionSendSyncRunnable
|
||||
{
|
||||
private:
|
||||
static void Notify(DBusPendingCall* aCall, void* aData)
|
||||
{
|
||||
DBusConnectionSendAndBlockRunnable* runnable(
|
||||
static_cast<DBusConnectionSendAndBlockRunnable*>(aData));
|
||||
|
||||
runnable->mReply = dbus_pending_call_steal_reply(aCall);
|
||||
|
||||
bool success = !!runnable->mReply;
|
||||
|
||||
if (runnable->mError) {
|
||||
success = success && !dbus_error_is_set(runnable->mError);
|
||||
|
||||
if (!dbus_set_error_from_message(runnable->mError, runnable->mReply)) {
|
||||
dbus_error_init(runnable->mError);
|
||||
}
|
||||
}
|
||||
|
||||
dbus_pending_call_cancel(aCall);
|
||||
dbus_pending_call_unref(aCall);
|
||||
|
||||
runnable->Completed(success);
|
||||
}
|
||||
|
||||
public:
|
||||
DBusConnectionSendAndBlockRunnable(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage,
|
||||
int aTimeout,
|
||||
DBusError* aError)
|
||||
: DBusConnectionSendSyncRunnable(aConnection, aMessage),
|
||||
mError(aError),
|
||||
mReply(nullptr),
|
||||
mTimeout(aTimeout)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
DBusPendingCall* call = nullptr;
|
||||
|
||||
dbus_bool_t success = dbus_connection_send_with_reply(mConnection,
|
||||
mMessage,
|
||||
&call,
|
||||
mTimeout);
|
||||
if (success == TRUE) {
|
||||
success = dbus_pending_call_set_notify(call, Notify, this, nullptr);
|
||||
} else {
|
||||
if (mError) {
|
||||
if (!call) {
|
||||
dbus_set_error(mError, DBUS_ERROR_DISCONNECTED, "Connection is closed");
|
||||
} else {
|
||||
dbus_error_init(mError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbus_message_unref(mMessage);
|
||||
|
||||
if (!success) {
|
||||
Completed(false);
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DBusMessage* GetReply()
|
||||
{
|
||||
return mReply;
|
||||
}
|
||||
|
||||
protected:
|
||||
~DBusConnectionSendAndBlockRunnable()
|
||||
{ }
|
||||
|
||||
private:
|
||||
DBusError* mError;
|
||||
DBusMessage* mReply;
|
||||
int mTimeout;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,58 +281,6 @@ bool RawDBusConnection::SendWithReply(DBusReplyCallback aCallback,
|
|||
return SendWithReply(aCallback, aData, aTimeout, msg);
|
||||
}
|
||||
|
||||
bool RawDBusConnection::SendWithError(DBusMessage** aReply,
|
||||
DBusError* aError,
|
||||
int aTimeout,
|
||||
DBusMessage* aMessage)
|
||||
{
|
||||
nsRefPtr<DBusConnectionSendAndBlockRunnable> t(
|
||||
new DBusConnectionSendAndBlockRunnable(mConnection, aMessage,
|
||||
aTimeout, aError));
|
||||
MOZ_ASSERT(t);
|
||||
|
||||
nsresult rv = DispatchToDBusThread(t);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (aMessage) {
|
||||
dbus_message_unref(aMessage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!t->WaitForCompletion()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aReply) {
|
||||
*aReply = t->GetReply();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawDBusConnection::SendWithError(DBusMessage** aReply,
|
||||
DBusError* aError,
|
||||
int aTimeout,
|
||||
const char* aPath,
|
||||
const char* aIntf,
|
||||
const char* aFunc,
|
||||
int aFirstArgType, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, aFirstArgType);
|
||||
DBusMessage* msg = BuildDBusMessage(aPath, aIntf, aFunc,
|
||||
aFirstArgType, args);
|
||||
va_end(args);
|
||||
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SendWithError(aReply, aError, aTimeout, msg);
|
||||
}
|
||||
|
||||
DBusMessage* RawDBusConnection::BuildDBusMessage(const char* aPath,
|
||||
const char* aIntf,
|
||||
const char* aFunc,
|
||||
|
|
|
@ -53,15 +53,6 @@ public:
|
|||
int aTimeout, const char* aPath, const char* aIntf,
|
||||
const char *aFunc, int aFirstArgType, ...);
|
||||
|
||||
/* Legacy interface, don't use in new code */
|
||||
bool SendWithError(DBusMessage** aReply, DBusError* aError, int aTimeout,
|
||||
DBusMessage* aMessage);
|
||||
|
||||
/* Legacy interface, don't use in new code */
|
||||
bool SendWithError(DBusMessage** aReply, DBusError* aError, int aTimeout,
|
||||
const char* aPath, const char* aIntf, const char* aFunc,
|
||||
int aFirstArgType, ...);
|
||||
|
||||
protected:
|
||||
DBusMessage* BuildDBusMessage(const char* aPath, const char* aIntf,
|
||||
const char* aFunc, int aFirstArgType,
|
||||
|
|
|
@ -17,10 +17,10 @@ if CONFIG['MOZ_B2G_RIL']:
|
|||
if CONFIG['MOZ_B2G_BT_BLUEZ']:
|
||||
DIRS += ['dbus']
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT']:
|
||||
DIRS += ['unixsocket', 'keystore']
|
||||
if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
DIRS += ['unixsocket']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
DIRS += ['netd']
|
||||
DIRS += ['netd', 'keystore']
|
||||
|
||||
TOOL_DIRS += ['app']
|
||||
|
|
169
ipc/ril/Ril.cpp
169
ipc/ril/Ril.cpp
|
@ -4,6 +4,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
@ -18,8 +20,8 @@
|
|||
#endif
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h" // For NS_IsMainThread.
|
||||
#include "Ril.h"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
using namespace mozilla::ipc;
|
||||
|
@ -32,17 +34,130 @@ const char* RIL_SOCKET_NAME = "/dev/socket/rilproxy";
|
|||
// desktop development.
|
||||
const uint32_t RIL_TEST_PORT = 6200;
|
||||
|
||||
class DispatchRILEvent : public WorkerTask
|
||||
nsTArray<nsRefPtr<mozilla::ipc::RilConsumer> > sRilConsumers;
|
||||
|
||||
class ConnectWorkerToRIL : public WorkerTask
|
||||
{
|
||||
public:
|
||||
DispatchRILEvent(UnixSocketRawData* aMessage)
|
||||
: mMessage(aMessage)
|
||||
ConnectWorkerToRIL()
|
||||
{ }
|
||||
|
||||
virtual bool RunTask(JSContext *aCx);
|
||||
};
|
||||
|
||||
class SendRilSocketDataTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SendRilSocketDataTask(unsigned long aClientId,
|
||||
UnixSocketRawData *aRawData)
|
||||
: mRawData(aRawData)
|
||||
, mClientId(aClientId)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sRilConsumers.Length() <= mClientId ||
|
||||
!sRilConsumers[mClientId] ||
|
||||
sRilConsumers[mClientId]->GetConnectionStatus() != SOCKET_CONNECTED) {
|
||||
// Probably shuting down.
|
||||
delete mRawData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
sRilConsumers[mClientId]->SendSocketData(mRawData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketRawData> mMessage;
|
||||
UnixSocketRawData *mRawData;
|
||||
unsigned long mClientId;
|
||||
};
|
||||
|
||||
bool
|
||||
PostToRIL(JSContext *aCx,
|
||||
unsigned aArgc,
|
||||
JS::Value *aArgv)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
|
||||
|
||||
if (aArgc != 2) {
|
||||
JS_ReportError(aCx, "Expecting two arguments with the RIL message");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Value cv = JS_ARGV(aCx, aArgv)[0];
|
||||
int clientId = cv.toInt32();
|
||||
|
||||
JS::Value v = JS_ARGV(aCx, aArgv)[1];
|
||||
|
||||
JSAutoByteString abs;
|
||||
void *data;
|
||||
size_t size;
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
JSString *str = JSVAL_TO_STRING(v);
|
||||
if (!abs.encodeUtf8(aCx, str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data = abs.ptr();
|
||||
size = abs.length();
|
||||
} else if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_IsTypedArrayObject(obj)) {
|
||||
JS_ReportError(aCx, "Object passed in wasn't a typed array");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t type = JS_GetArrayBufferViewType(obj);
|
||||
if (type != js::ArrayBufferView::TYPE_INT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
|
||||
JS_ReportError(aCx, "Typed array data is not octets");
|
||||
return false;
|
||||
}
|
||||
|
||||
size = JS_GetTypedArrayByteLength(obj);
|
||||
data = JS_GetArrayBufferViewData(obj);
|
||||
} else {
|
||||
JS_ReportError(aCx,
|
||||
"Incorrect argument. Expecting a string or a typed array");
|
||||
return false;
|
||||
}
|
||||
|
||||
UnixSocketRawData* raw = new UnixSocketRawData(data, size);
|
||||
|
||||
nsRefPtr<SendRilSocketDataTask> task =
|
||||
new SendRilSocketDataTask(clientId, raw);
|
||||
NS_DispatchToMainThread(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ConnectWorkerToRIL::RunTask(JSContext *aCx)
|
||||
{
|
||||
// Set up the postRILMessage on the function for worker -> RIL thread
|
||||
// communication.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
|
||||
NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
|
||||
JSObject *workerGlobal = JS::CurrentGlobalOrNull(aCx);
|
||||
|
||||
return !!JS_DefineFunction(aCx, workerGlobal,
|
||||
"postRILMessage", PostToRIL, 1, 0);
|
||||
}
|
||||
|
||||
class DispatchRILEvent : public WorkerTask
|
||||
{
|
||||
public:
|
||||
DispatchRILEvent(UnixSocketRawData* aMessage)
|
||||
: mMessage(aMessage)
|
||||
{ }
|
||||
|
||||
virtual bool RunTask(JSContext *aCx);
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketRawData> mMessage;
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -192,11 +307,45 @@ RilConsumer::RilConsumer(unsigned long aClientId,
|
|||
ConnectSocket(new RilConnector(mClientId), mAddress.get());
|
||||
}
|
||||
|
||||
nsresult
|
||||
RilConsumer::Register(unsigned int aClientId,
|
||||
WorkerCrossThreadDispatcher* aDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
sRilConsumers.EnsureLengthAtLeast(aClientId + 1);
|
||||
|
||||
if (sRilConsumers[aClientId]) {
|
||||
NS_WARNING("RilConsumer already registered");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
|
||||
if (!aDispatcher->PostTask(connection)) {
|
||||
NS_WARNING("Failed to connect worker to ril");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Now that we're set up, connect ourselves to the RIL thread.
|
||||
sRilConsumers[aClientId] = new RilConsumer(aClientId, aDispatcher);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RilConsumer::Shutdown()
|
||||
{
|
||||
mShutdown = true;
|
||||
CloseSocket();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (unsigned long i = 0; i < sRilConsumers.Length(); i++) {
|
||||
nsRefPtr<RilConsumer>& instance = sRilConsumers[i];
|
||||
if (!instance) {
|
||||
continue;
|
||||
}
|
||||
|
||||
instance->mShutdown = true;
|
||||
instance->CloseSocket();
|
||||
instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -212,20 +361,20 @@ void
|
|||
RilConsumer::OnConnectSuccess()
|
||||
{
|
||||
// Nothing to do here.
|
||||
LOG("RIL[%u]: %s\n", mClientId, __FUNCTION__);
|
||||
LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
RilConsumer::OnConnectError()
|
||||
{
|
||||
LOG("RIL[%u]: %s\n", mClientId, __FUNCTION__);
|
||||
LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__);
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
void
|
||||
RilConsumer::OnDisconnect()
|
||||
{
|
||||
LOG("RIL[%u]: %s\n", mClientId, __FUNCTION__);
|
||||
LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__);
|
||||
if (!mShutdown) {
|
||||
ConnectSocket(new RilConnector(mClientId), mAddress.get(), 1000);
|
||||
}
|
||||
|
|
|
@ -16,13 +16,16 @@ namespace ipc {
|
|||
class RilConsumer : public mozilla::ipc::UnixSocketConsumer
|
||||
{
|
||||
public:
|
||||
RilConsumer(unsigned long aClientId,
|
||||
mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
|
||||
virtual ~RilConsumer() { }
|
||||
|
||||
void Shutdown();
|
||||
static nsresult Register(unsigned int aClientId,
|
||||
mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
RilConsumer(unsigned long aClientId,
|
||||
mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
|
||||
|
||||
virtual void ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage);
|
||||
|
||||
virtual void OnConnectSuccess();
|
||||
|
|
|
@ -23,6 +23,10 @@ simple_events = [
|
|||
'StyleRuleChangeEvent',
|
||||
'StyleSheetChangeEvent',
|
||||
'StyleSheetApplicableStateChangeEvent',
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
'MozWifiStatusChangeEvent',
|
||||
'MozWifiConnectionInfoEvent',
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
'BluetoothDeviceEvent',
|
||||
'BluetoothStatusChangedEvent',
|
||||
|
@ -32,8 +36,6 @@ simple_events = [
|
|||
'DataErrorEvent',
|
||||
'MozEmergencyCbModeEvent',
|
||||
'MozOtaStatusEvent',
|
||||
'MozWifiStatusChangeEvent',
|
||||
'MozWifiConnectionInfoEvent',
|
||||
'MozCellBroadcastEvent',
|
||||
'MozVoicemailEvent',
|
||||
'USSDReceivedEvent',
|
||||
|
|
|
@ -2497,7 +2497,6 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
|||
// tile with the overall area we're supposed to be filling
|
||||
gfxRect fillRect =
|
||||
forceRepeatToCoverTiles ? areaToFill : tileRect.Intersect(areaToFill);
|
||||
ctx->NewPath();
|
||||
// Try snapping the fill rect. Snap its top-left and bottom-right
|
||||
// independently to preserve the orientation.
|
||||
gfxPoint snappedFillRectTopLeft = fillRect.TopLeft();
|
||||
|
@ -2523,6 +2522,7 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
|||
snappedFillRectBottomRight);
|
||||
ctx->SetMatrix(transform);
|
||||
}
|
||||
ctx->NewPath();
|
||||
ctx->Rectangle(fillRect);
|
||||
ctx->Translate(tileRect.TopLeft());
|
||||
ctx->SetPattern(gradientPattern);
|
||||
|
|
|
@ -643,8 +643,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
|||
nsRect* aDisplayPort,
|
||||
nsRect* aCriticalDisplayPort,
|
||||
ViewID aScrollId,
|
||||
const nsDisplayItem::ContainerParameters& aContainerParameters,
|
||||
bool aMayHaveTouchListeners) {
|
||||
const nsDisplayItem::ContainerParameters& aContainerParameters) {
|
||||
nsPresContext* presContext = aForFrame->PresContext();
|
||||
int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
LayoutDeviceToLayerScale resolution(aContainerParameters.mXScale, aContainerParameters.mYScale);
|
||||
|
@ -719,7 +718,16 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
|||
metrics.mZoom = metrics.mCumulativeResolution * metrics.mDevPixelsPerCSSPixel
|
||||
* layerToScreenScale;
|
||||
|
||||
metrics.mMayHaveTouchListeners = aMayHaveTouchListeners;
|
||||
if (presShell) {
|
||||
nsIDocument* document = nullptr;
|
||||
document = presShell->GetDocument();
|
||||
if (document) {
|
||||
nsCOMPtr<nsPIDOMWindow> innerWin(document->GetInnerWindow());
|
||||
if (innerWin) {
|
||||
metrics.mMayHaveTouchListeners = innerWin->HasTouchEventListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the composition bounds as the size of the scroll frame and
|
||||
// its origin relative to the reference frame.
|
||||
|
@ -1248,14 +1256,6 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
|
||||
bool mayHaveTouchListeners = false;
|
||||
if (document) {
|
||||
nsCOMPtr<nsPIDOMWindow> innerWin(document->GetInnerWindow());
|
||||
if (innerWin) {
|
||||
mayHaveTouchListeners = innerWin->HasTouchEventListeners();
|
||||
}
|
||||
}
|
||||
|
||||
nsRect viewport(aBuilder->ToReferenceFrame(aForFrame), aForFrame->GetSize());
|
||||
|
||||
RecordFrameMetrics(aForFrame, rootScrollFrame,
|
||||
|
@ -1263,7 +1263,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
root, mVisibleRect, viewport,
|
||||
(usingDisplayport ? &displayport : nullptr),
|
||||
(usingCriticalDisplayport ? &criticalDisplayport : nullptr),
|
||||
id, containerParameters, mayHaveTouchListeners);
|
||||
id, containerParameters);
|
||||
if (usingDisplayport &&
|
||||
!(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
|
||||
// See bug 693938, attachment 567017
|
||||
|
@ -3605,7 +3605,7 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
mVisibleRect, viewport,
|
||||
(usingDisplayport ? &displayport : nullptr),
|
||||
(usingCriticalDisplayport ? &criticalDisplayport : nullptr),
|
||||
scrollId, aContainerParameters, false);
|
||||
scrollId, aContainerParameters);
|
||||
|
||||
return layer.forget();
|
||||
}
|
||||
|
|
|
@ -127,9 +127,14 @@ endif #}
|
|||
|
||||
SHARED_LIBRARY_LIBS += $(DEPTH)/dom/camera/$(LIB_PREFIX)domcamera_s.$(LIB_SUFFIX)
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
SHARED_LIBRARY_LIBS += \
|
||||
$(DEPTH)/dom/system/gonk/$(LIB_PREFIX)domsystemgonk_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
endif #}
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
SHARED_LIBRARY_LIBS += \
|
||||
$(DEPTH)/dom/icc/src/$(LIB_PREFIX)dom_icc_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/cellbroadcast/src/$(LIB_PREFIX)dom_cellbroadcast_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/voicemail/$(LIB_PREFIX)domvoicemail_s.$(LIB_SUFFIX) \
|
||||
|
@ -326,7 +331,7 @@ ifdef MOZ_GSTREAMER
|
|||
LOCAL_INCLUDES += $(GSTREAMER_CFLAGS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/gonk
|
||||
endif #}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче