Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2013-10-18 11:45:22 +02:00
Родитель f05f468373 a3284daeb0
Коммит 0ad19c5f56
373 изменённых файлов: 5312 добавлений и 2593 удалений

Просмотреть файл

@ -360,6 +360,7 @@ pref("browser.dom.window.dump.enabled", false);
// Default Content Security Policy to apply to privileged and certified apps
pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'");
// If you change this CSP, make sure to update the fast path in nsCSPService.cpp
pref("security.apps.certified.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self'");
// Temporarily force-enable GL compositing. This is default-disabled
@ -388,9 +389,6 @@ pref("dom.ipc.browser_frames.oop_by_default", false);
// SMS/MMS
pref("dom.sms.enabled", true);
pref("dom.sms.strict7BitEncoding", false); // Disabled by default.
pref("dom.sms.requestStatusReport", true); // Enabled by default.
pref("dom.mms.requestStatusReport", true); // Enabled by default.
//The waiting time in network manager.
pref("network.gonk.ms-release-mms-connection", 30000);
@ -434,7 +432,6 @@ pref("services.push.udp.wakeupEnabled", true);
// NetworkStats
#ifdef MOZ_B2G_RIL
pref("dom.mozNetworkStats.enabled", true);
pref("ril.cellbroadcast.disabled", false);
pref("dom.webapps.firstRunWithSIM", true);
#endif
@ -730,10 +727,6 @@ pref("font.size.inflation.disabledInMasterProcess", true);
// consumption when applications are sent to the background.
pref("memory.free_dirty_pages", true);
// UAProfile settings
pref("wap.UAProf.url", "");
pref("wap.UAProf.tagname", "x-wap-profile");
pref("layout.imagevisibility.enabled", false);
pref("layout.imagevisibility.numscrollportwidths", 1);
pref("layout.imagevisibility.numscrollportheights", 1);
@ -824,6 +817,19 @@ pref("gfx.canvas.azure.accelerated", 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");

Просмотреть файл

@ -1,4 +1,4 @@
{
"revision": "563d1aa93586165246ab2ab9d40566a598f56387",
"revision": "154bb18c48ff06e41fb7ba24d8f72d520919646f",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -20,8 +20,7 @@
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1"
"MOZILLA_OFFICIAL": "1"
},
"b2g_manifest": "hamachi.xml",
"b2g_manifest_branch": "master",

Просмотреть файл

@ -20,7 +20,6 @@
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1",
"ANDROIDFS_DIR": "{workdir}/helix-ics"
},
"b2g_manifest": "helix.xml",

Просмотреть файл

@ -20,8 +20,7 @@
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1"
"MOZILLA_OFFICIAL": "1"
},
"b2g_manifest": "inari.xml",
"b2g_manifest_branch": "master",

Просмотреть файл

@ -20,8 +20,7 @@
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1"
"MOZILLA_OFFICIAL": "1"
},
"b2g_manifest": "leo.xml",
"b2g_manifest_branch": "master",

Просмотреть файл

@ -20,8 +20,7 @@
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1"
"MOZILLA_OFFICIAL": "1"
},
"b2g_manifest": "nexus-4.xml",
"b2g_manifest_branch": "master",

Просмотреть файл

@ -22,8 +22,7 @@
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"B2GUPDATER": "1"
"MOZILLA_OFFICIAL": "1"
},
"gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
"gaia": {

Просмотреть файл

@ -129,8 +129,9 @@ pref("app.update.cert.maxErrors", 5);
// the |app.update.url.override| preference should ONLY be used for testing.
// IMPORTANT! metro.js should also be updated for updates to certs.X.issuerName
// Nightly builds have switched over to aus4.mozilla.org, but we don't want anything else to yet.
#ifdef NIGHTLY_BUILD
// Non-release builds (Nightly, Aurora, etc.) have been switched over to aus4.mozilla.org.
// This condition protects us against accidentally using it for release builds.
#ifndef RELEASE_BUILD
pref("app.update.certs.1.issuerName", "CN=DigiCert Secure Server CA,O=DigiCert Inc,C=US");
pref("app.update.certs.1.commonName", "aus4.mozilla.org");
@ -172,7 +173,7 @@ pref("app.update.silent", false);
pref("app.update.staging.enabled", true);
// Update service URL:
#ifdef NIGHTLY_BUILD
#ifndef RELEASE_BUILD
pref("app.update.url", "https://aus4.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
#else
pref("app.update.url", "https://aus3.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");

Просмотреть файл

@ -778,27 +778,6 @@ var gBrowserInit = {
window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
new nsBrowserAccess();
// Manually hook up session and global history for the first browser
// so that we don't have to load global history before bringing up a
// window.
// Wire up session and global history before any possible
// progress notifications for back/forward button updating
gBrowser.webNavigation.sessionHistory = Cc["@mozilla.org/browser/shistory;1"].
createInstance(Ci.nsISHistory);
Services.obs.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false);
// remove the disablehistory attribute so the browser cleans up, as
// though it had done this work itself
gBrowser.browsers[0].removeAttribute("disablehistory");
// enable global history
try {
if (!gMultiProcessBrowser)
gBrowser.docShell.useGlobalHistory = true;
} catch(ex) {
Cu.reportError("Places database may be locked: " + ex);
}
// hook up UI through progress listener
gBrowser.addProgressListener(window.XULBrowserWindow);
gBrowser.addTabsProgressListener(window.TabsProgressListener);

Просмотреть файл

@ -1045,7 +1045,7 @@
<splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
<vbox id="appcontent" flex="1">
<tabbrowser id="content" disablehistory="true"
<tabbrowser id="content"
flex="1" contenttooltip="aHTMLTooltip"
tabcontainer="tabbrowser-tabs"
contentcontextmenu="contentAreaContextMenu"

Просмотреть файл

@ -34,7 +34,7 @@
<xul:hbox flex="1" class="browserSidebarContainer">
<xul:vbox flex="1" class="browserContainer">
<xul:stack flex="1" class="browserStack" anonid="browserStack">
<xul:browser anonid="initialBrowser" type="content-primary" message="true" disablehistory="true"
<xul:browser anonid="initialBrowser" type="content-primary" message="true"
xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectpopup"/>
</xul:stack>
</xul:vbox>

Просмотреть файл

@ -1479,7 +1479,7 @@ let SessionStoreInternal = {
TabStateCache.delete(aTab);
this._setWindowStateBusy(window);
this.restoreHistoryPrecursor(window, [aTab], [tabState], 0, 0, 0);
this.restoreHistoryPrecursor(window, [aTab], [tabState], 0);
},
duplicateTab: function ssi_duplicateTab(aWindow, aTab, aDelta = 0) {
@ -1499,7 +1499,7 @@ let SessionStoreInternal = {
aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
aWindow.gBrowser.addTab();
this.restoreHistoryPrecursor(aWindow, [newTab], [tabState], 0, 0, 0,
this.restoreHistoryPrecursor(aWindow, [newTab], [tabState], 0,
true /* Load this tab right away. */);
return newTab;
@ -1579,7 +1579,7 @@ let SessionStoreInternal = {
let tab = tabbrowser.addTab();
// restore tab content
this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1);
// restore the tab's position
tabbrowser.moveTabTo(tab, closedTab.pos);
@ -2352,7 +2352,7 @@ let SessionStoreInternal = {
}
this.restoreHistoryPrecursor(aWindow, tabs, winData.tabs,
(overwriteTabs ? (parseInt(winData.selected) || 1) : 0), 0, 0);
(overwriteTabs ? (parseInt(winData.selected) || 1) : 0));
if (aState.scratchpads) {
ScratchpadManager.restoreSession(aState.scratchpads);
@ -2456,40 +2456,17 @@ let SessionStoreInternal = {
* Array of tab data
* @param aSelectTab
* Index of selected tab
* @param aIx
* Index of the next tab to check readyness for
* @param aCount
* Counter for number of times delaying b/c browser or history aren't ready
* @param aRestoreImmediately
* Flag to indicate whether the given set of tabs aTabs should be
* restored/loaded immediately even if restore_on_demand = true
*/
restoreHistoryPrecursor:
function ssi_restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab,
aIx, aCount, aRestoreImmediately = false) {
aRestoreImmediately = false)
{
var tabbrowser = aWindow.gBrowser;
// make sure that all browsers and their histories are available
// - if one's not, resume this check in 100ms (repeat at most 10 times)
for (var t = aIx; t < aTabs.length; t++) {
try {
if (!tabbrowser.getBrowserForTab(aTabs[t]).webNavigation.sessionHistory) {
throw new Error();
}
}
catch (ex) { // in case browser or history aren't ready yet
if (aCount < 10) {
var restoreHistoryFunc = function(self) {
self.restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab,
aIx, aCount + 1, aRestoreImmediately);
};
aWindow.setTimeout(restoreHistoryFunc, 100, this);
return;
}
}
}
if (!this._isWindowLoaded(aWindow)) {
// from now on, the data will come from the actual window
delete this._statesToRestore[aWindow.__SS_restoreID];
@ -2515,7 +2492,7 @@ let SessionStoreInternal = {
return;
}
// Sets the tabs restoring order.
// Sets the tabs restoring order.
[aTabs, aTabData] =
this._setTabsRestoringOrder(tabbrowser, aTabs, aTabData, aSelectTab);
@ -2523,7 +2500,7 @@ let SessionStoreInternal = {
// and show/hide tabs as necessary. We'll also set the labels, user typed
// value, and attach a copy of the tab's data in case we close it before
// it's been restored.
for (t = 0; t < aTabs.length; t++) {
for (let t = 0; t < aTabs.length; t++) {
let tab = aTabs[t];
let browser = tabbrowser.getBrowserForTab(tab);
let tabData = aTabData[t];
@ -2595,14 +2572,14 @@ let SessionStoreInternal = {
// helper hashes for ensuring unique frame IDs and unique document
// identifiers.
var idMap = { used: {} };
var docIdentMap = {};
let idMap = { used: {} };
let docIdentMap = {};
this.restoreHistory(aWindow, aTabs, aTabData, idMap, docIdentMap,
aRestoreImmediately);
},
/**
* Restore history for a window
* Restore history for a list of tabs.
* @param aWindow
* Window reference
* @param aTabs

Просмотреть файл

@ -449,7 +449,7 @@ pref("app.update.silent", true);
pref("app.update.staging.enabled", true);
// Update service URL:
#ifdef NIGHTLY_BUILD
#ifndef RELEASE_BUILD
pref("app.update.url", "https://aus4.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
#else
pref("app.update.url", "https://aus3.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
@ -522,8 +522,9 @@ pref("app.update.cert.maxErrors", 5);
// the |app.update.url.override| preference should ONLY be used for testing.
// IMPORTANT! firefox.js should also be updated for updates to certs.X.issuerName
// Nightly builds have switched over to aus4.mozilla.org, but we don't want anything else to yet.
#ifdef NIGHTLY_BUILD
// Non-release builds (Nightly, Aurora, etc.) have been switched over to aus4.mozilla.org.
// This condition protects us against accidentally using it for release builds.
#ifndef RELEASE_BUILD
pref("app.update.certs.1.issuerName", "CN=DigiCert Secure Server CA,O=DigiCert Inc,C=US");
pref("app.update.certs.1.commonName", "aus4.mozilla.org");
pref("app.update.certs.2.issuerName", "CN=Thawte SSL CA,O=\"Thawte, Inc.\",C=US");

Просмотреть файл

@ -30,9 +30,8 @@ this.webappsUI = {
Services.obs.addObserver(this, "webapps-launch", false);
Services.obs.addObserver(this, "webapps-uninstall", false);
cpmm.addMessageListener("Webapps:Install:Return:OK", this);
cpmm.addMessageListener("Webapps:OfflineCache", this);
cpmm.addMessageListener("Webapps:Install:Return:KO", this);
cpmm.addMessageListener("Webapps:PackageEvent", this);
cpmm.addMessageListener("Webapps:UpdateState", this);
},
uninit: function webappsUI_uninit() {
@ -40,9 +39,8 @@ this.webappsUI = {
Services.obs.removeObserver(this, "webapps-launch");
Services.obs.removeObserver(this, "webapps-uninstall");
cpmm.removeMessageListener("Webapps:Install:Return:OK", this);
cpmm.removeMessageListener("Webapps:OfflineCache", this);
cpmm.removeMessageListener("Webapps:Install:Return:KO", this);
cpmm.removeMessageListener("Webapps:PackageEvent", this);
cpmm.removeMessageListener("Webapps:UpdateState", this);
},
receiveMessage: function(aMessage) {
@ -56,10 +54,10 @@ this.webappsUI = {
return;
}
if (aMessage.name == "Webapps:OfflineCache") {
if (aMessage.name == "Webapps:UpdateState") {
if (data.error) {
this.installations[manifestURL].reject(data.error);
} else if (data.installState == "installed") {
} else if (data.app.installState == "installed") {
this.installations[manifestURL].resolve();
}
} else if (aMessage.name == "Webapps:Install:Return:OK" &&
@ -70,12 +68,6 @@ this.webappsUI = {
}
} else if (aMessage.name == "Webapps:Install:Return:KO") {
this.installations[manifestURL].reject(data.error);
} else if (aMessage.name == "Webapps:PackageEvent") {
if (data.type == "installed") {
this.installations[manifestURL].resolve();
} else if (data.type == "error") {
this.installations[manifestURL].reject(data.error);
}
}
},

Просмотреть файл

@ -29,9 +29,9 @@ toolkit/library
editor
parser
js/src
js/xpconnect
js/xpconnect/loader
mfbt
js/xpconnect
js/xpconnect/loader
view
caps
xpfe/appshell

Просмотреть файл

@ -86,27 +86,41 @@ dnl ========================================================
MOZ_USE_PTHREADS=
_PTHREAD_LDFLAGS=""
dnl Do not allow a separate objdir build if a srcdir build exists.
dnl Do not allow objdir == srcdir builds.
dnl ==============================================================
_topsrcdir=`cd \`dirname $0\`; pwd`
_objdir=`pwd`
if test "$_topsrcdir" != "$_objdir"
then
# Check for a couple representative files in the source tree
_conflict_files=
for file in $_topsrcdir/Makefile $_topsrcdir/config/autoconf.mk; do
if test -f $file; then
_conflict_files="$_conflict_files $file"
fi
dnl TODO Don't exempt L10N builds once bug 842760 is resolved.
if test "$_topsrcdir" = "$_objdir" -a "${with_l10n_base+set}" != set; then
echo " ***"
echo " * Building directly in the main source directory is not allowed."
echo " *"
echo " * To build, you must run configure from a separate directory"
echo " * (referred to as an object directory)."
echo " *"
echo " * If you are building with a mozconfig, you will need to change your"
echo " * mozconfig to point to a different object directory."
echo " ***"
exit 1
fi
# Check for a couple representative files in the source tree
_conflict_files=
for file in $_topsrcdir/Makefile $_topsrcdir/config/autoconf.mk; do
if test -f $file; then
_conflict_files="$_conflict_files $file"
fi
done
if test "$_conflict_files"; then
echo "***"
echo "* Your source tree contains these files:"
for file in $_conflict_files; do
echo "* $file"
done
if test "$_conflict_files"; then
echo "***"
echo "* Your source tree contains these files:"
for file in $_conflict_files; do
echo "* $file"
done
cat 1>&2 <<-EOF
cat 1>&2 <<-EOF
* This indicates that you previously built in the source tree.
* A source tree build can confuse the separate objdir build.
*
@ -115,9 +129,8 @@ then
* 2. gmake distclean
***
EOF
exit 1
break
fi
exit 1
break
fi
MOZ_BUILD_ROOT=`pwd`
@ -209,6 +222,7 @@ if test -n "$gonkdir" ; then
15)
GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
MOZ_B2G_BT=1
MOZ_B2G_BT_BLUEZ=1
MOZ_B2G_CAMERA=1
MOZ_OMX_DECODER=1
AC_SUBST(MOZ_OMX_DECODER)
@ -217,9 +231,15 @@ if test -n "$gonkdir" ; then
18)
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
if test -d "$gonkdir/external/bluetooth/bluez"; then
GONK_INCLUDES+=" -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
MOZ_B2G_BT=1
MOZ_B2G_BT_BLUEZ=1
fi
if test -d "$gonkdir/external/bluetooth/bluedroid"; then
MOZ_B2G_BT=1
MOZ_B2G_BT_BLUEDROID=1
fi
MOZ_B2G_CAMERA=1
MOZ_OMX_DECODER=1
AC_SUBST(MOZ_OMX_DECODER)
@ -7275,6 +7295,8 @@ if test -n "$MOZ_B2G_BT"; then
AC_DEFINE(MOZ_B2G_BT)
fi
AC_SUBST(MOZ_B2G_BT)
AC_SUBST(MOZ_B2G_BT_BLUEZ)
AC_SUBST(MOZ_B2G_BT_BLUEDROID)
dnl ========================================================
dnl = Enable Pico Speech Synthesis (Gonk usually)

Просмотреть файл

@ -19,6 +19,7 @@
#endif
#include "js/TypeDecls.h"
#include "js/Value.h"
#include "js/RootingAPI.h"
#include "mozilla/Assertions.h"
#include "mozilla/EventForwards.h"
@ -1637,7 +1638,7 @@ public:
static nsresult WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsISupports *native, const nsIID* aIID,
JS::Value *vp,
JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the Value alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr,
@ -1649,7 +1650,7 @@ public:
// Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
static nsresult WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsISupports *native, JS::Value *vp,
nsISupports *native, JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the Value alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr,
@ -1660,7 +1661,7 @@ public:
}
static nsresult WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsISupports *native, nsWrapperCache *cache,
JS::Value *vp,
JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the Value alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr,
@ -2091,7 +2092,7 @@ private:
static nsresult WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsISupports *native, nsWrapperCache *cache,
const nsIID* aIID, JS::Value *vp,
const nsIID* aIID, JS::MutableHandle<JS::Value> vp,
nsIXPConnectJSObjectHolder** aHolder,
bool aAllowWrapping);

Просмотреть файл

@ -45,6 +45,7 @@ CSPService::CSPService()
CSPService::~CSPService()
{
mAppStatusCache.Clear();
}
NS_IMPL_ISUPPORTS2(CSPService, nsIContentPolicy, nsIChannelEventSink)
@ -105,6 +106,55 @@ CSPService::ShouldLoad(uint32_t aContentType,
return NS_OK;
}
// ----- THIS IS A TEMPORARY FAST PATH FOR CERTIFIED APPS. -----
// ----- PLEASE REMOVE ONCE bug 925004 LANDS. -----
// Cache the app status for this origin.
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
nsAutoCString contentOrigin;
aContentLocation->GetPrePath(contentOrigin);
if (aRequestPrincipal && !mAppStatusCache.Get(contentOrigin, &status)) {
aRequestPrincipal->GetAppStatus(&status);
mAppStatusCache.Put(contentOrigin, status);
}
if (status == nsIPrincipal::APP_STATUS_CERTIFIED) {
// The CSP for certified apps is :
// "default-src *; script-src 'self'; object-src 'none'; style-src 'self'"
// That means we can optimize for this case by:
// - loading only same origin scripts and stylesheets.
// - never loading objects.
// - accepting everything else.
switch (aContentType) {
case nsIContentPolicy::TYPE_SCRIPT:
case nsIContentPolicy::TYPE_STYLESHEET:
{
nsAutoCString sourceOrigin;
aRequestOrigin->GetPrePath(sourceOrigin);
if (!sourceOrigin.Equals(contentOrigin)) {
*aDecision = nsIContentPolicy::REJECT_SERVER;
}
}
break;
case nsIContentPolicy::TYPE_OBJECT:
*aDecision = nsIContentPolicy::REJECT_SERVER;
break;
default:
*aDecision = nsIContentPolicy::ACCEPT;
}
// Only cache and return if we are successful. If not, we want the error
// to be reported, and thus fallback to the slow path.
if (*aDecision == nsIContentPolicy::ACCEPT) {
return NS_OK;
}
}
// ----- END OF TEMPORARY FAST PATH FOR CERTIFIED APPS. -----
// find the principal of the document that initiated this request and see
// if it has a CSP policy object
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));

Просмотреть файл

@ -23,4 +23,7 @@ public:
CSPService();
virtual ~CSPService();
static bool sCSPEnabled;
private:
// Maps origins to app status.
nsDataHashtable<nsCStringHashKey, uint16_t> mAppStatusCache;
};

Просмотреть файл

@ -5659,14 +5659,14 @@ nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
nsresult
nsContentUtils::WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsISupports *native, nsWrapperCache *cache,
const nsIID* aIID, JS::Value *vp,
const nsIID* aIID, JS::MutableHandleValue vp,
nsIXPConnectJSObjectHolder **aHolder,
bool aAllowWrapping)
{
if (!native) {
NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
*vp = JSVAL_NULL;
vp.setNull();
return NS_OK;
}
@ -5685,7 +5685,7 @@ nsContentUtils::WrapNative(JSContext *cx, JS::Handle<JSObject*> scope,
nsresult rv = NS_OK;
AutoPushJSContext context(cx);
rv = sXPConnect->WrapNativeToJSVal(context, scope, native, cache, aIID,
aAllowWrapping, vp, aHolder);
aAllowWrapping, vp.address(), aHolder);
return rv;
}
@ -5728,8 +5728,7 @@ nsContentUtils::CreateBlobBuffer(JSContext* aCx,
return NS_ERROR_OUT_OF_MEMORY;
}
JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
return nsContentUtils::WrapNative(aCx, scope, blob, aBlob.address(), nullptr,
true);
return nsContentUtils::WrapNative(aCx, scope, blob, aBlob, nullptr, true);
}
void

Просмотреть файл

@ -206,9 +206,11 @@ nsDOMFileReader::GetResult(JSContext* aCx, JS::Value* aResult)
}
nsString tmpResult = mResult;
if (!xpc::StringToJsval(aCx, tmpResult, aResult)) {
JS::Rooted<JS::Value> result(aCx);
if (!xpc::StringToJsval(aCx, tmpResult, &result)) {
return NS_ERROR_FAILURE;
}
*aResult = result;
return NS_OK;
}

Просмотреть файл

@ -5167,7 +5167,7 @@ CustomElementConstructor(JSContext *aCx, unsigned aArgc, JS::Value* aVp)
nsresult rv = document->CreateElem(elemName, nullptr, kNameSpaceID_XHTML,
getter_AddRefs(newElement));
rv = nsContentUtils::WrapNative(aCx, global, newElement, newElement,
args.rval().address());
args.rval());
NS_ENSURE_SUCCESS(rv, false);
return true;
@ -6732,7 +6732,7 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
JS::Rooted<JSObject*> global(cx, GetScopeObject()->GetGlobalJSObject());
JS::Rooted<JS::Value> v(cx);
rv = nsContentUtils::WrapNative(cx, global, this, this, v.address(),
rv = nsContentUtils::WrapNative(cx, global, this, this, &v,
nullptr, /* aAllowWrapping = */ false);
if (rv.Failed())
return nullptr;
@ -11345,7 +11345,7 @@ nsIDocument::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
&NS_GET_IID(nsIDOMWindow),
winVal.address(),
&winVal,
getter_AddRefs(holder),
false);
if (NS_FAILED(rv)) {

Просмотреть файл

@ -832,7 +832,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
JS::Rooted<JS::Value> targetv(ctx);
JS::Rooted<JSObject*> global(ctx, JS_GetGlobalForObject(ctx, object));
nsContentUtils::WrapNative(ctx, global, aTarget, targetv.address(),
nsContentUtils::WrapNative(ctx, global, aTarget, &targetv,
nullptr, true);
JS::RootedObject cpows(ctx);
@ -888,7 +888,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
}
JS::Rooted<JSObject*> global(ctx, JS_GetGlobalForObject(ctx, object));
nsContentUtils::WrapNative(ctx, global, defaultThisValue,
thisValue.address(), nullptr, true);
&thisValue, nullptr, true);
} else {
// If the listener is a JS object which has receiveMessage function:
if (!JS_GetProperty(ctx, object, "receiveMessage", &funval) ||

Просмотреть файл

@ -49,7 +49,15 @@ void
nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
{
if (gDataTable) {
gDataTable->Remove(aUri);
nsCString uriIgnoringRef;
int32_t hashPos = aUri.FindChar('#');
if (hashPos < 0) {
uriIgnoringRef = aUri;
}
else {
uriIgnoringRef = StringHead(aUri, hashPos);
}
gDataTable->Remove(uriIgnoringRef);
if (gDataTable->Count() == 0) {
delete gDataTable;
gDataTable = nullptr;
@ -80,6 +88,27 @@ nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
return NS_OK;
}
static DataInfo*
GetDataInfo(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
nsCString uriIgnoringRef;
int32_t hashPos = aUri.FindChar('#');
if (hashPos < 0) {
uriIgnoringRef = aUri;
}
else {
uriIgnoringRef = StringHead(aUri, hashPos);
}
gDataTable->Get(uriIgnoringRef, &res);
return res;
}
nsIPrincipal*
nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
{
@ -87,8 +116,8 @@ nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
return nullptr;
}
DataInfo* res;
gDataTable->Get(aUri, &res);
DataInfo* res = GetDataInfo(aUri);
if (!res) {
return nullptr;
}
@ -114,18 +143,6 @@ nsHostObjectProtocolHandler::Traverse(const nsACString& aUri,
aCallback.NoteXPCOMChild(res->mObject);
}
static DataInfo*
GetDataInfo(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
gDataTable->Get(aUri, &res);
return res;
}
static nsISupports*
GetDataObject(nsIURI* aURI)
{

Просмотреть файл

@ -966,7 +966,7 @@ nsXMLHttpRequest::GetResponse(JSContext* aCx, ErrorResult& aRv)
if (aRv.Failed()) {
return JSVAL_NULL;
}
JS::Value result;
JS::Rooted<JS::Value> result(aCx);
if (!xpc::StringToJsval(aCx, str, &result)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return JSVAL_NULL;
@ -1014,7 +1014,7 @@ nsXMLHttpRequest::GetResponse(JSContext* aCx, ErrorResult& aRv)
JS::Rooted<JS::Value> result(aCx, JSVAL_NULL);
JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
aRv = nsContentUtils::WrapNative(aCx, scope, mResponseBlob, result.address(),
aRv = nsContentUtils::WrapNative(aCx, scope, mResponseBlob, &result,
nullptr, true);
return result;
}
@ -1026,7 +1026,7 @@ nsXMLHttpRequest::GetResponse(JSContext* aCx, ErrorResult& aRv)
JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Rooted<JS::Value> result(aCx, JSVAL_NULL);
aRv = nsContentUtils::WrapNative(aCx, scope, mResponseXML, result.address(),
aRv = nsContentUtils::WrapNative(aCx, scope, mResponseXML, &result,
nullptr, true);
return result;
}
@ -3659,7 +3659,7 @@ nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv)
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
JSAutoCompartment ac(aCx, wrapper);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, wrapper));
aRv = nsContentUtils::WrapNative(aCx, global, result, iid, v.address());
aRv = nsContentUtils::WrapNative(aCx, global, result, iid, &v);
return aRv.Failed() ? JSVAL_NULL : v;
}

Двоичные данные
content/base/test/reftest/mixed-bmp-png.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 17 KiB

Просмотреть файл

@ -0,0 +1 @@
== test_bug920877.html test_bug920877-ref.html

Просмотреть файл

@ -0,0 +1,20 @@
<html>
<body>
<script>
var img = document.createElement("img");
img.id = "img-ori";
img.src = "mixed-bmp-png.ico";
document.body.appendChild(img);
img = document.createElement("img");
img.id = "img-res32";
img.src = "mixed-bmp-png.ico#-moz-resolution=32,32";
document.body.appendChild(img);
img = document.createElement("img");
img.id = "img-res48";
img.src = "mixed-bmp-png.ico#-moz-resolution=48,48";
document.body.appendChild(img);
</script>
</body>
</html>

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -114,7 +114,7 @@ HTMLAudioElement::MozSetup(uint32_t aChannels, uint32_t aRate, ErrorResult& aRv)
#endif
mAudioStream = AudioStream::AllocateStream();
aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType);
aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType, AudioStream::HighLatency);
if (aRv.Failed()) {
mAudioStream->Shutdown();
mAudioStream = nullptr;

Просмотреть файл

@ -3155,7 +3155,7 @@ nsGenericHTMLElement::GetItemValue(JSContext* aCx, JSObject* aScope,
nsString string;
GetItemValueText(string);
JS::Value v;
JS::Rooted<JS::Value> v(aCx);
if (!xpc::NonVoidStringToJsval(aCx, string, &v)) {
aError.Throw(NS_ERROR_FAILURE);
return JS::UndefinedValue();

Просмотреть файл

@ -41,6 +41,11 @@ PRLogModuleInfo* gAudioStreamLog = nullptr;
static Mutex* gAudioPrefsLock = nullptr;
static double gVolumeScale;
static uint32_t gCubebLatency;
static bool gCubebLatencyPrefSet;
static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
StaticMutex AudioStream::mMutex;
uint32_t AudioStream::mPreferredSampleRate = 0;
/**
* When MOZ_DUMP_AUDIO is set in the environment (to anything),
@ -65,9 +70,10 @@ static int PrefChanged(const char* aPref, void* aClosure)
// Arbitrary default stream latency of 100ms. The higher this
// value, the longer stream volume changes will take to become
// audible.
uint32_t value = Preferences::GetUint(aPref, 100);
gCubebLatencyPrefSet = Preferences::HasUserValue(aPref);
uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS);
MutexAutoLock lock(*gAudioPrefsLock);
gCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 20), 1000);
gCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
}
return 0;
}
@ -97,6 +103,12 @@ static uint32_t GetCubebLatency()
MutexAutoLock lock(*gAudioPrefsLock);
return gCubebLatency;
}
static bool CubebLatencyPrefSet()
{
MutexAutoLock lock(*gAudioPrefsLock);
return gCubebLatencyPrefSet;
}
#endif
#if defined(MOZ_CUBEB) && defined(__ANDROID__) && defined(MOZ_B2G)
@ -311,7 +323,8 @@ class BufferedAudioStream : public AudioStream
~BufferedAudioStream();
nsresult Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannelType aAudioChannelType);
const dom::AudioChannelType aAudioChannelType,
AudioStream::LatencyRequest aLatencyRequest);
void Shutdown();
nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames);
uint32_t Available();
@ -431,6 +444,23 @@ int AudioStream::MaxNumberOfChannels()
return static_cast<int>(maxNumberOfChannels);
}
int AudioStream::PreferredSampleRate()
{
StaticMutexAutoLock lock(AudioStream::mMutex);
// Get the preferred samplerate for this platform, or fallback to something
// sensible if we fail. We cache the value, because this might be accessed
// often, and the complexity of the function call below depends on the
// backend used.
const int fallbackSampleRate = 44100;
if (mPreferredSampleRate == 0) {
if (cubeb_get_preferred_sample_rate(GetCubebContext(), &mPreferredSampleRate) != CUBEB_OK) {
mPreferredSampleRate = fallbackSampleRate;
}
}
return mPreferredSampleRate;
}
static void SetUint16LE(uint8_t* aDest, uint16_t aValue)
{
aDest[0] = aValue & 0xFF;
@ -526,7 +556,8 @@ BufferedAudioStream::EnsureTimeStretcherInitialized()
nsresult
BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannelType aAudioChannelType)
const dom::AudioChannelType aAudioChannelType,
AudioStream::LatencyRequest aLatencyRequest)
{
cubeb* cubebContext = GetCubebContext();
@ -562,10 +593,22 @@ BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
mAudioClock.Init();
// If the latency pref is set, use it. Otherwise, if this stream is intended
// for low latency playback, try to get the lowest latency possible.
// Otherwise, for normal streams, use 100ms.
uint32_t latency;
if (aLatencyRequest == AudioStream::LowLatency && !CubebLatencyPrefSet()) {
if (cubeb_get_min_latency(cubebContext, params, &latency) != CUBEB_OK) {
latency = GetCubebLatency();
}
} else {
latency = GetCubebLatency();
}
{
cubeb_stream* stream;
if (cubeb_stream_init(cubebContext, &stream, "BufferedAudioStream", params,
GetCubebLatency(), DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
mCubebStream.own(stream);
}
}

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "Latency.h"
#include "mozilla/StaticMutex.h"
namespace soundtouch {
class SoundTouch;
@ -92,6 +93,10 @@ class AudioClock
class AudioStream
{
public:
enum LatencyRequest {
HighLatency,
LowLatency
};
AudioStream();
virtual ~AudioStream();
@ -112,11 +117,16 @@ public:
// Returns the maximum number of channels supported by the audio hardware.
static int MaxNumberOfChannels();
// Returns the samplerate the systems prefer, because it is the
// samplerate the hardware/mixer supports.
static int PreferredSampleRate();
// Initialize the audio stream. aNumChannels is the number of audio
// channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
// (22050Hz, 44100Hz, etc).
virtual nsresult Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannelType aAudioStreamType) = 0;
const dom::AudioChannelType aAudioStreamType,
LatencyRequest aLatencyRequest) = 0;
// Closes the stream. All future use of the stream is an error.
virtual void Shutdown() = 0;
@ -178,6 +188,11 @@ public:
virtual nsresult SetPreservesPitch(bool aPreservesPitch);
protected:
// This mutex protects the mPreferedSamplerate member below.
static StaticMutex mMutex;
// Prefered samplerate, in Hz (characteristic of the
// hardware/mixer/platform/API used).
static uint32_t mPreferredSampleRate;
// Input rate in Hz (characteristic of the media being played)
int mInRate;
// Output rate in Hz (characteristic of the playback rate)

Просмотреть файл

@ -1059,7 +1059,7 @@ void MediaDecoderStateMachine::AudioLoop()
// circumstances, so we take care to drop the decoder monitor while
// initializing.
nsAutoPtr<AudioStream> audioStream(AudioStream::AllocateStream());
audioStream->Init(channels, rate, audioChannelType);
audioStream->Init(channels, rate, audioChannelType, AudioStream::HighLatency);
audioStream->SetVolume(volume);
if (audioStream->SetPreservesPitch(preservesPitch) != NS_OK) {
NS_WARNING("Setting the pitch preservation failed at AudioLoop start.");

Просмотреть файл

@ -768,7 +768,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTim
audioOutputStream->mStream = AudioStream::AllocateStream();
// XXX for now, allocate stereo output. But we need to fix this to
// match the system's ideal channel configuration.
audioOutputStream->mStream->Init(2, tracks->GetRate(), AUDIO_CHANNEL_NORMAL);
audioOutputStream->mStream->Init(2, tracks->GetRate(), AUDIO_CHANNEL_NORMAL, AudioStream::LowLatency);
audioOutputStream->mTrackID = tracks->GetID();
}
}

Просмотреть файл

@ -960,7 +960,7 @@ protected:
};
// Returns ideal audio rate for processing
inline TrackRate IdealAudioRate() { return 48000; }
inline TrackRate IdealAudioRate() { return AudioStream::PreferredSampleRate(); }
/**
* Initially, at least, we will have a singleton MediaStreamGraph per

Просмотреть файл

@ -85,7 +85,7 @@ void VideoFrameContainer::ClearCurrentFrame(bool aResetSize)
kungFuDeathGrip = mImageContainer->LockCurrentImage();
mImageContainer->UnlockCurrentImage();
mImageContainer->SetCurrentImage(nullptr);
mImageContainer->ClearAllImages();
mImageSizeChanged = aResetSize;
}

Просмотреть файл

@ -119,6 +119,7 @@ OpusTrackEncoder::OpusTrackEncoder()
, mEncoder(nullptr)
, mSourceSegment(new AudioSegment())
, mLookahead(0)
, mResampler(nullptr)
{
}
@ -147,16 +148,24 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate)
// The granule position is required to be incremented at a rate of 48KHz, and
// it is simply calculated as |granulepos = samples * (48000/source_rate)|,
// that is, the source sampling rate must divide 48000 evenly.
// If this constraint is not satisfied, we resample the input to 48kHz.
if (!((aSamplingRate >= 8000) && (kOpusSamplingRate / aSamplingRate) *
aSamplingRate == kOpusSamplingRate)) {
LOG("[Opus] Error! The source sample rate should be greater than 8000 and"
" divides 48000 evenly.");
return NS_ERROR_FAILURE;
int error;
mResampler = speex_resampler_init(mChannels,
aSamplingRate,
kOpusSamplingRate,
SPEEX_RESAMPLER_QUALITY_DEFAULT,
&error);
if (error != RESAMPLER_ERR_SUCCESS) {
return NS_ERROR_FAILURE;
}
}
mSamplingRate = aSamplingRate;
int error = 0;
mEncoder = opus_encoder_create(mSamplingRate, mChannels,
mEncoder = opus_encoder_create(GetOutputSampleRate(), mChannels,
OPUS_APPLICATION_AUDIO, &error);
mInitialized = (error == OPUS_OK);
@ -166,10 +175,16 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate)
return error == OPUS_OK ? NS_OK : NS_ERROR_FAILURE;
}
int
OpusTrackEncoder::GetOutputSampleRate()
{
return mResampler ? kOpusSamplingRate : mSamplingRate;
}
int
OpusTrackEncoder::GetPacketDuration()
{
return mSamplingRate * kFrameDurationMs / 1000;
return GetOutputSampleRate() * kFrameDurationMs / 1000;
}
nsresult
@ -282,8 +297,35 @@ OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
iter.Next();
}
// The ogg time stamping and pre-skip is always timed at 48000.
aOutputDuration = frameCopied * (kOpusSamplingRate / mSamplingRate);
if (mResampler) {
nsAutoTArray<AudioDataValue, 9600> resamplingDest;
// We want to consume all the input data, so we slightly oversize the
// resampled data buffer so we can fit the output data in. We cannot really
// predict the output frame count at each call.
uint32_t outframes = frameCopied * kOpusSamplingRate / mSamplingRate + 1;
uint32_t inframes = frameCopied;
resamplingDest.SetLength(outframes * mChannels);
#if MOZ_SAMPLE_TYPE_S16
short* in = reinterpret_cast<short*>(pcm.Elements());
short* out = reinterpret_cast<short*>(resamplingDest.Elements());
speex_resampler_process_interleaved_int(mResampler, in, &inframes,
out, &outframes);
#else
float* in = reinterpret_cast<float*>(pcm.Elements());
float* out = reinterpret_cast<float*>(resamplingDest.Elements());
speex_resampler_process_interleaved_float(mResampler, in, &inframes,
out, &outframes);
#endif
pcm = resamplingDest;
// This is always at 48000Hz.
aOutputDuration = outframes;
} else {
// The ogg time stamping and pre-skip is always timed at 48000.
aOutputDuration = frameCopied * (kOpusSamplingRate / mSamplingRate);
}
// Remove the raw data which has been pulled to pcm buffer.
// The value of frameCopied should equal to (or smaller than, if eos)
@ -294,6 +336,9 @@ OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
// encoding.
if (mSourceSegment->GetDuration() == 0 && mEndOfStream) {
mDoneEncoding = true;
if (mResampler) {
speex_resampler_destroy(mResampler);
}
LOG("[Opus] Done encoding.");
}

Просмотреть файл

@ -6,6 +6,8 @@
#ifndef OpusTrackEncoder_h_
#define OpusTrackEncoder_h_
#include <stdint.h>
#include <speex/speex_resampler.h>
#include "TrackEncoder.h"
#include "nsCOMPtr.h"
@ -35,6 +37,12 @@ private:
DATA
} mEncoderState;
/**
* Get the samplerate of the data to be fed to the Opus encoder. This might be
* different from the intput samplerate if resampling occurs.
*/
int GetOutputSampleRate();
/**
* The Opus encoder from libopus.
*/
@ -54,6 +62,12 @@ private:
* in order to align the time of input and output.
*/
int mLookahead;
/**
* If the input sample rate does not divide 48kHz evenly, the input data are
* resampled.
*/
SpeexResamplerState* mResampler;
};
}

Просмотреть файл

@ -345,6 +345,10 @@ nsresult MediaOmxReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndT
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
if (container && container->GetImageContainer()) {
container->GetImageContainer()->ClearAllImagesExceptFront();
}
mVideoQueue.Reset();
mAudioQueue.Reset();

Просмотреть файл

@ -231,6 +231,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_1(AudioDestinationNode, AudioNode,
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(AudioDestinationNode, AudioNode)

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsIDOMEventListener.h"
#include "nsIAudioChannelAgent.h"
#include "AudioChannelCommon.h"
#include "nsWeakReference.h"
namespace mozilla {
namespace dom {
@ -21,6 +22,7 @@ class AudioContext;
class AudioDestinationNode : public AudioNode
, public nsIDOMEventListener
, public nsIAudioChannelAgentCallback
, public nsSupportsWeakReference
{
public:
// This node type knows what MediaStreamGraph to use based on

Просмотреть файл

@ -50,13 +50,13 @@ DelayProcessor::Process(const double *aPerFrameDelays,
MOZ_ASSERT(readPosition >= 0.0, "Why are we reading before the beginning of the buffer?");
// Here is a the reason why readIndex1 and readIndex will never be out
// of bounds. The maximum value for bufferLength is 180 * 48000 (see
// AudioContext::CreateDelay). The maximum value for mCurrentDelay is
// 180.0, so initially readPosition cannot be more than bufferLength +
// a fraction less than 1. Then we take care of that case by
// subtracting bufferLength from it if needed. So, if
// |bufferLength-readPosition<1.0|, readIndex1 will end up being zero.
// If |1.0<=bufferLength-readPosition<2.0|, readIndex1 will be
// of bounds. The maximum value for bufferLength is
// 180 * AudioContext.samplerate (see AudioContext::CreateDelay). The
// maximum value for mCurrentDelay is 180.0, so initially readPosition
// cannot be more than bufferLength + a fraction less than 1. Then we
// take care of that case by subtracting bufferLength from it if needed.
// So, if |bufferLength-readPosition<1.0|, readIndex1 will end up being
// zero. If |1.0<=bufferLength-readPosition<2.0|, readIndex1 will be
// bufferLength-1 and readIndex2 will be 0.
int readIndex1 = int(readPosition);
int readIndex2 = (readIndex1 + 1) % bufferLength;

Двоичные данные
content/media/webaudio/test/audio-expected.wav

Двоичный файл не отображается.

Просмотреть файл

@ -12,15 +12,14 @@ support-files =
small-shot-expected.wav
small-shot-mono-expected.wav
small-shot.ogg
ting-dualchannel44.1-expected.wav
ting-dualchannel44.1.ogg
ting-dualchannel48-expected.wav
ting-dualchannel48.ogg
ting-expected.wav
ting-mono-dualchannel44.1-expected.wav
ting-mono-dualchannel48-expected.wav
ting-mono-expected.wav
ting.ogg
ting-44.1k-1ch.ogg
ting-44.1k-2ch.ogg
ting-48k-1ch.ogg
ting-48k-2ch.ogg
ting-44.1k-1ch.wav
ting-44.1k-2ch.wav
ting-48k-1ch.wav
ting-48k-2ch.wav
webaudio.js
[test_AudioBuffer.html]

Просмотреть файл

@ -13,7 +13,6 @@ SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
var ac = new AudioContext();
ok(ac, "Create a AudioContext object");
is(ac.sampleRate, 48000, "Correct sample rate");
ok(ac instanceof EventTarget, "AudioContexts must be EventTargets");
SimpleTest.finish();
});

Просмотреть файл

@ -105,63 +105,91 @@ function createWaveFileData(audioBuffer) {
</script>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var cx = new AudioContext();
// fuzzTolerance and fuzzToleranceMobile are used to determine fuzziness
// thresholds. They're needed to make sure that we can deal with neglibible
// differences in the binary buffer caused as a result of resampling the
// audio. fuzzToleranceMobile is typically larger on mobile platforms since
// we do fixed-point resampling as opposed to floating-point resampling on
// those platforms.
var tests = [
// A normal ogg file, 44.1khz
var files = [
// An ogg file, 44.1khz, mono
{
url: "ting.ogg",
url: "ting-44.1k-1ch.ogg",
valid: true,
expected: "ting-expected.wav",
expectedMono: "ting-mono-expected.wav",
numberOfChannels: 2,
duration: 0.6936,
length: 33294,
fuzzTolerance: 38,
fuzzToleranceMobile: 15906
expected: "ting-44.1k-1ch.wav",
numberOfChannels: 1,
frames: 30592,
sampleRate: 44100,
duration: 0.693,
fuzzTolerance: 5,
fuzzToleranceMobile: 1284
},
// An ogg file with two different channels, 44.1khz
// An ogg file, 44.1khz, stereo
{
url: "ting-dualchannel44.1.ogg",
url: "ting-44.1k-2ch.ogg",
valid: true,
expected: "ting-dualchannel44.1-expected.wav",
expectedMono: "ting-mono-dualchannel44.1-expected.wav",
expected: "ting-44.1k-2ch.wav",
numberOfChannels: 2,
duration: 0.6932,
length: 33274,
fuzzTolerance: 39,
fuzzToleranceMobile: 16798
frames: 30592,
sampleRate: 44100,
duration: 0.693,
fuzzTolerance: 6,
fuzzToleranceMobile: 2544
},
// An ogg file with two different channels, 48khz
// An ogg file, 48khz, mono
{
url: "ting-dualchannel48.ogg",
url: "ting-48k-1ch.ogg",
valid: true,
expected: "ting-dualchannel48-expected.wav",
expectedMono: "ting-mono-dualchannel48-expected.wav",
numberOfChannels: 2,
duration: 0.6373,
length: 30592,
fuzzTolerance: 9,
fuzzToleranceMobile: 8000
expected: "ting-48k-1ch.wav",
numberOfChannels: 1,
frames: 33297,
sampleRate: 48000,
duration: 0.693,
fuzzTolerance: 7,
fuzzToleranceMobile: 7070
},
// An ogg file which needs to be resampled
// An ogg file, 48khz, stereo
{
url: "small-shot.ogg",
url: "ting-48k-2ch.ogg",
valid: true,
expected: "small-shot-expected.wav",
expectedMono: "small-shot-mono-expected.wav",
expected: "ting-48k-2ch.wav",
numberOfChannels: 2,
duration: 0.2760,
length: 13248,
fuzzTolerance: 76,
fuzzToleranceMobile: 14844
frames: 33297,
sampleRate: 48000,
duration: 0.693,
fuzzTolerance: 12,
fuzzToleranceMobile: 13982
},
// A wave file
//{ url: "24bit-44khz.wav", valid: true, expected: "24bit-44khz-expected.wav" },
// Make sure decoding a wave file results in the same buffer (for both the
// resampling and non-resampling cases)
{
url: "ting-44.1k-1ch.wav",
valid: true,
expected: "ting-44.1k-1ch.wav",
numberOfChannels: 1,
frames: 30592,
sampleRate: 44100,
duration: 0.693,
fuzzTolerance: 0,
fuzzToleranceMobile: 0
},
{
url: "ting-48k-1ch.wav",
valid: true,
expected: "ting-48k-1ch.wav",
numberOfChannels: 1,
frames: 33297,
sampleRate: 48000,
duration: 0.693,
fuzzTolerance: 0,
fuzzToleranceMobile: 0
},
// // A wave file
// //{ url: "24bit-44khz.wav", valid: true, expected: "24bit-44khz-expected.wav" },
// A non-audio file
{ url: "invalid.txt", valid: false },
// A webm file with no audio
@ -171,24 +199,12 @@ var tests = [
url: "audio.ogv",
valid: true,
expected: "audio-expected.wav",
expectedMono: "audio-mono-expected.wav",
numberOfChannels: 2,
sampleRate: 44100,
frames: 47680,
duration: 1.0807,
length: 51872,
fuzzTolerance: 91427,
fuzzToleranceMobile: 119684
},
// Make sure decoding a wave file results in the same buffer
{
url: "audio-expected.wav",
valid: true,
expected: "audio-expected.wav",
expectedMono: "audio-mono-expected-2.wav",
numberOfChannels: 2,
duration: 1.0807,
length: 51872,
fuzzTolerance: 0,
fuzzToleranceMobile: 0
fuzzTolerance: 106,
fuzzToleranceMobile: 3482
}
];
@ -198,7 +214,7 @@ function fuzzyMemcmp(buf1, buf2, fuzz) {
var difference = 0;
is(buf1.length, buf2.length, "same length");
for (var i = 0; i < buf1.length; ++i) {
if (buf1[i] != buf2[i]) {
if (Math.abs(buf1[i] - buf2[i])) {
++difference;
}
}
@ -216,17 +232,20 @@ function getFuzzTolerance(test) {
}
function checkAudioBuffer(buffer, test, callback, monoTest) {
is(buffer.numberOfChannels, monoTest ? 1 : test.numberOfChannels, "Correct number of channels");
ok(Math.abs(buffer.duration - test.duration) < 1e-4, "Correct duration");
if (Math.abs(buffer.duration - test.duration) >= 1e-4) {
is(buffer.numberOfChannels, test.numberOfChannels, "Correct number of channels");
ok(Math.abs(buffer.duration - test.duration) < 1e-3, "Correct duration");
if (Math.abs(buffer.duration - test.duration) >= 1e-3) {
ok(false, "got: " + buffer.duration + ", expected: " + test.duration);
}
is(buffer.sampleRate, cx.sampleRate, "Correct sample rate");
is(buffer.length, test.length, "Correct length");
// Take into account the resampling when checking the size
var SRCRate = test.sampleRate / cx.sampleRate;
ok(Math.abs(buffer.length * SRCRate - test.frames) < test.frames * 0.01, "Correct length");
var wave = createWaveFileData(buffer);
var getExpected = new XMLHttpRequest();
getExpected.open("GET", monoTest ? test.expectedMono : test.expected, true);
getExpected.open("GET", test.expected, true);
getExpected.responseType = "arraybuffer";
getExpected.onload = function() {
ok(fuzzyMemcmp(wave, new Uint8Array(getExpected.response), getFuzzTolerance(test)), "Received expected decoded data");
@ -248,12 +267,7 @@ function runTest(test, callback) {
checkAudioBuffer(result, test, function() {
result = cx.createBuffer(xhr.response, false);
checkAudioBuffer(result, test, function() {
if ("expectedMono" in test) {
result = cx.createBuffer(xhr.response, true);
checkAudioBuffer(result, test, callback, true);
} else {
callback();
}
}, false);
}, false);
}, function onFailure() {
@ -267,17 +281,13 @@ function runTest(test, callback) {
}
function runNextTest() {
if (tests.length) {
runTest(tests.shift(), runNextTest);
if (files.length) {
runTest(files.shift(), runNextTest);
} else {
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
var cx = new AudioContext();
// Run some simple tests first
function callbackShouldNeverRun() {
ok(false, "callback should not fire");
@ -298,7 +308,7 @@ expectTypeError(function() {
cx.decodeAudioData(new Uint8Array(100), callbackShouldNeverRun, callbackShouldNeverRun);
});
if (cx.sampleRate == 48000) {
if (cx.sampleRate >= 44100) {
// Now, let's get real!
runNextTest();
} else {

Двоичные данные
content/media/webaudio/test/ting-44.1k-1ch.ogg Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-44.1k-1ch.wav Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-44.1k-2ch.ogg Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-44.1k-2ch.wav Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-48k-1ch.ogg Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-48k-1ch.wav Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-48k-2ch.ogg Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-48k-2ch.wav Normal file

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-dualchannel44.1.wav Normal file

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-dualchannel48.wav Normal file

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting-expected.wav

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичные данные
content/media/webaudio/test/ting.ogg

Двоичный файл не отображается.

Просмотреть файл

@ -3,6 +3,8 @@
# To: /content/canvas/test/reftest
skip-if(xulFennec) include ../../canvas/test/reftest/reftest.list
include ../../base/test/reftest/reftest.list # bug 920877
== bug453105.html bug453105-ref.html
== optiontext.html optiontext-ref.html
== bug456008.xhtml bug456008-ref.html

Просмотреть файл

@ -166,7 +166,7 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
dom::XULElementBinding::GetConstructorObject(cx, global, defineOnGlobal);
}
rv = nsContentUtils::WrapNative(cx, global, aBoundElement, v.address(),
rv = nsContentUtils::WrapNative(cx, global, aBoundElement, &v,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -309,7 +309,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
JS::Rooted<JS::Value> v(cx);
nsresult rv =
nsContentUtils::WrapNative(cx, globalObject, aBoundElement, v.address(),
nsContentUtils::WrapNative(cx, globalObject, aBoundElement, &v,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -307,7 +307,7 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
// scope if one doesn't already exist, and potentially wraps it cross-
// compartment into our scope (via aAllowWrapping=true).
JS::Rooted<JS::Value> targetV(cx, JS::UndefinedValue());
rv = nsContentUtils::WrapNative(cx, scopeObject, scriptTarget, targetV.address(), nullptr,
rv = nsContentUtils::WrapNative(cx, scopeObject, scriptTarget, &targetV, nullptr,
/* aAllowWrapping = */ true);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -1385,7 +1385,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot()
JS::Rooted<JSObject*> scope(jscontext, global->GetGlobalJSObject());
JS::Rooted<JS::Value> v(jscontext);
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
rv = nsContentUtils::WrapNative(jscontext, scope, mRoot, mRoot, v.address(),
rv = nsContentUtils::WrapNative(jscontext, scope, mRoot, mRoot, &v,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
@ -1396,7 +1396,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot()
JS::Rooted<JS::Value> jsdatabase(jscontext);
rv = nsContentUtils::WrapNative(jscontext, scope, mDB,
&NS_GET_IID(nsIRDFCompositeDataSource),
jsdatabase.address(), getter_AddRefs(wrapper));
&jsdatabase, getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
bool ok;
@ -1413,7 +1413,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot()
rv = nsContentUtils::WrapNative(jscontext, jselement,
static_cast<nsIXULTemplateBuilder*>(this),
&NS_GET_IID(nsIXULTemplateBuilder),
jsbuilder.address(), getter_AddRefs(wrapper));
&jsbuilder, getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
bool ok;

Просмотреть файл

@ -347,27 +347,24 @@ WebappsApplication.prototype = {
this._downloadError = null;
this.initDOMRequestHelper(aWindow, [
"Webapps:OfflineCache",
"Webapps:CheckForUpdate:Return:OK",
"Webapps:CheckForUpdate:Return:KO",
"Webapps:PackageEvent",
"Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO",
"Webapps:GetConnections:Return:OK"
"Webapps:FireEvent",
"Webapps:GetConnections:Return:OK",
"Webapps:UpdateState"
]);
cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
{
messages: ["Webapps:OfflineCache",
"Webapps:PackageEvent",
"Webapps:CheckForUpdate:Return:OK"],
app: {
id: this.id,
manifestURL: this.manifestURL,
installState: this.installState,
downloading: this.downloading
}
});
cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
messages: ["Webapps:FireEvent",
"Webapps:UpdateState"],
app: {
id: this.id,
manifestURL: this.manifestURL,
installState: this.installState,
downloading: this.downloading
}
});
},
get manifest() {
@ -378,8 +375,10 @@ WebappsApplication.prototype = {
},
get updateManifest() {
return this.updateManifest = this._updateManifest ? ObjectWrapper.wrap(this._updateManifest, this._window)
: null;
return this.updateManifest =
this._updateManifest ? ObjectWrapper.wrap(this._updateManifest,
this._window)
: null;
},
set onprogress(aCallback) {
@ -512,18 +511,42 @@ WebappsApplication.prototype = {
uninit: function() {
this._onprogress = null;
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
["Webapps:OfflineCache",
"Webapps:PackageEvent",
"Webapps:CheckForUpdate:Return:OK"]);
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages", [
"Webapps:FireEvent",
"Webapps:PackageEvent"
]);
manifestCache.evict(this.manifestURL, this.innerWindowID);
},
_fireEvent: function(aName, aHandler) {
if (aHandler) {
let event = new this._window.MozApplicationEvent(aName, { application: this });
aHandler.handleEvent(event);
_fireEvent: function(aName) {
let handler = this["_on" + aName];
if (handler) {
let event = new this._window.MozApplicationEvent(aName, {
application: this
});
try {
handler.handleEvent(event);
} catch (ex) {
dump("Event handler expection " + ex + "\n");
}
}
},
_updateState: function(aMsg) {
if (aMsg.app) {
for (let prop in aMsg.app) {
this[prop] = aMsg.app[prop];
}
}
if (aMsg.error) {
this._downloadError = aMsg.error;
}
if (aMsg.manifest) {
this._manifest = aMsg.manifest;
manifestCache.evict(this.manifestURL, this.innerWindowID);
}
},
@ -540,10 +563,11 @@ WebappsApplication.prototype = {
// ondownload* callbacks should be triggered on all app instances
if ((msg.oid != this._id || !req) &&
aMessage.name !== "Webapps:OfflineCache" &&
aMessage.name !== "Webapps:PackageEvent" &&
aMessage.name !== "Webapps:CheckForUpdate:Return:OK")
aMessage.name !== "Webapps:FireEvent" &&
aMessage.name !== "Webapps:UpdateState") {
return;
}
switch (aMessage.name) {
case "Webapps:Launch:Return:KO":
this.removeMessageListeners(["Webapps:Launch:Return:OK",
@ -558,108 +582,36 @@ WebappsApplication.prototype = {
case "Webapps:CheckForUpdate:Return:KO":
Services.DOMRequest.fireError(req, msg.error);
break;
case "Webapps:CheckForUpdate:Return:OK":
if (msg.manifestURL != this.manifestURL)
return;
manifestCache.evict(this.manifestURL, this.innerWindowID);
let hiddenProps = ["manifest", "updateManifest"];
let updatableProps = ["installOrigin", "installTime", "installState",
"lastUpdateCheck", "updateTime", "progress", "downloadAvailable",
"downloading", "readyToApplyDownload", "downloadSize"];
// Props that we don't update: origin, receipts, manifestURL, removable.
updatableProps.forEach(function(prop) {
if (msg.app[prop]) {
this[prop] = msg.app[prop];
}
}, this);
hiddenProps.forEach(function(prop) {
if (msg.app[prop]) {
this["_" + prop] = msg.app[prop];
}
}, this);
if (msg.event == "downloadapplied") {
this._fireEvent("downloadapplied", this._ondownloadapplied);
} else if (msg.event == "downloadavailable") {
this._fireEvent("downloadavailable", this._ondownloadavailable);
case "Webapps:FireEvent":
if (msg.manifestURL != this.manifestURL) {
return;
}
// The parent might ask childs to trigger more than one event in one
// shot, so in order to avoid needless IPC we allow an array for the
// 'eventType' IPC message field.
if (!Array.isArray(msg.eventType)) {
msg.eventType = [msg.eventType];
}
msg.eventType.forEach((aEventType) => {
if ("_on" + aEventType in this) {
this._fireEvent(aEventType);
} else {
dump("Unsupported event type " + aEventType + "\n");
}
});
if (req) {
Services.DOMRequest.fireSuccess(req, this.manifestURL);
}
break;
case "Webapps:OfflineCache":
if (msg.manifest != this.manifestURL)
case "Webapps:UpdateState":
if (msg.manifestURL != this.manifestURL) {
return;
if ("installState" in msg) {
this.installState = msg.installState;
this.progress = msg.progress;
if (this.installState == "installed") {
this._downloadError = null;
this.downloading = false;
this.downloadAvailable = false;
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
this._fireEvent("downloadapplied", this._ondownloadapplied);
} else {
this.downloading = true;
this._fireEvent("downloadprogress", this._onprogress);
}
} else if (msg.error) {
this._downloadError = msg.error;
this.downloading = false;
this._fireEvent("downloaderror", this._ondownloaderror);
}
break;
case "Webapps:PackageEvent":
if (msg.manifestURL != this.manifestURL)
return;
// Set app values according to parent process results.
let app = msg.app;
this.downloading = app.downloading;
this.downloadAvailable = app.downloadAvailable;
this.downloadSize = app.downloadSize || 0;
this.installState = app.installState;
this.progress = app.progress || msg.progress || 0;
this.readyToApplyDownload = app.readyToApplyDownload;
this.updateTime = app.updateTime;
this.origin = app.origin;
switch(msg.type) {
case "error":
case "canceled":
this._downloadError = msg.error;
this._fireEvent("downloaderror", this._ondownloaderror);
break;
case "progress":
this._fireEvent("downloadprogress", this._onprogress);
break;
case "installed":
manifestCache.evict(this.manifestURL, this.innerWindowID);
this._manifest = msg.manifest;
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
this._fireEvent("downloadapplied", this._ondownloadapplied);
break;
case "downloaded":
// We don't update the packaged apps manifests until they
// are installed or until the update is unstaged.
if (msg.manifest) {
manifestCache.evict(this.manifestURL, this.innerWindowID);
this._manifest = msg.manifest;
}
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
break;
case "applied":
manifestCache.evict(this.manifestURL, this.innerWindowID);
this._manifest = msg.manifest;
this._fireEvent("downloadapplied", this._ondownloadapplied);
break;
}
this._updateState(msg);
break;
case "Webapps:ClearBrowserData:Return":
this.removeMessageListeners(aMessage.name);
@ -667,10 +619,10 @@ WebappsApplication.prototype = {
break;
case "Webapps:Connect:Return:OK":
let messagePorts = [];
msg.messagePortIDs.forEach(function(aPortID) {
msg.messagePortIDs.forEach((aPortID) => {
let port = new this._window.MozInterAppMessagePort(aPortID);
messagePorts.push(port);
}, this);
});
req.resolve(messagePorts);
break;
case "Webapps:Connect:Return:KO":
@ -678,13 +630,13 @@ WebappsApplication.prototype = {
break;
case "Webapps:GetConnections:Return:OK":
let connections = [];
msg.connections.forEach(function(aConnection) {
msg.connections.forEach((aConnection) => {
let connection =
new this._window.MozInterAppConnection(aConnection.keyword,
aConnection.pubAppManifestURL,
aConnection.subAppManifestURL);
connections.push(connection);
}, this);
});
req.resolve(connections);
break;
}

Просмотреть файл

@ -43,7 +43,7 @@ function supportSystemMessages() {
}
// Minimum delay between two progress events while downloading, in ms.
const MIN_PROGRESS_EVENT_DELAY = 1000;
const MIN_PROGRESS_EVENT_DELAY = 1500;
const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
@ -945,8 +945,6 @@ this.DOMApplicationRegistry = {
addMessageListener: function(aMsgNames, aApp, aMm) {
aMsgNames.forEach(function (aMsgName) {
let man = aApp && aApp.manifestURL;
debug("Adding messageListener for: " + aMsgName + "App: " +
man);
if (!(aMsgName in this.children)) {
this.children[aMsgName] = [];
}
@ -966,8 +964,8 @@ this.DOMApplicationRegistry = {
});
// If it wasn't registered before, let's update its state
if ((aMsgName === 'Webapps:PackageEvent') ||
(aMsgName === 'Webapps:OfflineCache')) {
if ((aMsgName === 'Webapps:FireEvent') ||
(aMsgName === 'Webapps:UpdateState')) {
if (man) {
let app = this.getAppByManifestURL(aApp.manifestURL);
if (app && ((aApp.installState !== app.installState) ||
@ -1124,9 +1122,9 @@ this.DOMApplicationRegistry = {
// Webapps:Install:Return:OK
// Webapps:Uninstall:Return:OK
// Webapps:Uninstall:Broadcast:Return:OK
// Webapps:OfflineCache
// Webapps:FireEvent
// Webapps:checkForUpdate:Return:OK
// Webapps:PackageEvent
// Webapps:UpdateState
broadcastMessage: function broadcastMessage(aMsgName, aContent) {
if (!(aMsgName in this.children)) {
return;
@ -1140,7 +1138,7 @@ this.DOMApplicationRegistry = {
return FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
},
_writeFile: function ss_writeFile(aFile, aData, aCallbak) {
_writeFile: function _writeFile(aFile, aData, aCallback) {
debug("Saving " + aFile.path);
// Initialize the file output stream.
let ostream = FileUtils.openSafeFileOutputStream(aFile);
@ -1153,8 +1151,9 @@ this.DOMApplicationRegistry = {
// Asynchronously copy the data to the file.
let istream = converter.convertToInputStream(aData);
NetUtil.asyncCopy(istream, ostream, function(rc) {
if (aCallbak)
aCallbak();
if (aCallback) {
aCallback();
}
});
},
@ -1216,22 +1215,15 @@ this.DOMApplicationRegistry = {
let app = this.webapps[download.appId];
if (download.cacheUpdate) {
// Cancel hosted app download.
app.isCanceling = true;
try {
download.cacheUpdate.cancel();
} catch (e) {
delete app.isCanceling;
debug (e);
}
} else if (download.channel) {
// Cancel packaged app download.
app.isCanceling = true;
try {
download.channel.cancel(Cr.NS_BINDING_ABORTED);
} catch(e) {
delete app.isCanceling;
}
} catch(e) { }
} else {
return;
}
@ -1241,11 +1233,19 @@ this.DOMApplicationRegistry = {
app.installState = download.previousState;
app.downloading = false;
this._saveApps((function() {
this.broadcastMessage("Webapps:PackageEvent",
{ type: "canceled",
manifestURL: app.manifestURL,
app: app,
error: error });
this.broadcastMessage("Webapps:UpdateState", {
app: {
progress: 0,
installState: download.previousState,
downloading: false
},
error: error,
manifestURL: app.manifestURL,
})
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
manifestURL: app.manifestURL
});
}).bind(this));
AppDownloadManager.remove(aManifestURL);
},
@ -1267,11 +1267,14 @@ this.DOMApplicationRegistry = {
// If the caller is trying to start a download but we have nothing to
// download, send an error.
if (!app.downloadAvailable) {
this.broadcastMessage("Webapps:PackageEvent",
{ type: "canceled",
manifestURL: app.manifestURL,
app: app,
error: "NO_DOWNLOAD_AVAILABLE" });
this.broadcastMessage("Webapps:UpdateState", {
error: "NO_DOWNLOAD_AVAILABLE",
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
manifestURL: app.manifestURL
});
return;
}
@ -1303,16 +1306,21 @@ this.DOMApplicationRegistry = {
debug("appcache found");
this.startOfflineCacheDownload(manifest, app, null, isUpdate);
} else {
// hosted app with no appcache, nothing to do, but we fire a
// downloaded event
// Hosted app with no appcache, nothing to do, but we fire a
// downloaded event.
debug("No appcache found, sending 'downloaded' for " + aManifestURL);
app.downloadAvailable = false;
DOMApplicationRegistry.broadcastMessage("Webapps:PackageEvent",
{ type: "downloaded",
manifestURL: aManifestURL,
app: app,
manifest: jsonManifest });
DOMApplicationRegistry._saveApps();
DOMApplicationRegistry._saveApps(function() {
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: jsonManifest,
manifestURL: aManifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadsuccess",
manifestURL: aManifestURL
});
});
}
}).bind(this));
@ -1321,7 +1329,8 @@ this.DOMApplicationRegistry = {
this._loadJSONAsync(file, (function(aJSON) {
if (!aJSON) {
debug("startDownload: No update manifest found at " + file.path + " " + aManifestURL);
debug("startDownload: No update manifest found at " + file.path + " " +
aManifestURL);
return;
}
@ -1350,11 +1359,14 @@ this.DOMApplicationRegistry = {
app.readyToApplyDownload = true;
app.updateTime = Date.now();
DOMApplicationRegistry._saveApps(function() {
debug("About to fire Webapps:PackageEvent");
DOMApplicationRegistry.broadcastMessage("Webapps:PackageEvent",
{ type: "downloaded",
manifestURL: aManifestURL,
app: app });
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: aManifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadsuccess",
manifestURL: aManifestURL
});
if (app.installState == "pending") {
// We restarted a failed download, apply it automatically.
DOMApplicationRegistry.applyDownload(aManifestURL);
@ -1442,11 +1454,15 @@ this.DOMApplicationRegistry = {
}
this.updateDataStore(this.webapps[id].localId, app.origin,
app.manifestURL, aData);
this.broadcastMessage("Webapps:PackageEvent",
{ type: "applied",
manifestURL: app.manifestURL,
app: app,
manifest: aData });
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: aData,
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
manifestURL: app.manifestURL
});
}).bind(this));
}).bind(this));
}).bind(this));
@ -1475,6 +1491,14 @@ this.DOMApplicationRegistry = {
aApp.downloading = true;
aApp.progress = 0;
DOMApplicationRegistry._saveApps((function() {
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: {
downloading: true,
installState: aApp.installState,
progress: 0
},
manifestURL: aApp.manifestURL
});
let cacheUpdate = aProfileDir
? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir)
: updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false);
@ -1598,16 +1622,17 @@ this.DOMApplicationRegistry = {
// event.
app.downloadAvailable = true;
app.downloadSize = manifest.size;
aData.event = "downloadavailable";
aData.app = {
downloadAvailable: true,
downloadSize: manifest.size,
updateManifest: aManifest
}
app.updateManifest = aManifest;
DOMApplicationRegistry._saveApps(function() {
DOMApplicationRegistry.broadcastMessage("Webapps:CheckForUpdate:Return:OK",
aData);
delete aData.app.updateManifest;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadavailable",
manifestURL: app.manifestURL,
requestID: aData.requestID
});
});
}
@ -1662,10 +1687,17 @@ this.DOMApplicationRegistry = {
this.webapps[id] = app;
this._saveApps(function() {
let reg = DOMApplicationRegistry;
aData.app = app;
if (!manifest.appcache_path) {
aData.event = "downloadapplied";
reg.broadcastMessage("Webapps:CheckForUpdate:Return:OK", aData);
reg.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: app.manifest,
manifestURL: app.manifestURL
});
reg.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
manifestURL: app.manifestURL,
requestID: aData.requestID
});
} else {
// Check if the appcache is updatable, and send "downloadavailable" or
// "downloadapplied".
@ -1673,14 +1705,24 @@ this.DOMApplicationRegistry = {
observe: function(aSubject, aTopic, aObsData) {
debug("updateHostedApp: updateSvc.checkForUpdate return for " +
app.manifestURL + " - event is " + aTopic);
aData.event =
let eventType =
aTopic == "offline-cache-update-available" ? "downloadavailable"
: "downloadapplied";
aData.app.downloadAvailable = (aData.event == "downloadavailable");
reg._saveApps();
reg.broadcastMessage("Webapps:CheckForUpdate:Return:OK", aData);
app.downloadAvailable = (eventType == "downloadavailable");
reg._saveApps(function() {
reg.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: app.manifest,
manifestURL: app.manifestURL
});
reg.broadcastMessage("Webapps:FireEvent", {
eventType: eventType,
manifestURL: app.manifestURL,
requestID: aData.requestID
});
});
}
}
};
debug("updateHostedApp: updateSvc.checkForUpdate for " +
manifest.fullAppcachePath());
updateSvc.checkForUpdate(Services.io.newURI(manifest.fullAppcachePath(), null, null),
@ -1715,8 +1757,8 @@ this.DOMApplicationRegistry = {
let onlyCheckAppCache = false;
#ifdef MOZ_WIDGET_GONK
let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
onlyCheckAppCache = (app.basePath == appDir.path);
let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
onlyCheckAppCache = (app.basePath == appDir.path);
#endif
if (onlyCheckAppCache) {
@ -1744,19 +1786,24 @@ this.DOMApplicationRegistry = {
debug("onlyCheckAppCache updateSvc.checkForUpdate return for " +
app.manifestURL + " - event is " + aTopic);
if (aTopic == "offline-cache-update-available") {
aData.event = "downloadavailable";
app.downloadAvailable = true;
aData.app = app;
this._saveApps(function() {
DOMApplicationRegistry.broadcastMessage(
"Webapps:CheckForUpdate:Return:OK", aData);
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadavailable",
manifestURL: app.manifestURL,
requestID: aData.requestID
});
});
} else {
aData.error = "NOT_UPDATABLE";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
}
}
}
};
let helper = new ManifestHelper(manifest);
debug("onlyCheckAppCache - launch updateSvc.checkForUpdate for " +
helper.fullAppcachePath());
@ -1806,15 +1853,21 @@ this.DOMApplicationRegistry = {
if (oldHash != hash) {
updatePackagedApp.call(this, manifest);
} else {
// Like if we got a 304, just send a 'downloadapplied'
// or downloadavailable event.
aData.event = app.downloadAvailable ? "downloadavailable"
: "downloadapplied";
aData.app = {
lastCheckedUpdate: app.lastCheckedUpdate
}
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:OK", aData);
this._saveApps();
this._saveApps(function() {
// Like if we got a 304, just send a 'downloadapplied'
// or downloadavailable event.
let eventType = app.downloadAvailable ? "downloadavailable"
: "downloadapplied";
aMm.sendAsyncMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
aMm.sendAsyncMessage("Webapps:FireEvent", {
eventType: eventType,
manifestURL: app.manifestURL,
requestID: aData.requestID
});
});
}
} else {
// Update only the appcache if the manifest has not changed
@ -1826,16 +1879,22 @@ this.DOMApplicationRegistry = {
} else if (xhr.status == 304) {
// The manifest has not changed.
if (isPackage) {
// If the app is a packaged app, we just send a 'downloadapplied'
// or downloadavailable event.
app.lastCheckedUpdate = Date.now();
aData.event = app.downloadAvailable ? "downloadavailable"
: "downloadapplied";
aData.app = {
lastCheckedUpdate: app.lastCheckedUpdate
}
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:OK", aData);
this._saveApps();
this._saveApps(function() {
// If the app is a packaged app, we just send a 'downloadapplied'
// or downloadavailable event.
let eventType = app.downloadAvailable ? "downloadavailable"
: "downloadapplied";
aMm.sendAsyncMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
aMm.sendAsyncMessage("Webapps:FireEvent", {
eventType: eventType,
manifestURL: app.manifestURL,
requestID: aData.requestID
});
});
} else {
// For hosted apps, even if the manifest has not changed, we check
// for offline cache updates.
@ -2146,21 +2205,25 @@ this.DOMApplicationRegistry = {
if (supportUseCurrentProfile()) {
// Update the permissions for this app.
PermissionsInstaller.installPermissions({ manifest: aManifest,
origin: appObject.origin,
manifestURL: appObject.manifestURL },
true);
PermissionsInstaller.installPermissions({
manifest: aManifest,
origin: appObject.origin,
manifestURL: appObject.manifestURL
}, true);
}
this.updateDataStore(this.webapps[aId].localId, appObject.origin,
appObject.manifestURL, aManifest);
debug("About to fire Webapps:PackageEvent 'installed'");
this.broadcastMessage("Webapps:PackageEvent",
{ type: "installed",
manifestURL: appObject.manifestURL,
app: app,
manifest: aManifest });
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: aManifest,
manifestURL: appObject.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: ["downloadsuccess", "downloadapplied"],
manifestURL: appObject.manifestURL
});
if (installSuccessCallback) {
installSuccessCallback(aManifest, zipFile.path);
}
@ -2426,14 +2489,6 @@ this.DOMApplicationRegistry = {
dir.remove(true);
} catch (e) { }
// We avoid notifying the error to the DOM side if the app download
// was cancelled via cancelDownload, which already sends its own
// notification.
if (app.isCanceling) {
delete app.isCanceling;
return;
}
let download = AppDownloadManager.get(aApp.manifestURL);
app.downloading = false;
@ -2449,20 +2504,31 @@ this.DOMApplicationRegistry = {
delete app.staged;
}
self.broadcastMessage("Webapps:PackageEvent",
{ type: "error",
manifestURL: aApp.manifestURL,
error: aError,
app: app });
self._saveApps();
self._saveApps(function() {
self.broadcastMessage("Webapps:UpdateState", {
app: app,
error: aError,
manifestURL: aApp.manifestURL
});
self.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
manifestURL: aApp.manifestURL
});
});
AppDownloadManager.remove(aApp.manifestURL);
}
function sendProgressEvent() {
self.broadcastMessage("Webapps:PackageEvent",
{ type: "progress",
manifestURL: aApp.manifestURL,
app: app });
function sendProgressEvent(aProgress) {
self.broadcastMessage("Webapps:UpdateState", {
app: {
progress: aProgress
},
manifestURL: aApp.manifestURL
});
self.broadcastMessage("Webapps:FireEvent", {
eventType: "progress",
manifestURL: aApp.manifestURL
});
}
// aStoreId must be a string of the form
@ -2548,7 +2614,7 @@ this.DOMApplicationRegistry = {
let now = Date.now();
if (now - lastProgressTime > MIN_PROGRESS_EVENT_DELAY) {
debug("onProgress: " + aProgress + "/" + aProgressMax);
sendProgressEvent();
sendProgressEvent(aProgress);
lastProgressTime = now;
self._saveApps();
}
@ -2646,16 +2712,17 @@ this.DOMApplicationRegistry = {
OS.Path.join(dirPath, "update.webapp"));
}
self.broadcastMessage("Webapps:PackageEvent", {
type: "downloaded",
manifestURL: aApp.manifestURL,
app: app });
self.broadcastMessage("Webapps:PackageEvent", {
type: "applied",
manifestURL: aApp.manifestURL,
app: app });
// Save the updated registry, and cleanup the tmp directory.
self._saveApps();
self._saveApps(function() {
self.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: aApp.manifestURL
});
self.broadcastMessage("Webapps:FireEvent", {
manifestURL: aApp.manifestURL,
eventType: ["downloadsuccess", "downloadapplied"]
});
});
let file = FileUtils.getFile("TmpD", ["webapps", id], false);
if (file && file.exists()) {
file.remove(true);
@ -2907,7 +2974,7 @@ this.DOMApplicationRegistry = {
requestChannel.asyncOpen(listener, null);
// send a first progress event to correctly set the DOM object's properties
sendProgressEvent();
sendProgressEvent(0);
};
let checkDownloadSize = function (freeBytes) {
@ -3305,7 +3372,7 @@ let AppcacheObserver = function(aApp) {
this.app = aApp;
this.startStatus = aApp.installState;
this.lastProgressTime = 0;
// send a first progress event to correctly set the DOM object's properties
// Send a first progress event to correctly set the DOM object's properties.
this._sendProgressEvent();
};
@ -3313,10 +3380,14 @@ AppcacheObserver.prototype = {
// nsIOfflineCacheUpdateObserver implementation
_sendProgressEvent: function() {
let app = this.app;
DOMApplicationRegistry.broadcastMessage("Webapps:OfflineCache",
{ manifest: app.manifestURL,
installState: app.installState,
progress: app.progress });
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "progress",
manifestURL: app.manifestURL
});
},
updateStateChanged: function appObs_Update(aUpdate, aState) {
@ -3328,31 +3399,41 @@ AppcacheObserver.prototype = {
var self = this;
let setStatus = function appObs_setStatus(aStatus, aProgress) {
debug("Offlinecache setStatus to " + aStatus + " with progress " +
aProgress + " for " + app.origin);
aProgress + " for " + app.origin);
mustSave = (app.installState != aStatus);
app.installState = aStatus;
app.progress = aProgress;
if (aStatus == "installed") {
app.updateTime = Date.now();
app.downloading = false;
app.downloadAvailable = false;
if (aStatus != "installed") {
self._sendProgressEvent();
return;
}
self._sendProgressEvent();
app.updateTime = Date.now();
app.downloading = false;
app.downloadAvailable = false;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: ["downloadsuccess", "downloadapplied"],
manifestURL: app.manifestURL
});
}
let setError = function appObs_setError(aError) {
debug("Offlinecache setError to " + aError);
// If we are canceling the download, we already send a DOWNLOAD_CANCELED
// error.
if (!app.isCanceling) {
DOMApplicationRegistry.broadcastMessage("Webapps:OfflineCache",
{ manifest: app.manifestURL,
error: aError });
} else {
delete app.isCanceling;
}
app.downloading = false;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
error: aError,
eventType: "downloaderror",
manifestURL: app.manifestURL
});
mustSave = true;
}
@ -3369,9 +3450,9 @@ AppcacheObserver.prototype = {
setStatus("installed", aUpdate.byteProgress);
break;
case Ci.nsIOfflineCacheUpdateObserver.STATE_DOWNLOADING:
case Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED:
setStatus(this.startStatus, aUpdate.byteProgress);
break;
case Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED:
case Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMPROGRESS:
let now = Date.now();
if (now - this.lastProgressTime > MIN_PROGRESS_EVENT_DELAY) {

Просмотреть файл

@ -159,7 +159,7 @@ var steps = [
},
function() {
ok(true, "== TEST == Update packaged app - same package");
updateApp(false, 3, 4);
updateApp(false, 3, 3);
},
function() {
ok(true, "== TEST == Check for Update after getting the same package");

Просмотреть файл

@ -123,7 +123,7 @@ PostMessageReadStructuredClone(JSContext* cx,
JS::Rooted<JS::Value> val(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports,
val.address(),
&val,
getter_AddRefs(wrapper)))) {
return JSVAL_TO_OBJECT(val);
}

Просмотреть файл

@ -1589,7 +1589,7 @@ Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsContentUtils::WrapNative(aCx, aObject, native, prop_val.address(),
rv = nsContentUtils::WrapNative(aCx, aObject, native, &prop_val,
getter_AddRefs(holder), true);
if (NS_FAILED(rv)) {
@ -1716,8 +1716,13 @@ Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
bool
Navigator::HasTelephonySupport(JSContext* /* unused */, JSObject* aGlobal)
{
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.telephony.enabled", &enabled);
NS_ENSURE_TRUE(enabled, false);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && Telephony::CheckPermission(win);
return win && CheckPermission(win, "telephony");
}
/* static */
@ -1725,6 +1730,11 @@ bool
Navigator::HasMobileConnectionSupport(JSContext* /* unused */,
JSObject* aGlobal)
{
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.mobileconnection.enabled", &enabled);
NS_ENSURE_TRUE(enabled, false);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && (CheckPermission(win, "mobileconnection") ||
CheckPermission(win, "mobilenetwork"));
@ -1735,6 +1745,11 @@ bool
Navigator::HasCellBroadcastSupport(JSContext* /* unused */,
JSObject* aGlobal)
{
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.cellbroadcast.enabled", &enabled);
NS_ENSURE_TRUE(enabled, false);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && CheckPermission(win, "cellbroadcast");
}
@ -1744,6 +1759,11 @@ bool
Navigator::HasVoicemailSupport(JSContext* /* unused */,
JSObject* aGlobal)
{
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.voicemail.enabled", &enabled);
NS_ENSURE_TRUE(enabled, false);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && CheckPermission(win, "voicemail");
}
@ -1753,6 +1773,11 @@ bool
Navigator::HasIccManagerSupport(JSContext* /* unused */,
JSObject* aGlobal)
{
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.icc.enabled", &enabled);
NS_ENSURE_TRUE(enabled, false);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && CheckPermission(win, "mobileconnection");
}

Просмотреть файл

@ -643,13 +643,13 @@ IdToString(JSContext *cx, jsid id)
static inline nsresult
WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
nsWrapperCache *cache, const nsIID* aIID, jsval *vp,
nsWrapperCache *cache, const nsIID* aIID, JS::MutableHandle<JS::Value> vp,
nsIXPConnectJSObjectHolder** aHolder, bool aAllowWrapping)
{
if (!native) {
NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
*vp = JSVAL_NULL;
vp.setNull();
return NS_OK;
}
@ -661,13 +661,13 @@ WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
return nsDOMClassInfo::XPConnect()->WrapNativeToJSVal(cx, scope, native,
cache, aIID,
aAllowWrapping, vp,
aAllowWrapping, vp.address(),
aHolder);
}
static inline nsresult
WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
const nsIID* aIID, bool aAllowWrapping, jsval *vp,
const nsIID* aIID, bool aAllowWrapping, JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr)
@ -679,7 +679,7 @@ WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
// Same as the WrapNative above, but use these if aIID is nsISupports' IID.
static inline nsresult
WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
bool aAllowWrapping, jsval *vp,
bool aAllowWrapping, JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr)
@ -690,7 +690,8 @@ WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
static inline nsresult
WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
nsWrapperCache *cache, bool aAllowWrapping, jsval *vp,
nsWrapperCache *cache, bool aAllowWrapping,
JS::MutableHandle<JS::Value> vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nullptr)
@ -2221,26 +2222,25 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
// wrap parameters in the target compartment
// we also pass in the calling window as the first argument
unsigned argc = args.length() + 1;
nsAutoArrayPtr<JS::Value> argv(new JS::Value[argc]);
JS::AutoArrayRooter rooter(cx, 0, argv);
JS::AutoValueVector argv(cx);
argv.resize(argc);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
rv = WrapNative(cx, obj, currentWin, &NS_GET_IID(nsIDOMWindow),
true, &argv[0], getter_AddRefs(holder));
true, argv.handleAt(0), getter_AddRefs(holder));
if (!JS_WrapValue(cx, &argv[0]))
return NS_ERROR_FAILURE;
rooter.changeLength(1);
for (size_t i = 1; i < argc; ++i) {
argv[i] = args[i - 1];
if (!JS_WrapValue(cx, &argv[i]))
return NS_ERROR_FAILURE;
rooter.changeLength(i + 1);
}
JS::Rooted<JS::Value> frval(cx);
bool ret = JS_CallFunctionValue(cx, thisObject, funval, argc, argv,
bool ret = JS_CallFunctionValue(cx, thisObject, funval,
argc, argv.begin(),
frval.address());
if (!ret) {
@ -2250,7 +2250,7 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
}
}
return WrapNative(cx, obj, native, true, args.rval().address());
return WrapNative(cx, obj, native, true, args.rval());
}
static nsresult
@ -2818,7 +2818,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, v.address(), getter_AddRefs(holder));
false, &v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
if (install) {
@ -3100,7 +3100,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, v.address(), getter_AddRefs(holder));
false, &v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = constructor->Install(cx, obj, v);
@ -3202,7 +3202,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
JS::Rooted<JS::Value> val(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, val.address(), getter_AddRefs(holder));
false, &val, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = constructor->Install(cx, obj, val);
@ -3251,7 +3251,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
scope = aWin->GetGlobalJSObject();
}
rv = WrapNative(cx, scope, native, true, prop_val.address(),
rv = WrapNative(cx, scope, native, true, &prop_val,
getter_AddRefs(holder));
}
@ -3303,7 +3303,7 @@ ContentWindowGetter(JSContext *cx, unsigned argc, jsval *vp)
template<class Interface>
static nsresult
LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
LocationSetterGuts(JSContext *cx, JSObject *obj, JS::MutableHandle<JS::Value> vp)
{
// This function duplicates some of the logic in XPC_WN_HelperSetProperty
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
@ -3322,7 +3322,7 @@ LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
NS_ENSURE_SUCCESS(rv, rv);
// Grab the value we're being set to before we stomp on |vp|
JS::Rooted<JSString*> val(cx, ::JS_ValueToString(cx, *vp));
JS::Rooted<JSString*> val(cx, ::JS_ValueToString(cx, vp));
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
// Make sure |val| stays alive below
@ -3352,7 +3352,7 @@ static bool
LocationSetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
JS::MutableHandle<JS::Value> vp)
{
nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp.address());
nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return false;
@ -3365,7 +3365,7 @@ static bool
LocationSetterUnwrapper(JSContext *cx, JS::Handle<JSObject*> obj_, JS::Handle<jsid> id,
bool strict, JS::MutableHandle<JS::Value> vp)
{
JS::RootedObject obj(cx, obj_);
JS::Rooted<JSObject*> obj(cx, obj_);
JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
if (wrapped) {
@ -3410,7 +3410,7 @@ const InterfaceShimEntry kInterfaceShimMap[] =
{ "nsIDOMXPathResult", "XPathResult" } };
static nsresult
DefineComponentsShim(JSContext *cx, JS::HandleObject global, nsPIDOMWindow *win)
DefineComponentsShim(JSContext *cx, JS::Handle<JSObject*> global, nsPIDOMWindow *win)
{
// Keep track of how often this happens.
Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
@ -3468,7 +3468,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj_, jsid id_, uint32_t flags,
JSObject **objp, bool *_retval)
{
JS::RootedObject obj(cx, obj_);
JS::Rooted<JSObject*> obj(cx, obj_);
JS::RootedId id(cx, id_);
if (!JSID_IS_STRING(id)) {
@ -3565,7 +3565,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), true,
v.address(), getter_AddRefs(holder));
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
bool ok = JS_WrapValue(cx, v.address()) &&
@ -3590,7 +3590,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, top, &NS_GET_IID(nsIDOMWindow), true,
v.address(), getter_AddRefs(holder));
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Hold on to the top window object as a global property so we
@ -3606,7 +3606,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
// Handle resolving if id refers to a name resolved by DOM worker code.
JS::RootedObject tmp(cx, NULL);
JS::Rooted<JSObject*> tmp(cx, NULL);
if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
return NS_ERROR_FAILURE;
}
@ -3679,7 +3679,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), document, document,
&NS_GET_IID(nsIDOMDocument), v.address(), getter_AddRefs(holder),
&NS_GET_IID(nsIDOMDocument), &v, getter_AddRefs(holder),
false);
NS_ENSURE_SUCCESS(rv, rv);
@ -3986,9 +3986,11 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
if (array_item) {
JS::Rooted<JS::Value> rval(cx);
rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), array_item, cache,
true, vp);
true, &rval);
NS_ENSURE_SUCCESS(rv, rv);
*vp = rval;
rv = NS_SUCCESS_I_DID_SOMETHING;
}
@ -4085,7 +4087,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult tmp = WrapNative(cx, JS::CurrentGlobalOrNull(cx),
static_cast<nsINodeList*>(list), list, false,
collection.address(), getter_AddRefs(holder));
&collection, getter_AddRefs(holder));
if (NS_FAILED(tmp)) {
rv = tmp;
}
@ -4189,7 +4191,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JS::Handle<JSObject*> ob
}
if (result) {
rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), result, cache, true, vp.address());
rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), result, cache, true, vp);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
@ -4207,7 +4209,7 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JS::Handle<JSObject*> obj
JS::Handle<jsid> id, unsigned flags,
JS::MutableHandle<JSObject*> objp)
{
JS::RootedValue v(cx);
JS::Rooted<JS::Value> v(cx);
if (nsDOMClassInfo::sItem_id == id || nsDOMClassInfo::sNamedItem_id == id) {
// Define the item() or namedItem() method.
@ -4326,8 +4328,10 @@ nsStringArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_SUCCESS_I_DID_SOMETHING;
}
NS_ENSURE_TRUE(xpc::NonVoidStringToJsval(cx, val, vp),
JS::Rooted<JS::Value> rval(cx);
NS_ENSURE_TRUE(xpc::NonVoidStringToJsval(cx, val, &rval),
NS_ERROR_OUT_OF_MEMORY);
*vp = rval;
return NS_SUCCESS_I_DID_SOMETHING;
}

Просмотреть файл

@ -2385,8 +2385,9 @@ nsDOMWindowUtils::GetIsTestControllingRefreshes(bool *aResult)
return NS_ERROR_DOM_SECURITY_ERR;
}
nsPresContext* pc = GetPresContext();
*aResult =
GetPresContext()->RefreshDriver()->IsTestControllingRefreshesEnabled();
pc ? pc->RefreshDriver()->IsTestControllingRefreshesEnabled() : false;
return NS_OK;
}

Просмотреть файл

@ -3632,8 +3632,11 @@ nsGlobalWindow::GetScriptableContent(JSContext* aCx, JS::Value* aVal)
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
if (content && global) {
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
return nsContentUtils::WrapNative(aCx, global, content, aVal,
getter_AddRefs(wrapper));
JS::Rooted<JS::Value> rval(aCx);
nsresult rv = nsContentUtils::WrapNative(aCx, global, content, &rval,
getter_AddRefs(wrapper));
*aVal = rval;
return rv;
}
return NS_ERROR_FAILURE;
}
@ -6806,9 +6809,9 @@ PostMessageReadStructuredClone(JSContext* cx,
JS::Rooted<JS::Value> val(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports,
val.address(),
&val,
getter_AddRefs(wrapper)))) {
return JSVAL_TO_OBJECT(val);
return val.toObjectOrNull();
}
}
}

Просмотреть файл

@ -1035,23 +1035,21 @@ nsJSContext::JSObjectFromInterface(nsISupports* aTarget,
// We don't wrap here because we trust the JS engine to wrap the target
// later.
JS::Rooted<JS::Value> v(cx);
nsresult rv = nsContentUtils::WrapNative(cx, aScope, aTarget,
v.address());
nsresult rv = nsContentUtils::WrapNative(cx, aScope, aTarget, &v);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
nsCOMPtr<nsISupports> native =
nsContentUtils::XPConnect()->GetNativeOfWrapper(cx,
JSVAL_TO_OBJECT(v));
NS_ASSERTION(native == targetSupp, "Native should be the target!");
#endif
JSObject* obj = v.toObjectOrNull();
if (obj) {
JS::ExposeObjectToActiveJS(obj);
}
#ifdef DEBUG
nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
nsCOMPtr<nsISupports> native =
nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, obj);
NS_ASSERTION(native == targetSupp, "Native should be the target!");
#endif
*aRet = obj;
return NS_OK;
}
@ -1298,7 +1296,7 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
#endif
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
JS::Rooted<JS::Value> v(cx);
rv = nsContentUtils::WrapNative(cx, aScope, arg, v.address(),
rv = nsContentUtils::WrapNative(cx, aScope, arg, &v,
getter_AddRefs(wrapper));
if (NS_SUCCEEDED(rv)) {
*thisval = v;
@ -1500,7 +1498,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv)
JS::Rooted<JSObject*> global(cx, GetWindowProxy());
JS::Rooted<JS::Value> v(cx);
nsresult rv = nsContentUtils::WrapNative(cx, global,
data, iid, v.address(),
data, iid, &v,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -320,13 +320,13 @@ enum {
TOSTRING_NAME_RESERVED_SLOT = 1
};
bool
static bool
InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
{
JS::Rooted<JSObject*> callee(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> callee(cx, &args.callee());
JS::Rooted<JSObject*> obj(cx, JS_THIS_OBJECT(cx, vp));
if (!obj) {
if (!args.computeThis(cx).isObject()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
"null", "object");
return false;
@ -334,14 +334,14 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
JS::Value v = js::GetFunctionNativeReserved(callee,
TOSTRING_CLASS_RESERVED_SLOT);
const JSClass* clasp = static_cast<const JSClass*>(JSVAL_TO_PRIVATE(v));
const JSClass* clasp = static_cast<const JSClass*>(v.toPrivate());
v = js::GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
JSString* jsname = static_cast<JSString*>(JSVAL_TO_STRING(v));
size_t length;
const jschar* name = JS_GetInternedStringCharsAndLength(jsname, &length);
if (js::GetObjectJSClass(obj) != clasp) {
if (js::GetObjectJSClass(&args.computeThis(cx).toObject()) != clasp) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
NS_ConvertUTF16toUTF8(name).get(), "toString",
"object");
@ -357,7 +357,7 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
str.Append('\n');
str.AppendLiteral("}");
return xpc::NonVoidStringToJsval(cx, str, vp);
return xpc::NonVoidStringToJsval(cx, str, args.rval());
}
bool
@ -673,7 +673,7 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
bool
NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
JS::Handle<JSObject*> aScope,
JS::Value* aRetval,
JS::MutableHandle<JS::Value> aRetval,
xpcObjectHelper& aHelper,
const nsIID* aIID,
bool aAllowNativeWrapper)
@ -684,7 +684,7 @@ NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
nsWrapperCache *cache = aHelper.GetWrapperCache();
if (cache && cache->IsDOMBinding()) {
JS::RootedObject obj(aCx, cache->GetWrapper());
JS::Rooted<JSObject*> obj(aCx, cache->GetWrapper());
if (!obj) {
obj = cache->WrapObject(aCx, aScope);
}
@ -694,7 +694,7 @@ NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
}
if (obj) {
*aRetval = JS::ObjectValue(*obj);
aRetval.setObject(*obj);
return true;
}
}
@ -751,7 +751,7 @@ InstanceClassHasProtoAtDepth(JS::Handle<JSObject*> protoObject, uint32_t protoID
bool
XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
xpcObjectHelper& helper, const nsIID* iid,
bool allowNativeWrapper, JS::Value* rval)
bool allowNativeWrapper, JS::MutableHandle<JS::Value> rval)
{
if (!NativeInterface2JSObjectAndThrowIfFailed(cx, scope, rval, helper, iid,
allowNativeWrapper)) {
@ -759,7 +759,7 @@ XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
}
#ifdef DEBUG
JSObject* jsobj = JSVAL_TO_OBJECT(*rval);
JSObject* jsobj = rval.toObjectOrNull();
if (jsobj && !js::GetObjectParent(jsobj))
NS_ASSERTION(js::GetObjectClass(jsobj)->flags & JSCLASS_IS_GLOBAL,
"Why did we recreate this wrapper?");
@ -770,7 +770,7 @@ XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
bool
VariantToJsval(JSContext* aCx, JS::Handle<JSObject*> aScope,
nsIVariant* aVariant, JS::Value* aRetval)
nsIVariant* aVariant, JS::MutableHandle<JS::Value> aRetval)
{
nsresult rv;
if (!XPCVariant::VariantDataToJS(aVariant, &rv, aRetval)) {
@ -810,15 +810,14 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
return Throw(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
}
JS::Value* argv = JS_ARGV(cx, vp);
if (!argv[0].isObject()) {
if (!args[0].isObject()) {
return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
}
nsIJSID* iid;
SelfRef iidRef;
if (NS_FAILED(xpc_qsUnwrapArg<nsIJSID>(cx, argv[0], &iid, &iidRef.ptr,
&argv[0]))) {
if (NS_FAILED(xpc_qsUnwrapArg<nsIJSID>(cx, args[0], &iid, &iidRef.ptr,
args[0]))) {
return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
}
MOZ_ASSERT(iid);
@ -1475,7 +1474,7 @@ AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
{
for (uint32_t i = 0; i < names.Length(); ++i) {
JS::Rooted<JS::Value> v(cx);
if (!xpc::NonVoidStringToJsval(cx, names[i], v.address())) {
if (!xpc::NonVoidStringToJsval(cx, names[i], &v)) {
return false;
}
@ -1649,10 +1648,10 @@ private:
};
nsresult
ReparentWrapper(JSContext* aCx, JS::HandleObject aObjArg)
ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg)
{
// aObj is assigned to below, so needs to be re-rooted.
JS::RootedObject aObj(aCx, aObjArg);
JS::Rooted<JSObject*> aObj(aCx, aObjArg);
const DOMClass* domClass = GetDOMClass(aObj);
JS::Rooted<JSObject*> oldParent(aCx, JS_GetParent(aObj));
@ -1756,20 +1755,9 @@ ReparentWrapper(JSContext* aCx, JS::HandleObject aObjArg)
if (ww != aObj) {
MOZ_ASSERT(cache->HasSystemOnlyWrapper());
JS::RootedObject newwrapper(aCx,
xpc::WrapperFactory::WrapSOWObject(aCx, newobj));
if (!newwrapper) {
MOZ_CRASH();
}
// Oops. We don't support transplanting objects with SOWs anymore.
MOZ_CRASH();
// Ok, now we do the special object-plus-wrapper transplant.
ww = xpc::TransplantObjectWithWrapper(aCx, aObj, ww, newobj, newwrapper);
if (!ww) {
MOZ_CRASH();
}
aObj = newobj;
SetSystemOnlyWrapperSlot(aObj, JS::ObjectValue(*ww));
} else {
aObj = xpc::TransplantObject(aCx, aObj, newobj);
if (!aObj) {
@ -1863,7 +1851,7 @@ GlobalObject::GetAsSupports() const
// using new bindings.
nsresult rv = xpc_qsUnwrapArg<nsISupports>(mCx, val, &mGlobalObject,
static_cast<nsISupports**>(getter_AddRefs(mGlobalObjectRef)),
val.address());
&val);
if (NS_FAILED(rv)) {
mGlobalObject = nullptr;
Throw(mCx, NS_ERROR_XPC_BAD_CONVERT_JS);

Просмотреть файл

@ -35,8 +35,8 @@
class nsPIDOMWindow;
extern nsresult
xpc_qsUnwrapArgImpl(JSContext* cx, jsval v, const nsIID& iid, void** ppArg,
nsISupports** ppArgRef, jsval* vp);
xpc_qsUnwrapArgImpl(JSContext* cx, JS::Handle<JS::Value> v, const nsIID& iid, void** ppArg,
nsISupports** ppArgRef, JS::MutableHandle<JS::Value> vp);
namespace mozilla {
namespace dom {
@ -53,8 +53,8 @@ struct SelfRef
/** Convert a jsval to an XPCOM pointer. */
template <class Interface, class StrongRefType>
inline nsresult
UnwrapArg(JSContext* cx, jsval v, Interface** ppArg,
StrongRefType** ppArgRef, jsval* vp)
UnwrapArg(JSContext* cx, JS::Handle<JS::Value> v, Interface** ppArg,
StrongRefType** ppArgRef, JS::MutableHandle<JS::Value> vp)
{
nsISupports* argRef = *ppArgRef;
nsresult rv = xpc_qsUnwrapArgImpl(cx, v, NS_GET_TEMPLATE_IID(Interface),
@ -792,7 +792,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
bool
NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
JS::Handle<JSObject*> aScope,
JS::Value* aRetval,
JS::MutableHandle<JS::Value> aRetval,
xpcObjectHelper& aHelper,
const nsIID* aIID,
bool aAllowNativeWrapper);
@ -811,7 +811,7 @@ HandleNewBindingWrappingFailure(JSContext* cx, JS::Handle<JSObject*> scope,
}
qsObjectHelper helper(value, GetWrapperCache(value));
return NativeInterface2JSObjectAndThrowIfFailed(cx, scope, rval.address(),
return NativeInterface2JSObjectAndThrowIfFailed(cx, scope, rval,
helper, nullptr, true);
}
@ -977,12 +977,12 @@ InstanceClassHasProtoAtDepth(JS::Handle<JSObject*> protoObject, uint32_t protoID
bool
XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
xpcObjectHelper& helper, const nsIID* iid,
bool allowNativeWrapper, JS::Value* rval);
bool allowNativeWrapper, JS::MutableHandle<JS::Value> rval);
// Special-cased wrapping for variants
bool
VariantToJsval(JSContext* aCx, JS::Handle<JSObject*> aScope,
nsIVariant* aVariant, JS::Value* aRetval);
nsIVariant* aVariant, JS::MutableHandle<JS::Value> aRetval);
// Wrap an object "p" which is not using WebIDL bindings yet. This _will_
// actually work on WebIDL binding objects that are wrappercached, but will be
@ -994,10 +994,10 @@ WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p,
nsWrapperCache* cache, const nsIID* iid,
JS::MutableHandle<JS::Value> rval)
{
if (xpc_FastGetCachedWrapper(cache, scope, rval.address()))
if (xpc_FastGetCachedWrapper(cache, scope, rval))
return true;
qsObjectHelper helper(p, cache);
return XPCOMObjectToJsval(cx, scope, helper, iid, true, rval.address());
return XPCOMObjectToJsval(cx, scope, helper, iid, true, rval);
}
// A specialization of the above for nsIVariant, because that needs to
@ -1010,7 +1010,7 @@ WrapObject<nsIVariant>(JSContext* cx, JS::Handle<JSObject*> scope, nsIVariant* p
{
MOZ_ASSERT(iid);
MOZ_ASSERT(iid->Equals(NS_GET_IID(nsIVariant)));
return VariantToJsval(cx, scope, p, rval.address());
return VariantToJsval(cx, scope, p, rval);
}
// Wrap an object "p" which is not using WebIDL bindings yet. Just like the
@ -1100,8 +1100,8 @@ WrapNativeISupportsParent(JSContext* cx, JS::Handle<JSObject*> scope, T* p,
{
qsObjectHelper helper(ToSupports(p), cache);
JS::Rooted<JS::Value> v(cx);
return XPCOMObjectToJsval(cx, scope, helper, nullptr, false, v.address()) ?
JSVAL_TO_OBJECT(v) :
return XPCOMObjectToJsval(cx, scope, helper, nullptr, false, &v) ?
v.toObjectOrNull() :
nullptr;
}
@ -2005,7 +2005,7 @@ const T& NonNullHelper(const OwningNonNull<T>& aArg)
// Reparent the wrapper of aObj to whatever its native now thinks its
// parent should be.
nsresult
ReparentWrapper(JSContext* aCx, JS::HandleObject aObj);
ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObj);
/**
* Used to implement the hasInstance hook of an interface object.

Просмотреть файл

@ -1516,7 +1516,7 @@ class MethodDefiner(PropertyDefiner):
if any(m.isGetter() and m.isIndexed() for m in methods):
self.regular.append({"name": "@@iterator",
"methodInfo": False,
"selfHostedName": "ArrayIterator",
"selfHostedName": "ArrayValues",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": MemberCondition(None, None) })
@ -2409,7 +2409,7 @@ class CastableObjectUnwrapper():
"${type} *objPtr;\n"
"SelfRef objRef;\n"
"JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*${source}));\n"
"nsresult rv = UnwrapArg<${type}>(cx, val, &objPtr, &objRef.ptr, val.address());\n"
"nsresult rv = UnwrapArg<${type}>(cx, val, &objPtr, &objRef.ptr, &val);\n"
"if (NS_FAILED(rv)) {\n"
"${codeOnFailure}\n"
"}\n"
@ -3230,7 +3230,7 @@ for (uint32_t i = 0; i < length; ++i) {
templateBody += (
"JS::Rooted<JS::Value> tmpVal(cx, ${val});\n" +
typePtr + " tmp;\n"
"if (NS_FAILED(UnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), tmpVal.address()))) {\n")
"if (NS_FAILED(UnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), &tmpVal))) {\n")
templateBody += CGIndenter(onFailureBadType(failureCode,
descriptor.interface.identifier.name)).define()
templateBody += ("}\n"
@ -4121,9 +4121,9 @@ if (!returnArray) {
if type.isDOMString():
if type.nullable():
return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalRef}.address())" % result), False)
return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalHandle})" % result), False)
else:
return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalRef}.address())" % result), False)
return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalHandle})" % result), False)
if type.isByteString():
if type.nullable():

Просмотреть файл

@ -67,9 +67,9 @@ public:
MOZ_ASSERT(aReq && aAdapterPtr);
}
virtual bool ParseSuccessfulReply(JS::Value* aValue)
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
{
*aValue = JSVAL_VOID;
aValue.setUndefined();
const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
@ -113,7 +113,7 @@ public:
return false;
}
aValue->setObject(*JsDevices);
aValue.setObject(*JsDevices);
return true;
}
@ -136,9 +136,9 @@ public:
MOZ_ASSERT(aReq);
}
virtual bool ParseSuccessfulReply(JS::Value* aValue)
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
{
*aValue = JSVAL_VOID;
aValue.setUndefined();
const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::Tbool) {
@ -147,7 +147,7 @@ public:
return false;
}
aValue->setBoolean(v.get_bool());
aValue.setBoolean(v.get_bool());
return true;
}
@ -878,6 +878,75 @@ BluetoothAdapter::IsScoConnected(ErrorResult& aRv)
return request.forget();
}
already_AddRefed<DOMRequest>
BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<BluetoothVoidReplyRunnable> results =
new BluetoothVoidReplyRunnable(request);
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bs->AnswerWaitingCall(results);
return request.forget();
}
already_AddRefed<DOMRequest>
BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<BluetoothVoidReplyRunnable> results =
new BluetoothVoidReplyRunnable(request);
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bs->IgnoreWaitingCall(results);
return request.forget();
}
already_AddRefed<DOMRequest>
BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<BluetoothVoidReplyRunnable> results =
new BluetoothVoidReplyRunnable(request);
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bs->ToggleCalls(results);
return request.forget();
}
already_AddRefed<DOMRequest>
BluetoothAdapter::SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv)
{

Просмотреть файл

@ -137,6 +137,10 @@ public:
already_AddRefed<DOMRequest> DisconnectSco(ErrorResult& aRv);
already_AddRefed<DOMRequest> IsScoConnected(ErrorResult& aRv);
already_AddRefed<DOMRequest> AnswerWaitingCall(ErrorResult& aRv);
already_AddRefed<DOMRequest> IgnoreWaitingCall(ErrorResult& aRv);
already_AddRefed<DOMRequest> ToggleCalls(ErrorResult& aRv);
already_AddRefed<DOMRequest>
SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv);
already_AddRefed<DOMRequest>

Просмотреть файл

@ -142,22 +142,6 @@ static CINDItem sCINDItems[] = {
{"roam", "0,1", 0, true}
};
class mozilla::dom::bluetooth::Call {
public:
Call(uint16_t aState = nsITelephonyProvider::CALL_STATE_DISCONNECTED,
bool aDirection = false,
const nsAString& aNumber = EmptyString(),
int aType = TOA_UNKNOWN)
: mState(aState), mDirection(aDirection), mNumber(aNumber), mType(aType)
{
}
uint16_t mState;
bool mDirection; // true: incoming call; false: outgoing call
nsString mNumber;
int mType;
};
class BluetoothHfpManager::GetVolumeTask : public nsISettingsServiceCallback
{
public:
@ -313,6 +297,32 @@ IsMandatoryIndicator(const CINDType aType) {
(aType == CINDType::CALLSETUP);
}
/**
* Call
*/
Call::Call()
{
Reset();
}
void
Call::Reset()
{
mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
mDirection = false;
mNumber.Truncate();
mType = TOA_UNKNOWN;
}
bool
Call::IsActive()
{
return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
}
/**
* BluetoothHfpManager
*/
BluetoothHfpManager::BluetoothHfpManager()
{
Reset();
@ -326,6 +336,10 @@ BluetoothHfpManager::ResetCallArray()
// index from RIL starts at 1.
Call call;
mCurrentCallArray.AppendElement(call);
if (mPhoneType == PhoneType::CDMA) {
mCdmaSecondCall.Reset();
}
}
void
@ -550,6 +564,10 @@ BluetoothHfpManager::HandleVoiceConnectionChanged()
connection->GetVoiceConnectionInfo(getter_AddRefs(voiceInfo));
NS_ENSURE_TRUE_VOID(voiceInfo);
nsString type;
voiceInfo->GetType(type);
mPhoneType = GetPhoneType(type);
bool roaming;
voiceInfo->GetRoaming(&roaming);
UpdateCIND(CINDType::ROAM, roaming);
@ -647,10 +665,15 @@ 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) {
uint32_t brsf = BRSF_BIT_THREE_WAY_CALLING |
BRSF_BIT_ABILITY_TO_REJECT_CALL |
uint32_t brsf = BRSF_BIT_ABILITY_TO_REJECT_CALL |
BRSF_BIT_ENHANCED_CALL_STATUS;
// No support for three way calling in CDMA since
// CDMA disallows to hang existing call for CHLD=1
if (mPhoneType != PhoneType::CDMA) {
brsf |= BRSF_BIT_THREE_WAY_CALLING;
}
if (mBSIR) {
brsf |= BRSF_BIT_IN_BAND_RING_TONE;
}
@ -1076,6 +1099,68 @@ BluetoothHfpManager::Disconnect(BluetoothProfileController* aController)
mSocket = nullptr;
}
void
BluetoothHfpManager::SendCCWA(const nsAString& aNumber, int aType)
{
if (mCCWA) {
nsAutoCString ccwaMsg("+CCWA: \"");
ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
ccwaMsg.AppendLiteral("\",");
ccwaMsg.AppendInt(aType);
SendLine(ccwaMsg.get());
}
}
bool
BluetoothHfpManager::SendCLCC(const Call& aCall, int aIndex)
{
if (aCall.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
return true;
}
nsAutoCString message("+CLCC: ");
message.AppendInt(aIndex);
message.AppendLiteral(",");
message.AppendInt(aCall.mDirection);
message.AppendLiteral(",");
int status = 0;
switch (aCall.mState) {
case nsITelephonyProvider::CALL_STATE_CONNECTED:
if (mPhoneType == PhoneType::CDMA && aIndex == 1) {
status = (mCdmaSecondCall.IsActive()) ? 1 : 0;
}
message.AppendInt(status);
break;
case nsITelephonyProvider::CALL_STATE_HELD:
message.AppendInt(1);
break;
case nsITelephonyProvider::CALL_STATE_DIALING:
message.AppendInt(2);
break;
case nsITelephonyProvider::CALL_STATE_ALERTING:
message.AppendInt(3);
break;
case nsITelephonyProvider::CALL_STATE_INCOMING:
if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
message.AppendInt(4);
} else {
message.AppendInt(5);
}
break;
default:
BT_WARNING("Not handling call status for CLCC");
break;
}
message.AppendLiteral(",0,0,\"");
message.Append(NS_ConvertUTF16toUTF8(aCall.mNumber));
message.AppendLiteral("\",");
message.AppendInt(aCall.mType);
return SendLine(message.get());
}
bool
BluetoothHfpManager::SendLine(const char* aMessage)
{
@ -1143,49 +1228,18 @@ BluetoothHfpManager::SendCommand(const char* aCommand, uint32_t aValue)
} else if (!strcmp(aCommand, "+CLCC: ")) {
bool rv = true;
uint32_t callNumbers = mCurrentCallArray.Length();
for (uint32_t i = 1; i < callNumbers; i++) {
Call& call = mCurrentCallArray[i];
if (call.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
continue;
}
message.AssignLiteral("+CLCC: ");
message.AppendInt(i);
message.AppendLiteral(",");
message.AppendInt(call.mDirection);
message.AppendLiteral(",");
switch (call.mState) {
case nsITelephonyProvider::CALL_STATE_CONNECTED:
message.AppendInt(0);
break;
case nsITelephonyProvider::CALL_STATE_HELD:
message.AppendInt(1);
break;
case nsITelephonyProvider::CALL_STATE_DIALING:
message.AppendInt(2);
break;
case nsITelephonyProvider::CALL_STATE_ALERTING:
message.AppendInt(3);
break;
case nsITelephonyProvider::CALL_STATE_INCOMING:
if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
message.AppendInt(4);
} else {
message.AppendInt(5);
}
break;
default:
BT_WARNING("Not handling call status for CLCC");
break;
}
message.AppendLiteral(",0,0,\"");
message.Append(NS_ConvertUTF16toUTF8(call.mNumber));
message.AppendLiteral("\",");
message.AppendInt(call.mType);
rv &= SendLine(message.get());
uint32_t i;
for (i = 1; i < callNumbers; i++) {
rv &= SendCLCC(mCurrentCallArray[i], i);
}
if (!mCdmaSecondCall.mNumber.IsEmpty()) {
MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
MOZ_ASSERT(i == 2);
rv &= SendCLCC(mCdmaSecondCall, 2);
}
return rv;
} else {
message.AppendInt(aValue);
@ -1276,13 +1330,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
break;
case nsITelephonyProvider::CALL_STATE_INCOMING:
if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
if (mCCWA) {
nsAutoCString ccwaMsg("+CCWA: \"");
ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
ccwaMsg.AppendLiteral("\",");
ccwaMsg.AppendInt(mCurrentCallArray[aCallIndex].mType);
SendLine(ccwaMsg.get());
}
SendCCWA(aNumber, mCurrentCallArray[aCallIndex].mType);
UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
} else {
// Start sending RING indicator to HF
@ -1410,6 +1458,77 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
}
}
PhoneType
BluetoothHfpManager::GetPhoneType(const nsAString& aType)
{
// FIXME: Query phone type from RIL after RIL implements new API (bug 912019)
if (aType.EqualsLiteral("gsm") || aType.EqualsLiteral("gprs") ||
aType.EqualsLiteral("edge") || aType.EqualsLiteral("umts") ||
aType.EqualsLiteral("hspa") || aType.EqualsLiteral("hsdpa") ||
aType.EqualsLiteral("hsupa") || aType.EqualsLiteral("hspa+")) {
return PhoneType::GSM;
} else if (aType.EqualsLiteral("is95a") || aType.EqualsLiteral("is95b") ||
aType.EqualsLiteral("1xrtt") || aType.EqualsLiteral("evdo0") ||
aType.EqualsLiteral("evdoa") || aType.EqualsLiteral("evdob")) {
return PhoneType::CDMA;
}
return PhoneType::NONE;
}
void
BluetoothHfpManager::UpdateSecondNumber(const nsAString& aNumber)
{
MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
// Always regard second call as incoming call since v1.2 RIL
// doesn't support outgoing second call in CDMA.
mCdmaSecondCall.mDirection = true;
mCdmaSecondCall.mNumber = aNumber;
mCdmaSecondCall.mType = (aNumber[0] == '+') ? TOA_INTERNATIONAL :
TOA_UNKNOWN;
SendCCWA(aNumber, mCdmaSecondCall.mType);
UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, true);
}
void
BluetoothHfpManager::AnswerWaitingCall()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
// Pick up second call. First call is held now.
mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
SendCommand("+CIEV: ", CINDType::CALLHELD);
}
void
BluetoothHfpManager::IgnoreWaitingCall()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
mCdmaSecondCall.Reset();
UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
}
void
BluetoothHfpManager::ToggleCalls()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
// Toggle acitve and held calls
mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
nsITelephonyProvider::CALL_STATE_HELD :
nsITelephonyProvider::CALL_STATE_CONNECTED;
}
void
BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
{

Просмотреть файл

@ -50,6 +50,24 @@ enum BluetoothCmeError {
NETWORK_NOT_ALLOWED = 32
};
enum PhoneType {
NONE, // no connection
GSM,
CDMA
};
class Call {
public:
Call();
void Reset();
bool IsActive();
uint16_t mState;
bool mDirection; // true: incoming call; false: outgoing call
nsString mNumber;
int mType;
};
class BluetoothHfpManager : public BluetoothSocketObserver
, public BluetoothProfileManagerBase
, public BatteryObserver
@ -103,6 +121,12 @@ public:
bool IsConnected();
bool IsScoConnected();
// CDMA-specific functions
void UpdateSecondNumber(const nsAString& aNumber);
void AnswerWaitingCall();
void IgnoreWaitingCall();
void ToggleCalls();
private:
class CloseScoTask;
class GetVolumeTask;
@ -125,10 +149,13 @@ private:
void ResetCallArray();
uint32_t FindFirstCall(uint16_t aState);
uint32_t GetNumberOfCalls(uint16_t aState);
PhoneType GetPhoneType(const nsAString& aType);
void NotifyConnectionStatusChanged(const nsAString& aType);
void NotifyDialer(const nsAString& aCommand);
void SendCCWA(const nsAString& aNumber, int aType);
bool SendCLCC(const Call& aCall, int aIndex);
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
bool SendLine(const char* aMessage);
void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
@ -145,6 +172,7 @@ private:
bool mCMER;
bool mFirstCKPD;
int mNetworkSelectionMode;
PhoneType mPhoneType;
bool mReceiveVgsFlag;
bool mDialingRequestProcessed;
nsString mDeviceAddress;
@ -170,6 +198,9 @@ private:
nsRefPtr<BluetoothSocket> mHeadsetSocket;
nsRefPtr<BluetoothSocket> mScoSocket;
SocketConnectionStatus mScoSocketStatus;
// CDMA-specific variable
Call mCdmaSecondCall;
};
END_BLUETOOTH_NAMESPACE

Просмотреть файл

@ -42,9 +42,9 @@ public:
}
bool
ParseSuccessfulReply(JS::Value* aValue)
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
{
*aValue = JSVAL_VOID;
aValue.setUndefined();
const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {

Просмотреть файл

@ -32,7 +32,7 @@ BluetoothReplyRunnable::~BluetoothReplyRunnable()
{}
nsresult
BluetoothReplyRunnable::FireReply(const JS::Value& aVal)
BluetoothReplyRunnable::FireReply(JS::Handle<JS::Value> aVal)
{
nsCOMPtr<nsIDOMRequestService> rs =
do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
@ -62,10 +62,12 @@ BluetoothReplyRunnable::Run()
nsresult rv;
AutoSafeJSContext cx;
JS::Rooted<JS::Value> v(cx, JSVAL_VOID);
if (mReply->type() != BluetoothReply::TBluetoothReplySuccess) {
rv = FireReply(JSVAL_VOID);
rv = FireReply(v);
} else {
JS::Value v;
if (!ParseSuccessfulReply(&v)) {
rv = FireErrorString();
} else {

Просмотреть файл

@ -37,7 +37,7 @@ public:
protected:
virtual ~BluetoothReplyRunnable();
virtual bool ParseSuccessfulReply(JS::Value* aValue) = 0;
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) = 0;
// This is an autoptr so we don't have to bring the ipdl include into the
// header. We assume we'll only be running this once and it should die on
@ -45,7 +45,7 @@ protected:
nsAutoPtr<BluetoothReply> mReply;
private:
nsresult FireReply(const JS::Value& aVal);
nsresult FireReply(JS::Handle<JS::Value> aVal);
nsresult FireErrorString();
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
@ -59,9 +59,9 @@ public:
~BluetoothVoidReplyRunnable();
protected:
virtual bool ParseSuccessfulReply(JS::Value* aValue) MOZ_OVERRIDE
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) MOZ_OVERRIDE
{
*aValue = JSVAL_VOID;
aValue.setUndefined();
return true;
}
};

Просмотреть файл

@ -214,6 +214,9 @@ TelephonyListener::SupplementaryServiceNotification(int32_t aCallIndex,
NS_IMETHODIMP
TelephonyListener::NotifyCdmaCallWaiting(const nsAString& aNumber)
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->UpdateSecondNumber(aNumber);
return NS_OK;
}

Просмотреть файл

@ -44,7 +44,9 @@
#if defined(MOZ_B2G_BT)
# if defined(MOZ_BLUETOOTH_GONK)
# include "BluetoothGonkService.h"
#ifndef MOZ_B2G_BT_BLUEDROID
#include "BluetoothGonkService.h"
#endif
# elif defined(MOZ_BLUETOOTH_DBUS)
# include "BluetoothDBusService.h"
# else
@ -304,9 +306,13 @@ BluetoothService::Create()
#endif
#if defined(MOZ_BLUETOOTH_GONK)
#ifndef MOZ_B2G_BT_BLUEDROID
return new BluetoothGonkService();
#endif
#elif defined(MOZ_BLUETOOTH_DBUS)
#ifdef MOZ_B2G_BT_BLUEZ
return new BluetoothDBusService();
#endif
#endif
BT_WARNING("No platform support for bluetooth!");
return nullptr;

Просмотреть файл

@ -266,6 +266,15 @@ public:
virtual void
IsScoConnected(BluetoothReplyRunnable* aRunnable) = 0;
virtual void
AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) = 0;
virtual void
IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable) = 0;
virtual void
ToggleCalls(BluetoothReplyRunnable* aRunnable) = 0;
virtual void
SendMetaData(const nsAString& aTitle,
const nsAString& aArtist,

Просмотреть файл

@ -27,11 +27,12 @@
#include <errno.h>
#include <sys/socket.h>
#ifdef MOZ_B2G_BT_BLUEZ
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sco.h>
#endif
#include "BluetoothUnixSocketConnector.h"
#include "nsThreadUtils.h"
@ -43,6 +44,7 @@ static const int L2CAP_SO_SNDBUF = 400 * 1024; // 400 KB send buffer
static const int L2CAP_SO_RCVBUF = 400 * 1024; // 400 KB receive buffer
static const int L2CAP_MAX_MTU = 65000;
#ifdef MOZ_B2G_BT_BLUEZ
static
int get_bdaddr(const char *str, bdaddr_t *ba)
{
@ -62,6 +64,8 @@ void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
b[5], b[4], b[3], b[2], b[1], b[0]);
}
#endif
BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
BluetoothSocketType aType,
int aChannel,
@ -76,6 +80,7 @@ BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
bool
BluetoothUnixSocketConnector::SetUp(int aFd)
{
#ifdef MOZ_B2G_BT_BLUEZ
int lm = 0;
int sndbuf, rcvbuf;
@ -157,7 +162,7 @@ BluetoothUnixSocketConnector::SetUp(int aFd)
}
}
}
#endif
return true;
}
@ -167,6 +172,7 @@ BluetoothUnixSocketConnector::Create()
MOZ_ASSERT(!NS_IsMainThread());
int fd = -1;
#ifdef MOZ_B2G_BT_BLUEZ
switch (mType) {
case BluetoothSocketType::RFCOMM:
fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
@ -193,7 +199,7 @@ BluetoothUnixSocketConnector::Create()
BT_WARNING("Could not set up socket!");
return -1;
}
#endif
return fd;
}
@ -203,6 +209,7 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
sockaddr_any& aAddr,
const char* aAddress)
{
#ifdef MOZ_B2G_BT_BLUEZ
// Set to BDADDR_ANY, if it's not a server, we'll reset.
bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
@ -242,6 +249,7 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
BT_WARNING("Socket type unknown!");
return false;
}
#endif
return true;
}
@ -249,6 +257,7 @@ void
BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
nsAString& aAddrStr)
{
#ifdef MOZ_B2G_BT_BLUEZ
char addr[18];
switch (mType) {
case BluetoothSocketType::RFCOMM:
@ -265,4 +274,5 @@ BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
MOZ_CRASH("Socket should be either RFCOMM or SCO!");
}
aAddrStr.AssignASCII(addr);
#endif
}

Просмотреть файл

@ -36,6 +36,14 @@ DEFINES += -DMOZ_BLUETOOTH_DBUS
endif
endif
ifdef MOZ_B2G_BT_BLUEZ
DEFINES += -DMOZ_B2G_BT_BLUEZ
endif
ifdef MOZ_B2G_BT_BLUEDROID
DEFINES += -DMOZ_B2G_BT_BLUEDROID
endif
# Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
# subdirectory.
LOCAL_INCLUDES += $(VPATH:%=-I%)

Просмотреть файл

@ -65,7 +65,7 @@ public:
}
virtual bool
ParseSuccessfulReply(JS::Value* aValue) MOZ_OVERRIDE
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) MOZ_OVERRIDE
{
MOZ_CRASH("This should never be called!");
}
@ -226,6 +226,12 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_DisconnectScoRequest());
case Request::TIsScoConnectedRequest:
return actor->DoRequest(aRequest.get_IsScoConnectedRequest());
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());
case Request::TSendMetaDataRequest:
return actor->DoRequest(aRequest.get_SendMetaDataRequest());
case Request::TSendPlayStatusRequest:
@ -575,6 +581,39 @@ BluetoothRequestParent::DoRequest(const IsScoConnectedRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const AnswerWaitingCallRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
mService->AnswerWaitingCall(mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const IgnoreWaitingCallRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
mService->IgnoreWaitingCall(mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const ToggleCallsRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
mService->ToggleCalls(mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const SendMetaDataRequest& aRequest)
{

Просмотреть файл

@ -190,6 +190,15 @@ protected:
bool
DoRequest(const IsScoConnectedRequest& aRequest);
bool
DoRequest(const AnswerWaitingCallRequest& aRequest);
bool
DoRequest(const IgnoreWaitingCallRequest& aRequest);
bool
DoRequest(const ToggleCallsRequest& aRequest);
bool
DoRequest(const SendMetaDataRequest& aRequest);

Просмотреть файл

@ -328,6 +328,27 @@ BluetoothServiceChildProcess::IsScoConnected(BluetoothReplyRunnable* aRunnable)
SendRequest(aRunnable, IsScoConnectedRequest());
}
void
BluetoothServiceChildProcess::AnswerWaitingCall(
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, AnswerWaitingCallRequest());
}
void
BluetoothServiceChildProcess::IgnoreWaitingCall(
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, IgnoreWaitingCallRequest());
}
void
BluetoothServiceChildProcess::ToggleCalls(
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, ToggleCallsRequest());
}
void
BluetoothServiceChildProcess::SendMetaData(const nsAString& aTitle,
const nsAString& aArtist,

Просмотреть файл

@ -149,6 +149,15 @@ public:
virtual void
IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
ToggleCalls(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
SendMetaData(const nsAString& aTitle,
const nsAString& aArtist,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше