merge b2g-inbound to mozilla-central

This commit is contained in:
Carsten "Tomcat" Book
2014-03-20 14:07:58 +01:00
87 changed files with 1477 additions and 857 deletions

View File

@@ -650,6 +650,9 @@ pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0);
pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096); pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
pref("hal.processPriorityManager.gonk.MASTER.Nice", 0); pref("hal.processPriorityManager.gonk.MASTER.Nice", 0);
pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.PREALLOC.Nice", 18);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.Nice", 0); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.Nice", 0);

View File

@@ -0,0 +1,59 @@
#controls {
position: absolute;
left: 0;
bottom:0;
right: 0;
height: 30px;
background-color: -moz-dialog;
}
#home-button {
margin: auto;
margin-top: 3px;
width: 24px;
height: 24px;
background: #eee url("images/desktop/home-black.png") center no-repeat;
border: 1px solid #888;
border-radius: 12px;
display: block;
}
#home-button::-moz-focus-inner {
padding: 0;
border: 0;
}
#home-button:hover {
background-image: url("images/desktop/home-white.png");
background-color: #ccc;
border-color: #555;
}
#home-button.active {
background-image: url("images/desktop/home-white.png");
background-color: #888;
border-color: black;
}
#rotate-button {
position: absolute;
top: 3px;
bottom: 3px;
right: 3px;
width: 24px;
height: 24px;
background: #eee url("images/desktop/rotate.png") center no-repeat;
border: 1px solid #888;
border-radius: 12px;
display: block;
}
#rotate-button:hover {
background-color: #ccc;
border-color: #555;
}
#rotate-button.active {
background-color: #888;
border-color: black;
}

View File

@@ -2,16 +2,51 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
window.addEventListener("ContentStart", function(evt) { // Enable touch event shim on desktop that translates mouse events
// Enable touch event shim on desktop that translates mouse events // into touch ones
// into touch ones function enableTouch() {
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}) let require = Cu.import('resource://gre/modules/devtools/Loader.jsm', {})
.devtools.require; .devtools.require;
let { TouchEventHandler } = require("devtools/touch-events"); let { TouchEventHandler } = require('devtools/touch-events');
let chromeEventHandler = window.QueryInterface(Ci.nsIInterfaceRequestor) let chromeEventHandler = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation) .getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell) .QueryInterface(Ci.nsIDocShell)
.chromeEventHandler || window; .chromeEventHandler || window;
let touchEventHandler = new TouchEventHandler(chromeEventHandler); let touchEventHandler = new TouchEventHandler(chromeEventHandler);
touchEventHandler.start(); touchEventHandler.start();
}
function setupButtons() {
let homeButton = document.getElementById('home-button');
if (!homeButton) {
// The toolbar only exists in b2g desktop build with
// FXOS_SIMULATOR turned on.
return;
}
// The touch event helper is enabled on shell.html document,
// so that click events are delayed and it is better to
// listen for touch events.
homeButton.addEventListener('touchstart', function() {
shell.sendChromeEvent({type: 'home-button-press'});
homeButton.classList.add('active');
});
homeButton.addEventListener('touchend', function() {
shell.sendChromeEvent({type: 'home-button-release'});
homeButton.classList.remove('active');
});
Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
let rotateButton = document.getElementById('rotate-button');
rotateButton.addEventListener('touchstart', function () {
rotateButton.classList.add('active');
});
rotateButton.addEventListener('touchend', function() {
GlobalSimulatorScreen.flipScreen();
rotateButton.classList.remove('active');
});
}
window.addEventListener('ContentStart', function() {
enableTouch();
setupButtons();
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

View File

@@ -18,7 +18,7 @@ window.addEventListener('ContentStart', function() {
.getInterface(Components.interfaces.nsIDOMWindowUtils); .getInterface(Components.interfaces.nsIDOMWindowUtils);
let hostDPI = windowUtils.displayDPI; let hostDPI = windowUtils.displayDPI;
let DEFAULT_SCREEN = "320x480"; let DEFAULT_SCREEN = '320x480';
// This is a somewhat random selection of named screens. // This is a somewhat random selection of named screens.
// Add more to this list when we support more hardware. // Add more to this list when we support more hardware.
@@ -121,6 +121,11 @@ window.addEventListener('ContentStart', function() {
usage(); usage();
} }
Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
function resize(width, height, dpi, shouldFlip) {
GlobalSimulatorScreen.width = width;
GlobalSimulatorScreen.height = height;
// In order to do rescaling, we set the <browser> tag to the specified // In order to do rescaling, we set the <browser> tag to the specified
// width and height, and then use a CSS transform to scale it so that // width and height, and then use a CSS transform to scale it so that
// it appears at the correct size on the host display. We also set // it appears at the correct size on the host display. We also set
@@ -128,28 +133,80 @@ window.addEventListener('ContentStart', function() {
let scale = rescale ? hostDPI / dpi : 1; let scale = rescale ? hostDPI / dpi : 1;
// Set the window width and height to desired size plus chrome // Set the window width and height to desired size plus chrome
// Include the size of the toolbox displayed under the system app
let controls = document.getElementById('controls');
let controlsHeight = 0;
if (controls) {
controlsHeight = controls.getBoundingClientRect().height;
}
let chromewidth = window.outerWidth - window.innerWidth; let chromewidth = window.outerWidth - window.innerWidth;
let chromeheight = window.outerHeight - window.innerHeight; let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
window.resizeTo(Math.round(width * scale) + chromewidth, window.resizeTo(Math.round(width * scale) + chromewidth,
Math.round(height * scale) + chromeheight); Math.round(height * scale) + chromeheight);
let frameWidth = width, frameHeight = height;
if (shouldFlip) {
frameWidth = height;
frameHeight = width;
}
// Set the browser element to the full unscaled size of the screen // Set the browser element to the full unscaled size of the screen
browser.style.width = browser.style.minWidth = browser.style.maxWidth = let style = browser.style;
width + 'px'; style.width = style.minWidth = style.maxWidth =
browser.style.height = browser.style.minHeight = browser.style.maxHeight = frameWidth + 'px';
height + 'px'; style.height = style.minHeight = style.maxHeight =
frameHeight + 'px';
browser.setAttribute('flex', '0'); // Don't let it stretch browser.setAttribute('flex', '0'); // Don't let it stretch
style.transformOrigin = '';
style.transform = '';
// Now scale the browser element as needed // Now scale the browser element as needed
if (scale !== 1) { if (scale !== 1) {
browser.style.transformOrigin = 'top left'; style.transformOrigin = 'top left';
browser.style.transform = 'scale(' + scale + ',' + scale + ')'; style.transform += ' scale(' + scale + ',' + scale + ')';
}
if (shouldFlip) {
// Display the system app with a 90° clockwise rotation
let shift = Math.floor(Math.abs(frameWidth-frameHeight) / 2);
style.transform +=
' rotate(0.25turn) translate(-' + shift + 'px, -' + shift + 'px)';
} }
// Set the pixel density that we want to simulate. // Set the pixel density that we want to simulate.
// This doesn't change the on-screen size, but makes // This doesn't change the on-screen size, but makes
// CSS media queries and mozmm units work right. // CSS media queries and mozmm units work right.
Services.prefs.setIntPref('layout.css.dpi', dpi); Services.prefs.setIntPref('layout.css.dpi', dpi);
}
// Resize on startup
resize(width, height, dpi, false);
let defaultOrientation = width < height ? 'portrait' : 'landscape';
// Then resize on each rotation button click,
// or when the system app lock/unlock the orientation
Services.obs.addObserver(function orientationChangeListener(subject) {
let screen = subject.wrappedJSObject;
let { mozOrientation, screenOrientation } = screen;
let newWidth = width;
let newHeight = height;
// If we have an orientation different than the startup one,
// we switch the sizes
if (screenOrientation != defaultOrientation) {
newWidth = height;
newHeight = width;
}
// If the current app doesn't supports the current screen orientation
// still resize the window, but rotate its frame so that
// it is displayed rotated on the side
let shouldFlip = mozOrientation != screenOrientation;
resize(newWidth, newHeight, dpi, shouldFlip);
}, 'simulator-adjust-window-size', false);
// A utility function like console.log() for printing to the terminal window // A utility function like console.log() for printing to the terminal window
// Uses dump(), but enables it first, if necessary // Uses dump(), but enables it first, if necessary

View File

@@ -12,7 +12,11 @@
> >
<head> <head>
<link rel="stylesheet" href="shell.css" type="text/css" media="all" /> <link rel="stylesheet" href="shell.css" type="text/css">
#ifdef FXOS_SIMULATOR
<link rel="stylesheet" href="desktop.css" type="text/css">
#endif
<script type="application/javascript;version=1.8" <script type="application/javascript;version=1.8"
src="chrome://b2g/content/settings.js"> </script> src="chrome://b2g/content/settings.js"> </script>
<script type="application/javascript;version=1.8" <script type="application/javascript;version=1.8"
@@ -31,7 +35,15 @@
#endif #endif
</head> </head>
<body id="container"> <body id="container">
#ifdef MOZ_WIDGET_COCOA #ifdef FXOS_SIMULATOR
<!--
Some additional buttons are displayed on desktop to fake hardware buttons.
-->
<footer id="controls">
<button id="home-button"></button>
<button id="rotate-button"></button>
</footer>
#elifdef MOZ_WIDGET_COCOA
<!-- <!--
If the document is empty at startup, we don't display the window If the document is empty at startup, we don't display the window
at all on Mac OS... at all on Mac OS...

View File

@@ -303,7 +303,11 @@ var shell = {
systemAppFrame.setAttribute('src', "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;"); systemAppFrame.setAttribute('src', "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;");
let container = document.getElementById('container'); let container = document.getElementById('container');
#ifdef MOZ_WIDGET_COCOA #ifdef MOZ_WIDGET_COCOA
container.removeChild(document.getElementById('placeholder')); // See shell.html
let hotfix = document.getElementById('placeholder');
if (hotfix) {
container.removeChild(hotfix);
}
#endif #endif
container.appendChild(systemAppFrame); container.appendChild(systemAppFrame);

View File

@@ -14,7 +14,13 @@ chrome.jar:
* content/shell.js (content/shell.js) * content/shell.js (content/shell.js)
content/shell.css (content/shell.css) content/shell.css (content/shell.css)
content/devtools.js (content/devtools.js) content/devtools.js (content/devtools.js)
#ifndef ANDROID #ifdef FXOS_SIMULATOR
content/desktop.css (content/desktop.css)
content/images/desktop/home-black.png (content/images/desktop/home-black.png)
content/images/desktop/home-white.png (content/images/desktop/home-white.png)
content/images/desktop/rotate.png (content/images/desktop/rotate.png)
#endif
#ifndef MOZ_WIDGET_GONK
content/desktop.js (content/desktop.js) content/desktop.js (content/desktop.js)
content/screen.js (content/screen.js) content/screen.js (content/screen.js)
content/runapp.js (content/runapp.js) content/runapp.js (content/runapp.js)

View File

@@ -81,3 +81,9 @@ contract @mozilla.org/fxaccounts/fxaccounts-ui-glue;1 {51875c14-91d7-4b8c-b65d-3
# HelperAppDialog.js # HelperAppDialog.js
component {710322af-e6ae-4b0c-b2c9-1474a87b077e} HelperAppDialog.js component {710322af-e6ae-4b0c-b2c9-1474a87b077e} HelperAppDialog.js
contract @mozilla.org/helperapplauncherdialog;1 {710322af-e6ae-4b0c-b2c9-1474a87b077e} contract @mozilla.org/helperapplauncherdialog;1 {710322af-e6ae-4b0c-b2c9-1474a87b077e}
#ifndef MOZ_WIDGET_GONK
component {c83c02c0-5d43-4e3e-987f-9173b313e880} SimulatorScreen.js
contract @mozilla.org/simulator-screen;1 {c83c02c0-5d43-4e3e-987f-9173b313e880}
category profile-after-change SimulatorScreen @mozilla.org/simulator-screen;1
#endif

View File

@@ -0,0 +1,90 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
this.EXPORTED_SYMBOLS = [ 'GlobalSimulatorScreen' ];
const Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
this.GlobalSimulatorScreen = {
mozOrientationLocked: false,
// Actual orientation of apps
mozOrientation: 'portrait',
// The restricted list of actual orientation that can be used
// if mozOrientationLocked is true
lockedOrientation: [],
// The faked screen orientation
// if screenOrientation doesn't match mozOrientation due
// to lockedOrientation restriction, the app will be displayed
// on the side on desktop
screenOrientation: 'portrait',
// Updated by screen.js
width: 0, height: 0,
lock: function(orientation) {
this.mozOrientationLocked = true;
// Normalize to portrait or landscape,
// i.e. the possible values of screenOrientation
function normalize(str) {
if (str.match(/^portrait/)) {
return 'portrait';
} else if (str.match(/^landscape/)) {
return 'landscape';
} else {
return 'portrait';
}
}
this.lockedOrientation = orientation.map(normalize);
this.updateOrientation();
},
unlock: function() {
this.mozOrientationLocked = false;
this.updateOrientation();
},
updateOrientation: function () {
let orientation = this.screenOrientation;
// If the orientation is locked, we have to ensure ending up with a value
// of lockedOrientation. If none of lockedOrientation values matches
// the screen orientation we just choose the first locked orientation.
// This will be the precise scenario where the app is displayed on the
// side on desktop!
if (this.mozOrientationLocked &&
this.lockedOrientation.indexOf(this.screenOrientation) == -1) {
orientation = this.lockedOrientation[0];
}
// If the actual orientation changed,
// we have to fire mozorientation DOM events
if (this.mozOrientation != orientation) {
this.mozOrientation = orientation;
// Notify each app screen object to fire the event
Services.obs.notifyObservers(null, 'simulator-orientation-change', null);
}
// Finally, in any case, we update the window size and orientation
// (Use wrappedJSObject trick to be able to pass a raw JS object)
Services.obs.notifyObservers({wrappedJSObject:this}, 'simulator-adjust-window-size', null);
},
flipScreen: function() {
if (this.screenOrientation == 'portrait') {
this.screenOrientation = 'landscape';
} else if (this.screenOrientation == 'landscape') {
this.screenOrientation = 'portrait';
}
this.updateOrientation();
}
}

View File

@@ -0,0 +1,112 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let Ci = Components.interfaces;
let Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/DOMRequestHelper.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'GlobalSimulatorScreen',
'resource://gre/modules/GlobalSimulatorScreen.jsm');
let DEBUG_PREFIX = 'SimulatorScreen.js - ';
function debug() {
//dump(DEBUG_PREFIX + Array.slice(arguments) + '\n');
}
function fireOrientationEvent(window) {
let e = new window.Event('mozorientationchange');
window.screen.dispatchEvent(e);
}
function hookScreen(window) {
let nodePrincipal = window.document.nodePrincipal;
let origin = nodePrincipal.origin;
if (nodePrincipal.appStatus == nodePrincipal.APP_STATUS_NOT_INSTALLED) {
Cu.reportError('deny mozLockOrientation:' + origin + 'is not installed');
return;
}
let screen = window.wrappedJSObject.screen;
screen.mozLockOrientation = function (orientation) {
debug('mozLockOrientation:', orientation, 'from', origin);
// Normalize and do some checks against orientation input
if (typeof(orientation) == 'string') {
orientation = [orientation];
}
function isInvalidOrientationString(str) {
return typeof(str) != 'string' ||
!str.match(/^default$|^(portrait|landscape)(-(primary|secondary))?$/);
}
if (!Array.isArray(orientation) ||
orientation.some(isInvalidOrientationString)) {
Cu.reportError('Invalid orientation "' + orientation + '"');
return false;
}
GlobalSimulatorScreen.lock(orientation);
return true;
};
screen.mozUnlockOrientation = function() {
debug('mozOrientationUnlock from', origin);
GlobalSimulatorScreen.unlock();
return true;
};
Object.defineProperty(screen, 'width', {
get: function () GlobalSimulatorScreen.width
});
Object.defineProperty(screen, 'height', {
get: function () GlobalSimulatorScreen.height
});
Object.defineProperty(screen, 'mozOrientation', {
get: function () GlobalSimulatorScreen.mozOrientation
});
}
function SimulatorScreen() {}
SimulatorScreen.prototype = {
classID: Components.ID('{c83c02c0-5d43-4e3e-987f-9173b313e880}'),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
_windows: new Set(),
observe: function (subject, topic, data) {
switch (topic) {
case 'profile-after-change':
Services.obs.addObserver(this, 'document-element-inserted', false);
Services.obs.addObserver(this, 'simulator-orientation-change', false);
break;
case 'document-element-inserted':
let window = subject.defaultView;
if (!window) {
return;
}
hookScreen(window);
let windows = this._windows;
window.addEventListener('unload', function unload() {
window.removeEventListener('unload', unload);
windows.delete(window);
});
windows.add(window);
break;
case 'simulator-orientation-change':
this._windows.forEach(fireOrientationEvent);
break;
}
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SimulatorScreen]);

View File

@@ -46,6 +46,21 @@ XPCOMUtils.defineLazyServiceGetter(Services, "settings",
"@mozilla.org/settingsService;1", "@mozilla.org/settingsService;1",
"nsISettingsService"); "nsISettingsService");
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
'@mozilla.org/process/environment;1',
'nsIEnvironment');
function useSettings() {
// When we're running in the real phone, then we can use settings.
// But when we're running as part of xpcshell, there is no settings database
// and trying to use settings in this scenario causes lots of weird
// assertions at shutdown time.
if (typeof useSettings.result === "undefined") {
useSettings.result = !Services.env.get("XPCSHELL_TEST_PROFILE_DIR");
}
return useSettings.result;
}
function UpdateCheckListener(updatePrompt) { function UpdateCheckListener(updatePrompt) {
this._updatePrompt = updatePrompt; this._updatePrompt = updatePrompt;
} }
@@ -183,8 +198,10 @@ UpdatePrompt.prototype = {
showUpdateHistory: function UP_showUpdateHistory(aParent) { }, showUpdateHistory: function UP_showUpdateHistory(aParent) { },
showUpdateInstalled: function UP_showUpdateInstalled() { showUpdateInstalled: function UP_showUpdateInstalled() {
if (useSettings()) {
let lock = Services.settings.createLock(); let lock = Services.settings.createLock();
lock.set("deviceinfo.last_updated", Date.now(), null, null); lock.set("deviceinfo.last_updated", Date.now(), null, null);
}
}, },
// Custom functions // Custom functions
@@ -200,10 +217,12 @@ UpdatePrompt.prototype = {
}, },
setUpdateStatus: function UP_setUpdateStatus(aStatus) { setUpdateStatus: function UP_setUpdateStatus(aStatus) {
if (useSettings()) {
log("Setting gecko.updateStatus: " + aStatus); log("Setting gecko.updateStatus: " + aStatus);
let lock = Services.settings.createLock(); let lock = Services.settings.createLock();
lock.set("gecko.updateStatus", aStatus, null); lock.set("gecko.updateStatus", aStatus, null);
}
}, },
showApplyPrompt: function UP_showApplyPrompt(aUpdate) { showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
@@ -379,6 +398,7 @@ UpdatePrompt.prototype = {
#endif #endif
} }
if (useSettings()) {
// Save current os version in deviceinfo.previous_os // Save current os version in deviceinfo.previous_os
let lock = Services.settings.createLock({ let lock = Services.settings.createLock({
handle: callbackAfterSet, handle: callbackAfterSet,
@@ -393,6 +413,7 @@ UpdatePrompt.prototype = {
lock.set("deviceinfo.previous_os", value, null, null); lock.set("deviceinfo.previous_os", value, null, null);
} }
}); });
}
}, },
forceUpdateCheck: function UP_forceUpdateCheck() { forceUpdateCheck: function UP_forceUpdateCheck() {

View File

@@ -23,6 +23,11 @@ EXTRA_COMPONENTS += [
'YoutubeProtocolHandler.js', 'YoutubeProtocolHandler.js',
] ]
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
EXTRA_COMPONENTS += [
'SimulatorScreen.js'
]
EXTRA_PP_COMPONENTS += [ EXTRA_PP_COMPONENTS += [
'B2GComponents.manifest', 'B2GComponents.manifest',
'DirectoryProvider.js', 'DirectoryProvider.js',
@@ -41,6 +46,11 @@ EXTRA_JS_MODULES += [
'WebappsUpdater.jsm', 'WebappsUpdater.jsm',
] ]
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
EXTRA_JS_MODULES += [
'GlobalSimulatorScreen.jsm'
]
if CONFIG['MOZ_SERVICES_FXACCOUNTS']: if CONFIG['MOZ_SERVICES_FXACCOUNTS']:
EXTRA_COMPONENTS += [ EXTRA_COMPONENTS += [
'FxAccountsUIGlue.js' 'FxAccountsUIGlue.js'

View File

@@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/> <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

View File

@@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe"> <project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/> <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>

View File

@@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@@ -4,6 +4,6 @@
"branch": "", "branch": "",
"revision": "" "revision": ""
}, },
"revision": "91e5760ff948d3bef3959866c6a1744991560ef6", "revision": "6d2a2c5c58fce4b2263a7e5e654f6c4ccee5875a",
"repo_path": "/integration/gaia-central" "repo_path": "/integration/gaia-central"
} }

View File

@@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/> <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

View File

@@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@@ -176,7 +176,11 @@ fi
if test -n "$FXOS_SIMULATOR" -a -z "$GAIADIR" ; then if test -n "$FXOS_SIMULATOR" -a -z "$GAIADIR" ; then
AC_MSG_ERROR([FXOS_SIMULATOR=1 requires GAIADIR to be defined]) AC_MSG_ERROR([FXOS_SIMULATOR=1 requires GAIADIR to be defined])
fi fi
AC_SUBST(FXOS_SIMULATOR)
if test -n "$FXOS_SIMULATOR" ; then
AC_DEFINE(FXOS_SIMULATOR)
AC_SUBST(FXOS_SIMULATOR)
fi
MOZ_ARG_WITH_STRING(gonk, MOZ_ARG_WITH_STRING(gonk,
[ --with-gonk=DIR [ --with-gonk=DIR

View File

@@ -16,7 +16,8 @@
#include "EncodedBufferCache.h" #include "EncodedBufferCache.h"
#include "nsIDOMFile.h" #include "nsIDOMFile.h"
#include "mozilla/dom/BlobEvent.h" #include "mozilla/dom/BlobEvent.h"
#include "nsIPrincipal.h"
#include "nsMimeTypes.h"
#include "mozilla/dom/AudioStreamTrack.h" #include "mozilla/dom/AudioStreamTrack.h"
#include "mozilla/dom/VideoStreamTrack.h" #include "mozilla/dom/VideoStreamTrack.h"
@@ -320,7 +321,19 @@ private:
// Allocate encoder and bind with union stream. // Allocate encoder and bind with union stream.
// At this stage, the API doesn't allow UA to choose the output mimeType format. // At this stage, the API doesn't allow UA to choose the output mimeType format.
nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
if (doc) {
doc->NodePrincipal()->GetAppStatus(&appStatus);
}
// Only allow certificated application can assign AUDIO_3GPP
if (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP)) {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), aTrackTypes);
} else {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes); mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes);
}
if (!mEncoder) { if (!mEncoder) {
DoSessionEndTask(NS_ERROR_ABORT); DoSessionEndTask(NS_ERROR_ABORT);
@@ -579,7 +592,9 @@ MediaRecorder::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
/* static */ already_AddRefed<MediaRecorder> /* static */ already_AddRefed<MediaRecorder>
MediaRecorder::Constructor(const GlobalObject& aGlobal, MediaRecorder::Constructor(const GlobalObject& aGlobal,
DOMMediaStream& aStream, ErrorResult& aRv) DOMMediaStream& aStream,
const MediaRecorderOptions& aInitDict,
ErrorResult& aRv)
{ {
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports()); nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
if (!sgo) { if (!sgo) {
@@ -594,6 +609,7 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal,
} }
nsRefPtr<MediaRecorder> object = new MediaRecorder(aStream, ownerWindow); nsRefPtr<MediaRecorder> object = new MediaRecorder(aStream, ownerWindow);
object->SetMimeType(aInitDict.mMimeType);
return object.forget(); return object.forget();
} }

View File

@@ -20,6 +20,7 @@ class EncodedBufferCache;
class MediaEncoder; class MediaEncoder;
class ProcessedMediaStream; class ProcessedMediaStream;
class MediaInputPort; class MediaInputPort;
struct MediaRecorderOptions;
namespace dom { namespace dom {
@@ -75,7 +76,9 @@ public:
static already_AddRefed<MediaRecorder> static already_AddRefed<MediaRecorder>
Constructor(const GlobalObject& aGlobal, Constructor(const GlobalObject& aGlobal,
DOMMediaStream& aStream, ErrorResult& aRv); DOMMediaStream& aStream,
const MediaRecorderOptions& aInitDict,
ErrorResult& aRv);
// EventHandler // EventHandler
IMPL_EVENT_HANDLER(dataavailable) IMPL_EVENT_HANDLER(dataavailable)

View File

@@ -115,7 +115,7 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes)
(aMIMEType.EqualsLiteral(VIDEO_MP4) || (aMIMEType.EqualsLiteral(VIDEO_MP4) ||
(aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) { (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) {
if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) { if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
audioEncoder = new OmxAudioTrackEncoder(); audioEncoder = new OmxAACAudioTrackEncoder();
NS_ENSURE_TRUE(audioEncoder, nullptr); NS_ENSURE_TRUE(audioEncoder, nullptr);
} }
videoEncoder = new OmxVideoTrackEncoder(); videoEncoder = new OmxVideoTrackEncoder();
@@ -123,6 +123,14 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes)
NS_ENSURE_TRUE(writer, nullptr); NS_ENSURE_TRUE(writer, nullptr);
NS_ENSURE_TRUE(videoEncoder, nullptr); NS_ENSURE_TRUE(videoEncoder, nullptr);
mimeType = NS_LITERAL_STRING(VIDEO_MP4); mimeType = NS_LITERAL_STRING(VIDEO_MP4);
} else if (MediaEncoder::IsOMXEncoderEnabled() &&
(aMIMEType.EqualsLiteral(AUDIO_3GPP))) {
audioEncoder = new OmxAMRAudioTrackEncoder();
NS_ENSURE_TRUE(audioEncoder, nullptr);
writer = new ISOMediaWriter(aTrackTypes, ISOMediaWriter::TYPE_FRAG_3GP);
NS_ENSURE_TRUE(writer, nullptr);
mimeType = NS_LITERAL_STRING(AUDIO_3GPP);
} }
#endif // MOZ_OMX_ENCODER #endif // MOZ_OMX_ENCODER
else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() && else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&

View File

@@ -67,6 +67,8 @@ OmxVideoTrackEncoder::GetMetadata()
nsRefPtr<AVCTrackMetadata> meta = new AVCTrackMetadata(); nsRefPtr<AVCTrackMetadata> meta = new AVCTrackMetadata();
meta->mWidth = mFrameWidth; meta->mWidth = mFrameWidth;
meta->mHeight = mFrameHeight; meta->mHeight = mFrameHeight;
meta->mDisplayWidth = mDisplayWidth;
meta->mDisplayHeight = mDisplayHeight;
meta->mFrameRate = ENCODER_CONFIG_FRAME_RATE; meta->mFrameRate = ENCODER_CONFIG_FRAME_RATE;
return meta.forget(); return meta.forget();
} }
@@ -155,49 +157,6 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
return NS_OK; return NS_OK;
} }
nsresult
OmxAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
{
mChannels = aChannels;
mSamplingRate = aSamplingRate;
mEncoder = OMXCodecWrapper::CreateAACEncoder();
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
nsresult rv = mEncoder->Configure(mChannels, mSamplingRate);
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mInitialized = (rv == NS_OK);
mReentrantMonitor.NotifyAll();
return NS_OK;
}
already_AddRefed<TrackMetadataBase>
OmxAudioTrackEncoder::GetMetadata()
{
{
// Wait if mEncoder is not initialized nor is being canceled.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
while (!mCanceled && !mInitialized) {
mReentrantMonitor.Wait();
}
}
if (mCanceled || mEncodingComplete) {
return nullptr;
}
nsRefPtr<AACTrackMetadata> meta = new AACTrackMetadata();
meta->mChannels = mChannels;
meta->mSampleRate = mSamplingRate;
meta->mFrameSize = OMXCodecWrapper::kAACFrameSize;
meta->mFrameDuration = OMXCodecWrapper::kAACFrameDuration;
return meta.forget();
}
nsresult nsresult
OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer) OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
{ {
@@ -218,8 +177,15 @@ OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
} }
nsRefPtr<EncodedFrame> audiodata = new EncodedFrame(); nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
if (mEncoder->GetCodecType() == OMXCodecWrapper::AAC_ENC) {
audiodata->SetFrameType(isCSD ? audiodata->SetFrameType(isCSD ?
EncodedFrame::AAC_CSD : EncodedFrame::AAC_AUDIO_FRAME); EncodedFrame::AAC_CSD : EncodedFrame::AAC_AUDIO_FRAME);
} else if (mEncoder->GetCodecType() == OMXCodecWrapper::AMR_NB_ENC){
audiodata->SetFrameType(isCSD ?
EncodedFrame::AMR_AUDIO_CSD : EncodedFrame::AMR_AUDIO_FRAME);
} else {
MOZ_ASSERT("audio codec not supported");
}
audiodata->SetTimeStamp(outTimeUs); audiodata->SetTimeStamp(outTimeUs);
rv = audiodata->SwapInFrameData(frameData); rv = audiodata->SwapInFrameData(frameData);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@@ -277,4 +243,82 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
return NS_OK; return NS_OK;
} }
nsresult
OmxAACAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
{
mChannels = aChannels;
mSamplingRate = aSamplingRate;
mEncoder = OMXCodecWrapper::CreateAACEncoder();
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
nsresult rv = mEncoder->Configure(mChannels, mSamplingRate, mSamplingRate);
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mInitialized = (rv == NS_OK);
mReentrantMonitor.NotifyAll();
return NS_OK;
}
already_AddRefed<TrackMetadataBase>
OmxAACAudioTrackEncoder::GetMetadata()
{
{
// Wait if mEncoder is not initialized nor is being canceled.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
while (!mCanceled && !mInitialized) {
mReentrantMonitor.Wait();
}
}
if (mCanceled || mEncodingComplete) {
return nullptr;
}
nsRefPtr<AACTrackMetadata> meta = new AACTrackMetadata();
meta->mChannels = mChannels;
meta->mSampleRate = mSamplingRate;
meta->mFrameSize = OMXCodecWrapper::kAACFrameSize;
meta->mFrameDuration = OMXCodecWrapper::kAACFrameDuration;
return meta.forget();
}
nsresult
OmxAMRAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
{
mChannels = aChannels;
mSamplingRate = aSamplingRate;
mEncoder = OMXCodecWrapper::CreateAMRNBEncoder();
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
nsresult rv = mEncoder->Configure(mChannels, mSamplingRate, AMR_NB_SAMPLERATE);
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mInitialized = (rv == NS_OK);
mReentrantMonitor.NotifyAll();
return NS_OK;
}
already_AddRefed<TrackMetadataBase>
OmxAMRAudioTrackEncoder::GetMetadata()
{
{
// Wait if mEncoder is not initialized nor is being canceled.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
while (!mCanceled && !mInitialized) {
mReentrantMonitor.Wait();
}
}
if (mCanceled || mEncodingComplete) {
return nullptr;
}
nsRefPtr<AMRTrackMetadata> meta = new AMRTrackMetadata();
return meta.forget();
}
} }

View File

@@ -43,26 +43,54 @@ private:
nsAutoPtr<android::OMXVideoEncoder> mEncoder; nsAutoPtr<android::OMXVideoEncoder> mEncoder;
}; };
class OmxAudioTrackEncoder MOZ_FINAL : public AudioTrackEncoder class OmxAudioTrackEncoder : public AudioTrackEncoder
{ {
public: public:
OmxAudioTrackEncoder() OmxAudioTrackEncoder()
: AudioTrackEncoder() : AudioTrackEncoder()
{} {}
already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE; already_AddRefed<TrackMetadataBase> GetMetadata() = 0;
nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE; nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
protected: protected:
nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE; nsresult Init(int aChannels, int aSamplingRate) = 0;
private:
// Append encoded frames to aContainer. // Append encoded frames to aContainer.
nsresult AppendEncodedFrames(EncodedFrameContainer& aContainer); nsresult AppendEncodedFrames(EncodedFrameContainer& aContainer);
nsAutoPtr<android::OMXAudioEncoder> mEncoder; nsAutoPtr<android::OMXAudioEncoder> mEncoder;
}; };
class OmxAACAudioTrackEncoder MOZ_FINAL : public OmxAudioTrackEncoder
{
public:
OmxAACAudioTrackEncoder()
: OmxAudioTrackEncoder()
{}
already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
protected:
nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
};
class OmxAMRAudioTrackEncoder MOZ_FINAL : public OmxAudioTrackEncoder
{
public:
OmxAMRAudioTrackEncoder()
: OmxAudioTrackEncoder()
{}
enum {
AMR_NB_SAMPLERATE = 8000,
};
already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
protected:
nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
};
} }
#endif #endif

View File

@@ -49,10 +49,14 @@ public:
// The base class for video metadata. // The base class for video metadata.
class VideoTrackMetadata : public TrackMetadataBase { class VideoTrackMetadata : public TrackMetadataBase {
public: public:
// VideoHeight and VideoWidth are the frame size of the elementary stream.
virtual uint32_t GetVideoHeight() = 0; virtual uint32_t GetVideoHeight() = 0;
virtual uint32_t GetVideoWidth() = 0; virtual uint32_t GetVideoWidth() = 0;
// VideoDisplayHeight and VideoDisplayWidth are the display frame size.
virtual uint32_t GetVideoDisplayHeight() = 0;
virtual uint32_t GetVideoDisplayWidth() = 0;
// VideoClockRate is the number of samples per second in video frame's // VideoClockRate is the number of samples per second in video frame's
// timestamp. // timestamp.
// For example, if VideoClockRate is 90k Hz and VideoFrameRate is // For example, if VideoClockRate is 90k Hz and VideoFrameRate is

View File

@@ -167,6 +167,7 @@ nsresult
ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta) ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta)
{ {
if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC || if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC ||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR ||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC) { aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC) {
mMetaArray.AppendElement(aTrackMeta); mMetaArray.AppendElement(aTrackMeta);
return NS_OK; return NS_OK;
@@ -178,7 +179,8 @@ nsresult
ISOControl::GetAudioMetadata(nsRefPtr<AudioTrackMetadata>& aAudMeta) ISOControl::GetAudioMetadata(nsRefPtr<AudioTrackMetadata>& aAudMeta)
{ {
for (uint32_t i = 0; i < mMetaArray.Length() ; i++) { for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC) { if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC ||
mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR) {
aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get()); aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get());
return NS_OK; return NS_OK;
} }

View File

@@ -1179,9 +1179,14 @@ TrackHeaderBox::Generate(uint32_t* aBoxSize)
volume = (mTrackType == Audio_Track ? 0x0100 : 0); volume = (mTrackType == Audio_Track ? 0x0100 : 0);
if (mTrackType == Video_Track) { if (mTrackType == Video_Track) {
width = mVideoMeta->GetVideoDisplayWidth() << 16;
height = mVideoMeta->GetVideoDisplayHeight() << 16;
// Check display size, using the pixel size if any of them is invalid.
if (!width || !height) {
width = mVideoMeta->GetVideoWidth() << 16; width = mVideoMeta->GetVideoWidth() << 16;
height = mVideoMeta->GetVideoHeight() << 16; height = mVideoMeta->GetVideoHeight() << 16;
} }
}
size += sizeof(creation_time) + size += sizeof(creation_time) +
sizeof(modification_time) + sizeof(modification_time) +

View File

@@ -45,6 +45,8 @@ public:
// VideoTrackMetadata members // VideoTrackMetadata members
uint32_t GetVideoHeight() MOZ_OVERRIDE { return mHeight; } uint32_t GetVideoHeight() MOZ_OVERRIDE { return mHeight; }
uint32_t GetVideoWidth() MOZ_OVERRIDE {return mWidth; } uint32_t GetVideoWidth() MOZ_OVERRIDE {return mWidth; }
uint32_t GetVideoDisplayHeight() MOZ_OVERRIDE { return mDisplayHeight; }
uint32_t GetVideoDisplayWidth() MOZ_OVERRIDE { return mDisplayWidth; }
uint32_t GetVideoClockRate() MOZ_OVERRIDE { return AVC_CLOCK_RATE; } uint32_t GetVideoClockRate() MOZ_OVERRIDE { return AVC_CLOCK_RATE; }
uint32_t GetVideoFrameRate() MOZ_OVERRIDE { return mFrameRate; } uint32_t GetVideoFrameRate() MOZ_OVERRIDE { return mFrameRate; }
@@ -55,6 +57,8 @@ public:
AVCTrackMetadata() AVCTrackMetadata()
: mHeight(0) : mHeight(0)
, mWidth(0) , mWidth(0)
, mDisplayHeight(0)
, mDisplayWidth(0)
, mFrameRate(0) { , mFrameRate(0) {
MOZ_COUNT_CTOR(AVCTrackMetadata); MOZ_COUNT_CTOR(AVCTrackMetadata);
} }
@@ -62,6 +66,8 @@ public:
uint32_t mHeight; uint32_t mHeight;
uint32_t mWidth; uint32_t mWidth;
uint32_t mDisplayHeight;
uint32_t mDisplayWidth;
uint32_t mFrameRate; // frames per second uint32_t mFrameRate; // frames per second
}; };

View File

@@ -27,6 +27,8 @@ using namespace mozilla::layers;
#define ENCODER_CONFIG_I_FRAME_INTERVAL 1 #define ENCODER_CONFIG_I_FRAME_INTERVAL 1
// Wait up to 5ms for input buffers. // Wait up to 5ms for input buffers.
#define INPUT_BUFFER_TIMEOUT_US (5 * 1000ll) #define INPUT_BUFFER_TIMEOUT_US (5 * 1000ll)
// AMR NB kbps
#define AMRNB_BITRATE 12200
#define CODEC_ERROR(args...) \ #define CODEC_ERROR(args...) \
do { \ do { \
@@ -45,6 +47,16 @@ OMXCodecWrapper::CreateAACEncoder()
return aac.forget(); return aac.forget();
} }
OMXAudioEncoder*
OMXCodecWrapper::CreateAMRNBEncoder()
{
nsAutoPtr<OMXAudioEncoder> amr(new OMXAudioEncoder(CodecType::AMR_NB_ENC));
// Return the object only when media codec is valid.
NS_ENSURE_TRUE(amr->IsValid(), nullptr);
return amr.forget();
}
OMXVideoEncoder* OMXVideoEncoder*
OMXCodecWrapper::CreateAVCEncoder() OMXCodecWrapper::CreateAVCEncoder()
{ {
@@ -56,7 +68,9 @@ OMXCodecWrapper::CreateAVCEncoder()
} }
OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType) OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType)
: mStarted(false) : mCodecType(aCodecType)
, mStarted(false)
, mAMRCSDProvided(false)
{ {
ProcessState::self()->startThreadPool(); ProcessState::self()->startThreadPool();
@@ -65,6 +79,8 @@ OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType)
if (aCodecType == CodecType::AVC_ENC) { if (aCodecType == CodecType::AVC_ENC) {
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_VIDEO_AVC, true); mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_VIDEO_AVC, true);
} else if (aCodecType == CodecType::AMR_NB_ENC) {
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AMR_NB, true);
} else if (aCodecType == CodecType::AAC_ENC) { } else if (aCodecType == CodecType::AAC_ENC) {
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AAC, true); mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AAC, true);
} else { } else {
@@ -380,28 +396,53 @@ void OMXVideoEncoder::AppendFrame(nsTArray<uint8_t>* aOutputBuf,
} }
nsresult nsresult
OMXAudioEncoder::Configure(int aChannels, int aSamplingRate) OMXAudioEncoder::Configure(int aChannels, int aInputSampleRate,
int aEncodedSampleRate)
{ {
MOZ_ASSERT(!mStarted); MOZ_ASSERT(!mStarted);
NS_ENSURE_TRUE(aChannels > 0 && aSamplingRate > 0, NS_ERROR_INVALID_ARG); NS_ENSURE_TRUE(aChannels > 0 && aInputSampleRate > 0 && aEncodedSampleRate >= 0,
NS_ERROR_INVALID_ARG);
if (aInputSampleRate != aEncodedSampleRate) {
int error;
mResampler = speex_resampler_init(aChannels,
aInputSampleRate,
aEncodedSampleRate,
SPEEX_RESAMPLER_QUALITY_DEFAULT,
&error);
if (error != RESAMPLER_ERR_SUCCESS) {
return NS_ERROR_FAILURE;
}
speex_resampler_skip_zeros(mResampler);
}
// Set up configuration parameters for AAC encoder. // Set up configuration parameters for AAC encoder.
sp<AMessage> format = new AMessage; sp<AMessage> format = new AMessage;
// Fixed values. // Fixed values.
if (mCodecType == AAC_ENC) {
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
format->setInt32("bitrate", kAACBitrate);
format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC); format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
format->setInt32("bitrate", kAACBitrate);
format->setInt32("sample-rate", aInputSampleRate);
} else if (mCodecType == AMR_NB_ENC) {
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
format->setInt32("bitrate", AMRNB_BITRATE);
format->setInt32("sample-rate", aEncodedSampleRate);
} else {
MOZ_ASSERT(false, "Can't support this codec type!!");
}
// Input values. // Input values.
format->setInt32("channel-count", aChannels); format->setInt32("channel-count", aChannels);
format->setInt32("sample-rate", aSamplingRate);
status_t result = mCodec->configure(format, nullptr, nullptr, status_t result = mCodec->configure(format, nullptr, nullptr,
MediaCodec::CONFIGURE_FLAG_ENCODE); MediaCodec::CONFIGURE_FLAG_ENCODE);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE); NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
mChannels = aChannels; mChannels = aChannels;
mSampleDuration = 1000000 / aSamplingRate; mSampleDuration = 1000000 / aInputSampleRate;
mResamplingRatio = aEncodedSampleRate > 0 ? 1.0 *
aEncodedSampleRate / aInputSampleRate : 1.0;
result = Start(); result = Start();
return result == OK ? NS_OK : NS_ERROR_FAILURE; return result == OK ? NS_OK : NS_ERROR_FAILURE;
@@ -474,6 +515,14 @@ private:
size_t mOffset; size_t mOffset;
}; };
OMXAudioEncoder::~OMXAudioEncoder()
{
if (mResampler) {
speex_resampler_destroy(mResampler);
mResampler = nullptr;
}
}
nsresult nsresult
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags) OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
{ {
@@ -495,16 +544,16 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
} }
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE); NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
size_t samplesCopied = 0; // Number of copied samples. size_t sourceSamplesCopied = 0; // Number of copied samples.
if (numSamples > 0) { if (numSamples > 0) {
// Copy input PCM data to input buffer until queue is empty. // Copy input PCM data to input buffer until queue is empty.
AudioSegment::ChunkIterator iter(const_cast<AudioSegment&>(aSegment)); AudioSegment::ChunkIterator iter(const_cast<AudioSegment&>(aSegment));
while (!iter.IsEnded()) { while (!iter.IsEnded()) {
AudioChunk chunk = *iter; AudioChunk chunk = *iter;
size_t samplesToCopy = chunk.GetDuration(); // Number of samples to copy. size_t sourceSamplesToCopy = chunk.GetDuration(); // Number of samples to copy.
size_t bytesToCopy = samplesToCopy * mChannels * sizeof(AudioDataValue); size_t bytesToCopy = sourceSamplesToCopy * mChannels *
sizeof(AudioDataValue) * mResamplingRatio;
if (bytesToCopy > buffer.AvailableSize()) { if (bytesToCopy > buffer.AvailableSize()) {
// Not enough space left in input buffer. Send it to encoder and get a // Not enough space left in input buffer. Send it to encoder and get a
// new one. // new one.
@@ -515,32 +564,47 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
if (result == -EAGAIN) { if (result == -EAGAIN) {
// All input buffers are full. Caller can try again later after // All input buffers are full. Caller can try again later after
// consuming some output buffers. // consuming some output buffers.
aSegment.RemoveLeading(samplesCopied); aSegment.RemoveLeading(sourceSamplesCopied);
return NS_OK; return NS_OK;
} }
mTimestamp += samplesCopied * mSampleDuration; mTimestamp += sourceSamplesCopied * mSampleDuration;
samplesCopied = 0; sourceSamplesCopied = 0;
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE); NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
} }
AudioDataValue* dst = reinterpret_cast<AudioDataValue*>(buffer.GetPointer()); AudioDataValue* dst = reinterpret_cast<AudioDataValue*>(buffer.GetPointer());
uint32_t dstSamplesCopied = sourceSamplesToCopy;
if (!chunk.IsNull()) { if (!chunk.IsNull()) {
if (mResampler) {
nsAutoTArray<AudioDataValue, 9600> pcm;
pcm.SetLength(bytesToCopy);
// Append the interleaved data to input buffer. // Append the interleaved data to input buffer.
AudioTrackEncoder::InterleaveTrackData(chunk, samplesToCopy, mChannels, AudioTrackEncoder::InterleaveTrackData(chunk, sourceSamplesToCopy,
mChannels,
pcm.Elements());
uint32_t inframes = sourceSamplesToCopy;
short* in = reinterpret_cast<short*>(pcm.Elements());
speex_resampler_process_interleaved_int(mResampler, in, &inframes,
dst, &dstSamplesCopied);
} else {
AudioTrackEncoder::InterleaveTrackData(chunk, sourceSamplesToCopy,
mChannels,
dst); dst);
dstSamplesCopied = sourceSamplesToCopy * mChannels;
}
} else { } else {
// Silence. // Silence.
memset(dst, 0, bytesToCopy); memset(dst, 0, mResamplingRatio * sourceSamplesToCopy * sizeof(AudioDataValue));
} }
samplesCopied += samplesToCopy; sourceSamplesCopied += sourceSamplesToCopy;
buffer.IncreaseOffset(bytesToCopy); buffer.IncreaseOffset(dstSamplesCopied * sizeof(AudioDataValue));
iter.Next(); iter.Next();
} }
if (samplesCopied > 0) { if (sourceSamplesCopied > 0) {
aSegment.RemoveLeading(samplesCopied); aSegment.RemoveLeading(sourceSamplesCopied);
} }
} else if (aInputFlags & BUFFER_EOS) { } else if (aInputFlags & BUFFER_EOS) {
// No audio data left in segment but we still have to feed something to // No audio data left in segment but we still have to feed something to
@@ -548,10 +612,10 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
size_t bytesToCopy = mChannels * sizeof(AudioDataValue); size_t bytesToCopy = mChannels * sizeof(AudioDataValue);
memset(buffer.GetPointer(), 0, bytesToCopy); memset(buffer.GetPointer(), 0, bytesToCopy);
buffer.IncreaseOffset(bytesToCopy); buffer.IncreaseOffset(bytesToCopy);
samplesCopied = 1; sourceSamplesCopied = 1;
} }
if (samplesCopied > 0) { if (sourceSamplesCopied > 0) {
int flags = aInputFlags; int flags = aInputFlags;
if (aSegment.GetDuration() > 0) { if (aSegment.GetDuration() > 0) {
// Don't signal EOS until source segment is empty. // Don't signal EOS until source segment is empty.
@@ -560,7 +624,7 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
result = buffer.Enqueue(mTimestamp, flags); result = buffer.Enqueue(mTimestamp, flags);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE); NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
mTimestamp += samplesCopied * mSampleDuration; mTimestamp += sourceSamplesCopied * mSampleDuration;
} }
return NS_OK; return NS_OK;
@@ -663,6 +727,20 @@ OMXCodecWrapper::GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
mCodec->releaseOutputBuffer(index); mCodec->releaseOutputBuffer(index);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
} else if ((mCodecType == AMR_NB_ENC) && !mAMRCSDProvided){
// OMX AMR codec won't provide csd data, need to generate a fake one.
nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
// Decoder config descriptor
const uint8_t decConfig[] = {
0x0, 0x0, 0x0, 0x0, // vendor: 4 bytes
0x0, // decoder version
0x83, 0xFF, // mode set: all enabled
0x00, // mode change period
0x01, // frames per sample
};
aOutputBuf->AppendElements(decConfig, sizeof(decConfig));
outFlags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
mAMRCSDProvided = true;
} else { } else {
AppendFrame(aOutputBuf, omxBuf->data(), omxBuf->size()); AppendFrame(aOutputBuf, omxBuf->data(), omxBuf->size());
} }

View File

@@ -15,6 +15,8 @@
#include "GonkNativeWindow.h" #include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h" #include "GonkNativeWindowClient.h"
#include <speex/speex_resampler.h>
namespace android { namespace android {
class OMXAudioEncoder; class OMXAudioEncoder;
@@ -53,6 +55,7 @@ public:
// Codec types. // Codec types.
enum CodecType { enum CodecType {
AAC_ENC, // AAC encoder. AAC_ENC, // AAC encoder.
AMR_NB_ENC, // AMR_NB encoder.
AVC_ENC, // AVC/H.264 encoder. AVC_ENC, // AVC/H.264 encoder.
TYPE_COUNT TYPE_COUNT
}; };
@@ -83,6 +86,9 @@ public:
/** Create a AAC audio encoder. Returns nullptr when failed. */ /** Create a AAC audio encoder. Returns nullptr when failed. */
static OMXAudioEncoder* CreateAACEncoder(); static OMXAudioEncoder* CreateAACEncoder();
/** Create a AMR audio encoder. Returns nullptr when failed. */
static OMXAudioEncoder* CreateAMRNBEncoder();
/** Create a AVC/H.264 video encoder. Returns nullptr when failed. */ /** Create a AVC/H.264 video encoder. Returns nullptr when failed. */
static OMXVideoEncoder* CreateAVCEncoder(); static OMXVideoEncoder* CreateAVCEncoder();
@@ -97,7 +103,10 @@ public:
nsresult GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf, nsresult GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
int64_t* aOutputTimestamp, int* aOutputFlags, int64_t* aOutputTimestamp, int* aOutputFlags,
int64_t aTimeOut); int64_t aTimeOut);
/*
* Get the codec type
*/
int GetCodecType() { return mCodecType; }
protected: protected:
/** /**
* See whether the object has been initialized successfully and is ready to * See whether the object has been initialized successfully and is ready to
@@ -160,7 +169,9 @@ private:
Vector<sp<ABuffer> > mInputBufs; // MediaCodec buffers to hold input data. Vector<sp<ABuffer> > mInputBufs; // MediaCodec buffers to hold input data.
Vector<sp<ABuffer> > mOutputBufs; // MediaCodec buffers to hold output data. Vector<sp<ABuffer> > mOutputBufs; // MediaCodec buffers to hold output data.
int mCodecType;
bool mStarted; // Has MediaCodec been started? bool mStarted; // Has MediaCodec been started?
bool mAMRCSDProvided;
}; };
/** /**
@@ -172,8 +183,9 @@ public:
/** /**
* Configure audio codec parameters and start media codec. It must be called * Configure audio codec parameters and start media codec. It must be called
* before calling Encode() and GetNextEncodedFrame(). * before calling Encode() and GetNextEncodedFrame().
* aReSamplingRate = 0 means no resampler required
*/ */
nsresult Configure(int aChannelCount, int aSampleRate); nsresult Configure(int aChannelCount, int aInputSampleRate, int aEncodedSampleRate);
/** /**
* Encode 16-bit PCM audio samples stored in aSegment. To notify end of * Encode 16-bit PCM audio samples stored in aSegment. To notify end of
@@ -183,10 +195,10 @@ public:
*/ */
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0); nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
~OMXAudioEncoder();
protected: protected:
virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf, virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
ABuffer* aData) MOZ_OVERRIDE; ABuffer* aData) MOZ_OVERRIDE;
private: private:
// Hide these. User should always use creator functions to get a media codec. // Hide these. User should always use creator functions to get a media codec.
OMXAudioEncoder() MOZ_DELETE; OMXAudioEncoder() MOZ_DELETE;
@@ -199,15 +211,24 @@ private:
*/ */
OMXAudioEncoder(CodecType aCodecType) OMXAudioEncoder(CodecType aCodecType)
: OMXCodecWrapper(aCodecType) : OMXCodecWrapper(aCodecType)
, mResampler(nullptr)
, mChannels(0) , mChannels(0)
, mTimestamp(0) , mTimestamp(0)
, mSampleDuration(0) {} , mSampleDuration(0)
, mResamplingRatio(0) {}
// For creator function to access hidden constructor. // For creator function to access hidden constructor.
friend class OMXCodecWrapper; friend class OMXCodecWrapper;
/**
* If the input sample rate does not divide 48kHz evenly, the input data are
* resampled.
*/
SpeexResamplerState* mResampler;
// Number of audio channels. // Number of audio channels.
size_t mChannels; size_t mChannels;
float mResamplingRatio;
// The total duration of audio samples that have been encoded in microseconds. // The total duration of audio samples that have been encoded in microseconds.
int64_t mTimestamp; int64_t mTimestamp;
// Time per audio sample in microseconds. // Time per audio sample in microseconds.

View File

@@ -30,12 +30,10 @@ function startTest(test, token) {
} }
manager.started(token); manager.started(token);
var a = new Audio(test.name); var a = new Audio(test.name);
a.addEventListener("canplaythrough", a.autoplay = true;
function(e){ e.target.play(); },
false);
a.addEventListener("ended", a.addEventListener("ended",
function(e){ function(e){
ok(true, "We should get to the end. Oh look we did."); ok(true, "[" + a.src + "]We should get to the end. Oh look we did.");
manager.finished(token); manager.finished(token);
}, },
false); false);

View File

@@ -61,7 +61,7 @@ function runTest()
// Ensure that the preallocated process initially gets BACKGROUND priority. // Ensure that the preallocated process initially gets BACKGROUND priority.
// That's it. // That's it.
expectProcessCreated().then(function(childID) { expectProcessCreated().then(function(childID) {
return expectPriorityChange(childID, 'BACKGROUND'); return expectPriorityChange(childID, 'PREALLOC');
}).then(function() { }).then(function() {
cleanUp(); cleanUp();
SimpleTest.finish(); SimpleTest.finish();

View File

@@ -448,7 +448,7 @@ ContentParent::PreallocateAppProcess()
new ContentParent(/* app = */ nullptr, new ContentParent(/* app = */ nullptr,
/* isForBrowserElement = */ false, /* isForBrowserElement = */ false,
/* isForPreallocated = */ true, /* isForPreallocated = */ true,
PROCESS_PRIORITY_BACKGROUND); PROCESS_PRIORITY_PREALLOC);
process->Init(); process->Init();
return process.forget(); return process.forget();
} }
@@ -1453,7 +1453,7 @@ ContentParent::ContentParent(ContentParent* aTemplate,
// memory priority, which it has inherited from this process. // memory priority, which it has inherited from this process.
ProcessPriority priority; ProcessPriority priority;
if (IsPreallocated()) { if (IsPreallocated()) {
priority = PROCESS_PRIORITY_BACKGROUND; priority = PROCESS_PRIORITY_PREALLOC;
} else { } else {
priority = PROCESS_PRIORITY_FOREGROUND; priority = PROCESS_PRIORITY_FOREGROUND;
} }

View File

@@ -945,6 +945,10 @@ ParticularProcessPriorityManager::ComputePriority()
ProcessCPUPriority ProcessCPUPriority
ParticularProcessPriorityManager::ComputeCPUPriority() ParticularProcessPriorityManager::ComputeCPUPriority()
{ {
if (mPriority == PROCESS_PRIORITY_PREALLOC) {
return PROCESS_CPU_PRIORITY_LOW;
}
if (mPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) { if (mPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
return PROCESS_CPU_PRIORITY_NORMAL; return PROCESS_CPU_PRIORITY_NORMAL;
} }

View File

@@ -336,7 +336,9 @@ function isNetworkReady() {
.getService(SpecialPowers.Ci.nsINetworkInterfaceListService); .getService(SpecialPowers.Ci.nsINetworkInterfaceListService);
var itfList = listService.getDataInterfaceList( var itfList = listService.getDataInterfaceList(
SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_MMS_INTERFACES | SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_MMS_INTERFACES |
SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES); SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES |
SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_IMS_INTERFACES |
SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_DUN_INTERFACES);
var num = itfList.getNumberOfInterface(); var num = itfList.getNumberOfInterface();
for (var i = 0; i < num; i++) { for (var i = 0; i < num; i++) {
if (itfList.getInterface(i).ip) { if (itfList.getInterface(i).ip) {

View File

@@ -14,7 +14,7 @@ interface nsIDOMMozSmsSegmentInfo;
#define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1" #define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1"
%} %}
[scriptable, builtinclass, uuid(67d038b2-0039-11e3-9fd3-83de190730f7)] [scriptable, builtinclass, uuid(17fce9e4-af56-11e3-83d9-b71055e95493)]
interface nsIMobileMessageService : nsISupports interface nsIMobileMessageService : nsISupports
{ {
[implicit_jscontext] [implicit_jscontext]
@@ -27,9 +27,9 @@ interface nsIMobileMessageService : nsISupports
in DOMString receiver, in DOMString receiver,
in DOMString body, in DOMString body,
in DOMString messageClass, in DOMString messageClass,
in jsval timestamp, in unsigned long long timestamp,
in jsval sentTimestamp, in unsigned long long sentTimestamp,
in jsval deliveryTimestamp, in unsigned long long deliveryTimestamp,
in bool read); in bool read);
[implicit_jscontext] [implicit_jscontext]
@@ -40,13 +40,13 @@ interface nsIMobileMessageService : nsISupports
in jsval deliveryInfo, in jsval deliveryInfo,
in DOMString sender, in DOMString sender,
in jsval receivers, in jsval receivers,
in jsval timestamp, in unsigned long long timestamp,
in jsval sentTimestamp, in unsigned long long sentTimestamp,
in boolean read, in boolean read,
in DOMString subject, in DOMString subject,
in DOMString smil, in DOMString smil,
in jsval attachments, in jsval attachments,
in jsval expiryDate, in unsigned long long expiryDate,
in boolean readReportRequested); in boolean readReportRequested);
nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments, nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments,
@@ -56,7 +56,7 @@ interface nsIMobileMessageService : nsISupports
[implicit_jscontext] [implicit_jscontext]
nsIDOMMozMobileMessageThread createThread(in unsigned long long id, nsIDOMMozMobileMessageThread createThread(in unsigned long long id,
in jsval participants, in jsval participants,
in jsval timestamp, in unsigned long long timestamp,
in DOMString lastMessageSubject, in DOMString lastMessageSubject,
in DOMString body, in DOMString body,
in unsigned long long unreadCount, in unsigned long long unreadCount,

View File

@@ -1,42 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MessageUtils_h
#define MessageUtils_h
/**
* A helper function to convert the JS value to an integer value for time.
*
* @params aCx
* The JS context.
* @params aTime
* Can be an object or a number.
* @params aReturn
* The integer value to return.
* @return NS_OK if the convertion succeeds.
*/
static nsresult
convertTimeToInt(JSContext* aCx, const JS::Value& aTime, uint64_t& aReturn)
{
if (aTime.isObject()) {
JS::Rooted<JSObject*> timestampObj(aCx, &aTime.toObject());
if (!JS_ObjectIsDate(aCx, timestampObj)) {
return NS_ERROR_INVALID_ARG;
}
aReturn = js_DateGetMsecSinceEpoch(timestampObj);
} else {
if (!aTime.isNumber()) {
return NS_ERROR_INVALID_ARG;
}
double number = aTime.toNumber();
if (static_cast<uint64_t>(number) != number) {
return NS_ERROR_INVALID_ARG;
}
aReturn = static_cast<uint64_t>(number);
}
return NS_OK;
}
#endif

View File

@@ -16,7 +16,6 @@
#include "mozilla/dom/mobilemessage/SmsTypes.h" #include "mozilla/dom/mobilemessage/SmsTypes.h"
#include "nsDOMFile.h" #include "nsDOMFile.h"
#include "nsCxPusher.h" #include "nsCxPusher.h"
#include "MessageUtils.h"
using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::mobilemessage;
@@ -174,13 +173,13 @@ MmsMessage::Create(int32_t aId,
const JS::Value& aDeliveryInfo, const JS::Value& aDeliveryInfo,
const nsAString& aSender, const nsAString& aSender,
const JS::Value& aReceivers, const JS::Value& aReceivers,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const JS::Value& aSentTimestamp, uint64_t aSentTimestamp,
bool aRead, bool aRead,
const nsAString& aSubject, const nsAString& aSubject,
const nsAString& aSmil, const nsAString& aSmil,
const JS::Value& aAttachments, const JS::Value& aAttachments,
const JS::Value& aExpiryDate, uint64_t aExpiryDate,
bool aIsReadReportRequested, bool aIsReadReportRequested,
JSContext* aCx, JSContext* aCx,
nsIDOMMozMmsMessage** aMessage) nsIDOMMozMmsMessage** aMessage)
@@ -255,16 +254,6 @@ MmsMessage::Create(int32_t aId,
receivers.AppendElement(receiverStr); receivers.AppendElement(receiverStr);
} }
// Set |timestamp|.
uint64_t timestamp;
nsresult rv = convertTimeToInt(aCx, aTimestamp, timestamp);
NS_ENSURE_SUCCESS(rv, rv);
// Set |sentTimestamp|.
uint64_t sentTimestamp;
rv = convertTimeToInt(aCx, aSentTimestamp, sentTimestamp);
NS_ENSURE_SUCCESS(rv, rv);
// Set |attachments|. // Set |attachments|.
if (!aAttachments.isObject()) { if (!aAttachments.isObject()) {
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
@@ -291,11 +280,6 @@ MmsMessage::Create(int32_t aId,
attachments.AppendElement(attachment); attachments.AppendElement(attachment);
} }
// Set |expiryDate|.
uint64_t expiryDate;
rv = convertTimeToInt(aCx, aExpiryDate, expiryDate);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMMozMmsMessage> message = new MmsMessage(aId, nsCOMPtr<nsIDOMMozMmsMessage> message = new MmsMessage(aId,
aThreadId, aThreadId,
aIccId, aIccId,
@@ -303,13 +287,13 @@ MmsMessage::Create(int32_t aId,
deliveryInfo, deliveryInfo,
aSender, aSender,
receivers, receivers,
timestamp, aTimestamp,
sentTimestamp, aSentTimestamp,
aRead, aRead,
aSubject, aSubject,
aSmil, aSmil,
attachments, attachments,
expiryDate, aExpiryDate,
aIsReadReportRequested); aIsReadReportRequested);
message.forget(aMessage); message.forget(aMessage);
return NS_OK; return NS_OK;

View File

@@ -66,13 +66,13 @@ public:
const JS::Value& aDeliveryInfo, const JS::Value& aDeliveryInfo,
const nsAString& aSender, const nsAString& aSender,
const JS::Value& aReceivers, const JS::Value& aReceivers,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const JS::Value& aSentTimestamp, uint64_t aSentTimestamp,
bool aRead, bool aRead,
const nsAString& aSubject, const nsAString& aSubject,
const nsAString& aSmil, const nsAString& aSmil,
const JS::Value& aAttachments, const JS::Value& aAttachments,
const JS::Value& aExpiryDate, uint64_t aExpiryDate,
bool aReadReportRequested, bool aReadReportRequested,
JSContext* aCx, JSContext* aCx,
nsIDOMMozMmsMessage** aMessage); nsIDOMMozMmsMessage** aMessage);

View File

@@ -38,10 +38,10 @@ MobileMessageService::CreateSmsMessage(int32_t aId,
const nsAString& aReceiver, const nsAString& aReceiver,
const nsAString& aBody, const nsAString& aBody,
const nsAString& aMessageClass, const nsAString& aMessageClass,
JS::Handle<JS::Value> aTimestamp, uint64_t aTimestamp,
JS::Handle<JS::Value> aSentTimestamp, uint64_t aSentTimestamp,
JS::Handle<JS::Value> aDeliveryTimestamp, uint64_t aDeliveryTimestamp,
const bool aRead, bool aRead,
JSContext* aCx, JSContext* aCx,
nsIDOMMozSmsMessage** aMessage) nsIDOMMozSmsMessage** aMessage)
{ {
@@ -70,13 +70,13 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
JS::Handle<JS::Value> aDeliveryInfo, JS::Handle<JS::Value> aDeliveryInfo,
const nsAString& aSender, const nsAString& aSender,
JS::Handle<JS::Value> aReceivers, JS::Handle<JS::Value> aReceivers,
JS::Handle<JS::Value> aTimestamp, uint64_t aTimestamp,
JS::Handle<JS::Value> aSentTimestamp, uint64_t aSentTimestamp,
bool aRead, bool aRead,
const nsAString& aSubject, const nsAString& aSubject,
const nsAString& aSmil, const nsAString& aSmil,
JS::Handle<JS::Value> aAttachments, JS::Handle<JS::Value> aAttachments,
JS::Handle<JS::Value> aExpiryDate, uint64_t aExpiryDate,
bool aReadReportRequested, bool aReadReportRequested,
JSContext* aCx, JSContext* aCx,
nsIDOMMozMmsMessage** aMessage) nsIDOMMozMmsMessage** aMessage)
@@ -115,7 +115,7 @@ MobileMessageService::CreateSmsSegmentInfo(int32_t aSegments,
NS_IMETHODIMP NS_IMETHODIMP
MobileMessageService::CreateThread(uint64_t aId, MobileMessageService::CreateThread(uint64_t aId,
JS::Handle<JS::Value> aParticipants, JS::Handle<JS::Value> aParticipants,
JS::Handle<JS::Value> aTimestamp, uint64_t aTimestamp,
const nsAString& aLastMessageSubject, const nsAString& aLastMessageSubject,
const nsAString& aBody, const nsAString& aBody,
uint64_t aUnreadCount, uint64_t aUnreadCount,

View File

@@ -28,12 +28,12 @@ NS_IMPL_ADDREF(MobileMessageThread)
NS_IMPL_RELEASE(MobileMessageThread) NS_IMPL_RELEASE(MobileMessageThread)
/* static */ nsresult /* static */ nsresult
MobileMessageThread::Create(const uint64_t aId, MobileMessageThread::Create(uint64_t aId,
const JS::Value& aParticipants, const JS::Value& aParticipants,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const nsAString& aLastMessageSubject, const nsAString& aLastMessageSubject,
const nsAString& aBody, const nsAString& aBody,
const uint64_t aUnreadCount, uint64_t aUnreadCount,
const nsAString& aLastMessageType, const nsAString& aLastMessageType,
JSContext* aCx, JSContext* aCx,
nsIDOMMozMobileMessageThread** aThread) nsIDOMMozMobileMessageThread** aThread)
@@ -76,25 +76,10 @@ MobileMessageThread::Create(const uint64_t aId,
} }
} }
// We support both a Date object and a millisecond timestamp as a number. // Set |timestamp|;
if (aTimestamp.isObject()) { data.timestamp() = aTimestamp;
JS::Rooted<JSObject*> obj(aCx, &aTimestamp.toObject());
if (!JS_ObjectIsDate(aCx, obj)) {
return NS_ERROR_INVALID_ARG;
}
data.timestamp() = js_DateGetMsecSinceEpoch(obj);
} else {
if (!aTimestamp.isNumber()) {
return NS_ERROR_INVALID_ARG;
}
double number = aTimestamp.toNumber();
if (static_cast<uint64_t>(number) != number) {
return NS_ERROR_INVALID_ARG;
}
data.timestamp() = static_cast<uint64_t>(number);
}
// Set |aLastMessageType|. // Set |lastMessageType|.
{ {
MessageType lastMessageType; MessageType lastMessageType;
if (aLastMessageType.Equals(MESSAGE_TYPE_SMS)) { if (aLastMessageType.Equals(MESSAGE_TYPE_SMS)) {
@@ -112,12 +97,12 @@ MobileMessageThread::Create(const uint64_t aId,
return NS_OK; return NS_OK;
} }
MobileMessageThread::MobileMessageThread(const uint64_t aId, MobileMessageThread::MobileMessageThread(uint64_t aId,
const nsTArray<nsString>& aParticipants, const nsTArray<nsString>& aParticipants,
const uint64_t aTimestamp, uint64_t aTimestamp,
const nsString& aLastMessageSubject, const nsString& aLastMessageSubject,
const nsString& aBody, const nsString& aBody,
const uint64_t aUnreadCount, uint64_t aUnreadCount,
MessageType aLastMessageType) MessageType aLastMessageType)
: mData(aId, aParticipants, aTimestamp, aLastMessageSubject, aBody, : mData(aId, aParticipants, aTimestamp, aLastMessageSubject, aBody,
aUnreadCount, aLastMessageType) aUnreadCount, aLastMessageType)

View File

@@ -23,22 +23,22 @@ public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZMOBILEMESSAGETHREAD NS_DECL_NSIDOMMOZMOBILEMESSAGETHREAD
MobileMessageThread(const uint64_t aId, MobileMessageThread(uint64_t aId,
const nsTArray<nsString>& aParticipants, const nsTArray<nsString>& aParticipants,
const uint64_t aTimestamp, uint64_t aTimestamp,
const nsString& aLastMessageSubject, const nsString& aLastMessageSubject,
const nsString& aBody, const nsString& aBody,
const uint64_t aUnreadCount, uint64_t aUnreadCount,
mobilemessage::MessageType aLastMessageType); mobilemessage::MessageType aLastMessageType);
MobileMessageThread(const ThreadData& aData); MobileMessageThread(const ThreadData& aData);
static nsresult Create(const uint64_t aId, static nsresult Create(uint64_t aId,
const JS::Value& aParticipants, const JS::Value& aParticipants,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const nsAString& aLastMessageSubject, const nsAString& aLastMessageSubject,
const nsAString& aBody, const nsAString& aBody,
const uint64_t aUnreadCount, uint64_t aUnreadCount,
const nsAString& aLastMessageType, const nsAString& aLastMessageType,
JSContext* aCx, JSContext* aCx,
nsIDOMMozMobileMessageThread** aThread); nsIDOMMozMobileMessageThread** aThread);

View File

@@ -8,7 +8,6 @@
#include "jsapi.h" // For OBJECT_TO_JSVAL and JS_NewDateObjectMsec #include "jsapi.h" // For OBJECT_TO_JSVAL and JS_NewDateObjectMsec
#include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch #include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch
#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType #include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
#include "MessageUtils.h"
using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::mobilemessage;
@@ -60,10 +59,10 @@ SmsMessage::Create(int32_t aId,
const nsAString& aReceiver, const nsAString& aReceiver,
const nsAString& aBody, const nsAString& aBody,
const nsAString& aMessageClass, const nsAString& aMessageClass,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const JS::Value& aSentTimestamp, uint64_t aSentTimestamp,
const JS::Value& aDeliveryTimestamp, uint64_t aDeliveryTimestamp,
const bool aRead, bool aRead,
JSContext* aCx, JSContext* aCx,
nsIDOMMozSmsMessage** aMessage) nsIDOMMozSmsMessage** aMessage)
{ {
@@ -119,16 +118,13 @@ SmsMessage::Create(int32_t aId,
} }
// Set |timestamp|. // Set |timestamp|.
nsresult rv = convertTimeToInt(aCx, aTimestamp, data.timestamp()); data.timestamp() = aTimestamp;
NS_ENSURE_SUCCESS(rv, rv);
// Set |sentTimestamp|. // Set |sentTimestamp|.
rv = convertTimeToInt(aCx, aSentTimestamp, data.sentTimestamp()); data.sentTimestamp() = aSentTimestamp;
NS_ENSURE_SUCCESS(rv, rv);
// Set |deliveryTimestamp|. // Set |deliveryTimestamp|.
rv = convertTimeToInt(aCx, aDeliveryTimestamp, data.deliveryTimestamp()); data.deliveryTimestamp() = aDeliveryTimestamp;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(data); nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(data);
message.swap(*aMessage); message.swap(*aMessage);

View File

@@ -34,6 +34,7 @@ public:
uint64_t aSentTimestamp, uint64_t aSentTimestamp,
uint64_t aDeliveryTimestamp, uint64_t aDeliveryTimestamp,
bool aRead); bool aRead);
SmsMessage(const mobilemessage::SmsMessageData& aData); SmsMessage(const mobilemessage::SmsMessageData& aData);
static nsresult Create(int32_t aId, static nsresult Create(int32_t aId,
@@ -45,10 +46,10 @@ public:
const nsAString& aReceiver, const nsAString& aReceiver,
const nsAString& aBody, const nsAString& aBody,
const nsAString& aMessageClass, const nsAString& aMessageClass,
const JS::Value& aTimestamp, uint64_t aTimestamp,
const JS::Value& aSentTimestamp, uint64_t aSentTimestamp,
const JS::Value& aDeliveryTimestamp, uint64_t aDeliveryTimestamp,
const bool aRead, bool aRead,
JSContext* aCx, JSContext* aCx,
nsIDOMMozSmsMessage** aMessage); nsIDOMMozSmsMessage** aMessage);
const mobilemessage::SmsMessageData& GetData() const; const mobilemessage::SmsMessageData& GetData() const;

View File

@@ -40,7 +40,7 @@ NS_IMETHODIMP
SmsService::Send(uint32_t aServiceId, SmsService::Send(uint32_t aServiceId,
const nsAString& aNumber, const nsAString& aNumber,
const nsAString& aMessage, const nsAString& aMessage,
const bool aSilent, bool aSilent,
nsIMobileMessageCallback* aRequest) nsIMobileMessageCallback* aRequest)
{ {
if (!AndroidBridge::Bridge()) { if (!AndroidBridge::Bridge()) {

View File

@@ -100,7 +100,7 @@ NS_IMETHODIMP
SmsService::Send(uint32_t aServiceId, SmsService::Send(uint32_t aServiceId,
const nsAString& aNumber, const nsAString& aNumber,
const nsAString& aMessage, const nsAString& aMessage,
const bool aSilent, bool aSilent,
nsIMobileMessageCallback* aRequest) nsIMobileMessageCallback* aRequest)
{ {
nsCOMPtr<nsIRadioInterface> radioInterface; nsCOMPtr<nsIRadioInterface> radioInterface;

View File

@@ -165,7 +165,7 @@ NS_IMETHODIMP
SmsIPCService::Send(uint32_t aServiceId, SmsIPCService::Send(uint32_t aServiceId,
const nsAString& aNumber, const nsAString& aNumber,
const nsAString& aMessage, const nsAString& aMessage,
const bool aSilent, bool aSilent,
nsIMobileMessageCallback* aRequest) nsIMobileMessageCallback* aRequest)
{ {
return SendRequest(SendMessageRequest(SendSmsMessageRequest(aServiceId, return SendRequest(SendMessageRequest(SendSmsMessageRequest(aServiceId,

View File

@@ -33,7 +33,7 @@ function run_test() {
*/ */
add_test(function test_interface() { add_test(function test_interface() {
let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null, let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
"normal", new Date(), new Date(), new Date(), true); "normal", Date.now(), Date.now(), Date.now(), true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage); do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_eq(sms.id, 0); do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0); do_check_eq(sms.threadId, 0);
@@ -53,7 +53,7 @@ add_test(function test_interface() {
*/ */
add_test(function test_icc_id_not_available() { add_test(function test_icc_id_not_available() {
let sms = newMessage(null, null, null, "sent", "success", null, null, null, let sms = newMessage(null, null, null, "sent", "success", null, null, null,
"normal", new Date(), new Date(), new Date(), true); "normal", Date.now(), Date.now(), Date.now(), true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage); do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_eq(sms.id, 0); do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0); do_check_eq(sms.threadId, 0);
@@ -73,7 +73,7 @@ add_test(function test_icc_id_not_available() {
*/ */
add_test(function test_readonly_attributes() { add_test(function test_readonly_attributes() {
let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null, let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
"normal", new Date(), new Date(), new Date(), true); "normal", Date.now(), Date.now(), Date.now(), true);
sms.id = 1; sms.id = 1;
do_check_eq(sms.id, 0); do_check_eq(sms.id, 0);
@@ -144,7 +144,8 @@ add_test(function test_timestamp_number() {
}); });
/** /**
* Test supplying the timestamp as a Date object. * Test supplying the timestamp as a Date object, which will be automatically
* casted to unsigned long long.
*/ */
add_test(function test_timestamp_date() { add_test(function test_timestamp_date() {
let date = new Date(); let date = new Date();
@@ -166,113 +167,13 @@ add_test(function test_timestamp_date() {
run_next_test(); run_next_test();
}); });
/**
* Test that a floating point number for the timestamp is not allowed.
*/
add_test(function test_invalid_timestamp_float() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 3.1415, new Date(), new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test sentTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), 3.1415, new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), new Date(), 3.1415, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
});
/**
* Test that a null value for the timestamp is not allowed.
*/
add_test(function test_invalid_timestamp_null() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", null, new Date(), new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test sentTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), null, new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), new Date(), null, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
});
/**
* Test that undefined for the timestamp is not allowed.
*/
add_test(function test_invalid_timestamp_undefined() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", undefined, new Date(), new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test sentTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), undefined, new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), new Date(), undefined, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
});
/**
* Test that a random object for the timestamp is not allowed.
*/
add_test(function test_invalid_timestamp_object() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", {}, new Date(), new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test sentTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), {}, new Date(), true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", new Date(), new Date(), {}, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
});
/** /**
* Test that an invalid delivery string is not accepted. * Test that an invalid delivery string is not accepted.
*/ */
add_test(function test_invalid_delivery_string() { add_test(function test_invalid_delivery_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, "this is invalid", "pending", "the sender", newMessage(42, 1, ICC_ID, "this is invalid", "pending", "the sender",
"the receiver", "the body", "normal", new Date(), 0, 0, true); "the receiver", "the body", "normal", Date.now(), 0, 0, true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });
@@ -283,7 +184,7 @@ add_test(function test_invalid_delivery_string() {
add_test(function test_invalid_delivery_string() { add_test(function test_invalid_delivery_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, 1, "pending", "the sender", "the receiver", "the body", newMessage(42, 1, ICC_ID, 1, "pending", "the sender", "the receiver", "the body",
"normal", new Date(), 0, 0, true); "normal", Date.now(), 0, 0, true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });
@@ -294,7 +195,7 @@ add_test(function test_invalid_delivery_string() {
add_test(function test_invalid_delivery_status_string() { add_test(function test_invalid_delivery_status_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "this is invalid", "the sender", "the receiver", newMessage(42, 1, ICC_ID, "sent", "this is invalid", "the sender", "the receiver",
"the body", "normal", new Date(), new Date(), 0, true); "the body", "normal", Date.now(), Date.now(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });
@@ -305,7 +206,7 @@ add_test(function test_invalid_delivery_status_string() {
add_test(function test_invalid_delivery_status_string() { add_test(function test_invalid_delivery_status_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", 1, "the sender", "the receiver", "the body", newMessage(42, 1, ICC_ID, "sent", 1, "the sender", "the receiver", "the body",
"normal", new Date(), new Date(), 0, true); "normal", Date.now(), Date.now(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });
@@ -316,7 +217,7 @@ add_test(function test_invalid_delivery_status_string() {
add_test(function test_invalid_message_class_string() { add_test(function test_invalid_message_class_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver", newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "this is invalid", new Date(), new Date(), new Date(), true); "the body", "this is invalid", Date.now(), Date.now(), Date.now(), true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });
@@ -327,7 +228,7 @@ add_test(function test_invalid_message_class_string() {
add_test(function test_invalid_message_class_string() { add_test(function test_invalid_message_class_string() {
do_check_throws(function() { do_check_throws(function() {
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver", newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", 1, new Date(), new Date(), new Date(), true); "the body", 1, Date.now(), Date.now(), Date.now(), true);
}, Cr.NS_ERROR_INVALID_ARG); }, Cr.NS_ERROR_INVALID_ARG);
run_next_test(); run_next_test();
}); });

View File

@@ -30,7 +30,7 @@ var gData = [
perm: ["wifi-manage"], perm: ["wifi-manage"],
needParentPerm: true, needParentPerm: true,
obj: "mozWifiManager", obj: "mozWifiManager",
idl: "nsIDOMWifiManager", webidl: "MozWifiManager",
verifier: verifier.toSource(), verifier: verifier.toSource(),
}, },
] ]

View File

@@ -38,7 +38,10 @@ NetworkInterfaceListService.prototype = {
LIST_NOT_INCLUDE_MMS_INTERFACES) != 0, LIST_NOT_INCLUDE_MMS_INTERFACES) != 0,
excludeIms: (aConditions & excludeIms: (aConditions &
Ci.nsINetworkInterfaceListService. Ci.nsINetworkInterfaceListService.
LIST_NOT_INCLUDE_IMS_INTERFACES) != 0 LIST_NOT_INCLUDE_IMS_INTERFACES) != 0,
excludeDun: (aConditions &
Ci.nsINetworkInterfaceListService.
LIST_NOT_INCLUDE_DUN_INTERFACES) != 0
} }
)[0]); )[0]);
} }

View File

@@ -452,7 +452,8 @@ NetworkManager.prototype = {
isNetworkTypeSecondaryMobile: function(type) { isNetworkTypeSecondaryMobile: function(type) {
return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS || return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL || type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL ||
type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS); type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS ||
type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN);
}, },
isNetworkTypeMobile: function(type) { isNetworkTypeMobile: function(type) {

View File

@@ -64,11 +64,11 @@ EXTRA_COMPONENTS += [
'NetworkInterfaceListService.js', 'NetworkInterfaceListService.js',
'NetworkInterfaceListService.manifest', 'NetworkInterfaceListService.manifest',
'NetworkManager.manifest', 'NetworkManager.manifest',
'NetworkService.js',
'NetworkService.manifest', 'NetworkService.manifest',
] ]
EXTRA_PP_COMPONENTS += [ EXTRA_PP_COMPONENTS += [
'NetworkManager.js', 'NetworkManager.js',
'NetworkService.js',
] ]
EXTRA_JS_MODULES += [ EXTRA_JS_MODULES += [
'systemlibs.js', 'systemlibs.js',

View File

@@ -59,7 +59,7 @@ function setEmulatorAPN() {
[{"carrier":"T-Mobile US", [{"carrier":"T-Mobile US",
"apn":"epc.tmobile.com", "apn":"epc.tmobile.com",
"mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc", "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
"types":["default","supl","mms","ims"]}] "types":["default","supl","mms","ims","dun"]}]
]; ];
return setSetting(APN_KEY, apn); return setSetting(APN_KEY, apn);
@@ -155,7 +155,8 @@ function testNonDefaultDataConnection() {
let typeMapping = { let typeMapping = {
"mms": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS, "mms": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
"supl": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL, "supl": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL,
"ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS "ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS,
"dun": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN
}; };
let networkType = typeMapping[type]; let networkType = typeMapping[type];
@@ -176,6 +177,7 @@ function testNonDefaultDataConnection() {
.then(() => doTestNonDefaultDataConnection("mms")) .then(() => doTestNonDefaultDataConnection("mms"))
.then(() => doTestNonDefaultDataConnection("supl")) .then(() => doTestNonDefaultDataConnection("supl"))
.then(() => doTestNonDefaultDataConnection("ims")) .then(() => doTestNonDefaultDataConnection("ims"))
.then(() => doTestNonDefaultDataConnection("dun"))
// Restore APN settings // Restore APN settings
.then(() => setSetting(APN_KEY, currentApn)) .then(() => setSetting(APN_KEY, currentApn))
.then(null, () => { .then(null, () => {

View File

@@ -677,8 +677,16 @@ var interfaceNamesInGlobalScope =
{name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"}, {name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"}, {name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiConnection", b2g: true, permission: "wifi-manage"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiConnectionInfo", b2g: true, permission: "wifi-manage"},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiConnectionInfoEvent", b2g: true}, {name: "MozWifiConnectionInfoEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiManager", b2g: true, permission: "wifi-manage"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiNetwork", b2g: true, permission: "wifi-manage"},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiStatusChangeEvent", b2g: true}, {name: "MozWifiStatusChangeEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!

View File

@@ -12,7 +12,7 @@
enum RecordingState { "inactive", "recording", "paused" }; enum RecordingState { "inactive", "recording", "paused" };
[Constructor(MediaStream stream)] [Constructor(MediaStream stream, optional MediaRecorderOptions options)]
interface MediaRecorder : EventTarget { interface MediaRecorder : EventTarget {
readonly attribute MediaStream stream; readonly attribute MediaStream stream;
@@ -45,3 +45,6 @@ interface MediaRecorder : EventTarget {
void requestData(); void requestData();
}; };
dictionary MediaRecorderOptions {
DOMString mimeType = ""; // Default encoding mimeType.
};

View File

@@ -0,0 +1,237 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
enum WifiWPSMethod {
"pbc",
"pin",
"cancel"
};
enum ConnectionStatus {
"connecting",
"associated",
"connected",
"disconnected"
};
dictionary WifiWPSInfo {
WifiWPSMethod method;
DOMString? pin;
DOMString? bssid;
};
dictionary NetworkProperties {
DOMString ssid;
sequence<DOMString>? security;
sequence<DOMString>? capabilities;
boolean known;
boolean connected;
boolean hidden;
};
[Constructor(optional NetworkProperties properties),
JSImplementation="@mozilla.org/mozwifinetwork;1"]
interface MozWifiNetwork {
readonly attribute DOMString ssid;
readonly attribute any security;
readonly attribute any capabilities;
readonly attribute boolean known;
readonly attribute boolean connected;
readonly attribute boolean hidden;
attribute DOMString? bssid;
attribute DOMString? signalStrength;
attribute long? relSignalStrength;
attribute DOMString? psk;
attribute DOMString? keyManagement;
attribute DOMString? identity;
attribute DOMString? password;
attribute DOMString? phase1;
attribute DOMString? phase2;
attribute DOMString? eap;
attribute DOMString? pin;
};
[JSImplementation="@mozilla.org/mozwificonnection;1"]
interface MozWifiConnection {
readonly attribute ConnectionStatus status;
readonly attribute MozWifiNetwork? network;
};
[JSImplementation="@mozilla.org/mozwificonnectioninfo;1"]
interface MozWifiConnectionInfo {
readonly attribute short signalStrength;
readonly attribute short relSignalStrength;
readonly attribute long linkSpeed;
readonly attribute DOMString? ipAddress;
};
dictionary IPConfiguration {
boolean enabled;
DOMString ipaddr;
DOMString proxy;
short maskLength;
DOMString gateway;
DOMString dns1;
DOMString dns2;
};
[JSImplementation="@mozilla.org/wifimanager;1",
NavigatorProperty="mozWifiManager",
Func="Navigator::HasWifiManagerSupport"]
interface MozWifiManager : EventTarget {
/**
* Returns the list of currently available networks.
* onsuccess: We have obtained the current list of networks. request.value
* is an object whose property names are SSIDs and values are
* network objects.
* onerror: We were unable to obtain a list of property names.
*/
DOMRequest getNetworks();
/**
* Returns the list of networks known to the system that will be
* automatically connected to if they're in range.
* onsuccess: request.value is an object whose property names are
* SSIDs and values are network objects.
* onerror: We were unable to obtain a list of known networks.
*/
DOMRequest getKnownNetworks();
/**
* Takes one of the networks returned from getNetworks and tries to
* connect to it.
* @param network A network object with information about the network,
* such as the SSID, key management desired, etc.
* onsuccess: We have started attempting to associate with the network.
* request.value is true.
* onerror: We were unable to select the network. This most likely means a
* configuration error.
*/
DOMRequest associate(MozWifiNetwork network);
/**
* Given a network, removes it from the list of networks that we'll
* automatically connect to. In order to re-connect to the network, it is
* necessary to call associate on it.
* @param network A network object with the SSID of the network to remove.
* onsuccess: We have removed this network. If we were previously
* connected to it, we have started reconnecting to the next
* network in the list.
* onerror: We were unable to remove the network.
*/
DOMRequest forget(MozWifiNetwork network);
/**
* Wi-Fi Protected Setup functionality.
* @param detail WPS detail which has 'method' and 'pin' field.
* The possible method field values are:
* - pbc: The Push Button Configuration.
* - pin: The PIN configuration.
* - cancel: Request to cancel WPS in progress.
* If method field is 'pin', 'pin' field can exist and has
* a PIN number.
* If method field is 'pin', 'bssid' field can exist and has
* a opposite BSSID.
* onsuccess: We have successfully started/canceled wps.
* onerror: We have failed to start/cancel wps.
*/
DOMRequest wps(optional WifiWPSInfo detail);
/**
* Turn on/off wifi power saving mode.
* @param enabled true or false.
* onsuccess: We have successfully turn on/off wifi power saving mode.
* onerror: We have failed to turn on/off wifi power saving mode.
*/
DOMRequest setPowerSavingMode(boolean enabled);
/**
* Given a network, configure using static IP instead of running DHCP
* @param network A network object with the SSID of the network to set static ip.
* @param info info should have following field:
* - enabled True to enable static IP, false to use DHCP
* - ipaddr configured static IP address
* - proxy configured proxy server address
* - maskLength configured mask length
* - gateway configured gateway address
* - dns1 configured first DNS server address
* - dns2 configured seconf DNS server address
* onsuccess: We have successfully configure the static ip mode.
* onerror: We have failed to configure the static ip mode.
*/
DOMRequest setStaticIpMode(MozWifiNetwork network, optional IPConfiguration info);
/**
* Given a network, configure http proxy when using wifi.
* @param network A network object with the SSID of the network to set http proxy.
* @param info info should have following field:
* - httpProxyHost ip address of http proxy.
* - httpProxyPort port of http proxy, set 0 to use default port 8080.
* set info to null to clear http proxy.
* onsuccess: We have successfully configure http proxy.
* onerror: We have failed to configure http proxy.
*/
DOMRequest setHttpProxy(MozWifiNetwork network, any info);
/**
* Returns whether or not wifi is currently enabled.
*/
readonly attribute boolean enabled;
/**
* Returns the MAC address of the wifi adapter.
*/
readonly attribute DOMString macAddress;
/**
* An non-null object containing the following information:
* - status ("disconnected", "connecting", "associated", "connected")
* - network
*
* Note that the object returned is read only. Any changes required must
* be done by calling other APIs.
*/
readonly attribute MozWifiConnection? connection;
/**
* A connectionInformation object with the same information found in an
* nsIDOMMozWifiConnectionInfoEvent (but without the network).
* If we are not currently connected to a network, this will be null.
*/
readonly attribute MozWifiConnectionInfo? connectionInformation;
/**
* State notification listeners. These all take an
* nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
* may be null).
*
* The possible statuses are:
* - connecting: Fires when we start the process of connecting to a
* network.
* - associated: Fires when we have connected to an access point but do
* not yet have an IP address.
* - connected: Fires once we are fully connected to an access point and
* can access the internet.
* - disconnected: Fires when we either fail to connect to an access
* point (transition: associated -> disconnected) or
* when we were connected to a network but have
* disconnected for any reason (transition: connected ->
* disconnected).
*/
attribute EventHandler onstatuschange;
/**
* An event listener that is called with information about the signal
* strength and link speed every 5 seconds.
*/
attribute EventHandler onconnectionInfoUpdate;
/**
* These two events fire when the wifi system is brought online or taken
* offline.
*/
attribute EventHandler onenabled;
attribute EventHandler ondisabled;
};

View File

@@ -553,6 +553,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
WEBIDL_FILES += [ WEBIDL_FILES += [
'MozSpeakerManager.webidl', 'MozSpeakerManager.webidl',
'MozWifiConnectionInfoEvent.webidl', 'MozWifiConnectionInfoEvent.webidl',
'MozWifiManager.webidl',
'MozWifiP2pManager.webidl', 'MozWifiP2pManager.webidl',
'MozWifiP2pStatusChangeEvent.webidl', 'MozWifiP2pStatusChangeEvent.webidl',
'MozWifiStatusChangeEvent.webidl', 'MozWifiStatusChangeEvent.webidl',

View File

@@ -15,67 +15,74 @@ Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
const DEBUG = false; // set to false to suppress debug messages const DEBUG = false; // set to false to suppress debug messages
const DOMWIFIMANAGER_CONTRACTID = "@mozilla.org/wifimanager;1"; const DOMWIFIMANAGER_CONTRACTID = "@mozilla.org/wifimanager;1";
const DOMWIFIMANAGER_CID = Components.ID("{2cf775a7-1837-410c-9e26-323c42e076da}"); const DOMWIFIMANAGER_CID = Components.ID("{c9b5f09e-25d2-40ca-aef4-c4d13d93c706}");
function DOMWifiManager() { function MozWifiNetwork() {
} }
function exposeCurrentNetwork(currentNetwork) { MozWifiNetwork.prototype = {
currentNetwork.__exposedProps__ = exposeCurrentNetwork.currentNetworkApi;
}
exposeCurrentNetwork.currentNetworkApi = { init: function(aWindow) {
ssid: "r", this._window = aWindow;
security: "r", },
capabilities: "r",
known: "r" __init: function(obj) {
this.ssid = obj.ssid;
this.security = obj.security;
this.capabilities = obj.capabilities;
this.known = obj.known;
this.connected = obj.connected;
this.hidden = obj.hidden;
},
classID: Components.ID("{c01fd751-43c0-460a-8b64-abf652ec7220}"),
contractID: "@mozilla.org/mozwifinetwork;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer])
}; };
// For smaller, read-only APIs, we expose any property that doesn't begin with function MozWifiConnection(obj) {
// an underscore. this.status = obj.status;
function exposeReadOnly(obj) { this.network = obj.network;
var exposedProps = {}; }
for (let i in obj) {
if (i[0] === "_")
continue;
exposedProps[i] = "r";
}
obj.__exposedProps__ = exposedProps; MozWifiConnection.prototype = {
return obj; classID: Components.ID("{23579da4-201b-4319-bd42-9b7f337343ac}"),
contractID: "@mozilla.org/mozwificonnection;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
};
function MozWifiConnectionInfo(obj) {
this.signalStrength = obj.signalStrength;
this.relSignalStrength = obj.relSignalStrength;
this.linkSpeed = obj.linkSpeed;
this.ipAddress = obj.ipAddress;
}
MozWifiConnectionInfo.prototype = {
classID: Components.ID("{83670352-6ed4-4c35-8de9-402296a1959c}"),
contractID: "@mozilla.org/mozwificonnectioninfo;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
}
function DOMWifiManager() {
this.defineEventHandlerGetterSetter("onstatuschange");
this.defineEventHandlerGetterSetter("onconnectionInfoUpdate");
this.defineEventHandlerGetterSetter("onenabled");
this.defineEventHandlerGetterSetter("ondisabled");
} }
DOMWifiManager.prototype = { DOMWifiManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype, __proto__: DOMRequestIpcHelper.prototype,
classID: DOMWIFIMANAGER_CID,
classInfo: XPCOMUtils.generateCI({classID: DOMWIFIMANAGER_CID,
contractID: DOMWIFIMANAGER_CONTRACTID,
classDescription: "DOMWifiManager", classDescription: "DOMWifiManager",
interfaces: [Ci.nsIDOMWifiManager], classID: DOMWIFIMANAGER_CID,
flags: Ci.nsIClassInfo.DOM_OBJECT}), contractID: DOMWIFIMANAGER_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiManager,
Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference, Ci.nsISupportsWeakReference,
Ci.nsIObserver]), Ci.nsIObserver]),
// nsIDOMGlobalPropertyInitializer implementation // nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) { init: function(aWindow) {
let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
let perm = principal == secMan.getSystemPrincipal()
? Ci.nsIPermissionManager.ALLOW_ACTION
: Services.perms.testExactPermissionFromPrincipal(principal, "wifi-manage");
// Only pages with perm set can use the wifi manager.
this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
if (!this._hasPrivileges) {
return null;
}
// Maintain this state for synchronous APIs. // Maintain this state for synchronous APIs.
this._currentNetwork = null; this._currentNetwork = null;
this._connectionStatus = "disconnected"; this._connectionStatus = "disconnected";
@@ -101,10 +108,8 @@ DOMWifiManager.prototype = {
var state = this._mm.sendSyncMessage("WifiManager:getState")[0]; var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
if (state) { if (state) {
this._currentNetwork = state.network; this._currentNetwork = this._convertWifiNetwork(state.network);
if (this._currentNetwork) this._lastConnectionInfo = this._convertConnectionInfo(state.connectionInfo);
exposeCurrentNetwork(this._currentNetwork);
this._lastConnectionInfo = state.connectionInfo;
this._enabled = state.enabled; this._enabled = state.enabled;
this._connectionStatus = state.status; this._connectionStatus = state.status;
this._macAddress = state.macAddress; this._macAddress = state.macAddress;
@@ -117,11 +122,40 @@ DOMWifiManager.prototype = {
} }
}, },
uninit: function() { _convertWifiNetworkToJSON: function(aNetwork) {
this._onStatusChange = null; let json = {};
this._onConnectionInfoUpdate = null;
this._onEnabled = null; for (let key in aNetwork) {
this._onDisabled = null; // In WifiWorker.js there are lots of check using "key in network".
// So if the value of any property of WifiNetwork is undefined, do not clone it.
if (aNetwork[key] != undefined) {
json[key] = aNetwork[key];
}
}
return json;
},
_convertWifiNetwork: function(aNetwork) {
let network = aNetwork ? new this._window.MozWifiNetwork(aNetwork) : null;
return network;
},
_convertWifiNetworks: function(aNetworks) {
let networks = [];
for (let i in aNetworks) {
networks.push(this._convertWifiNetwork(aNetworks[i]));
}
return networks;
},
_convertConnection: function(aConn) {
let conn = aConn ? new MozWifiConnection(aConn) : null;
return conn;
},
_convertConnectionInfo: function(aInfo) {
let info = aInfo ? new MozWifiConnectionInfo(aInfo) : null;
return info;
}, },
_sendMessageForRequest: function(name, data, request) { _sendMessageForRequest: function(name, data, request) {
@@ -144,7 +178,7 @@ DOMWifiManager.prototype = {
switch (aMessage.name) { switch (aMessage.name) {
case "WifiManager:getNetworks:Return:OK": case "WifiManager:getNetworks:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
break; break;
case "WifiManager:getNetworks:Return:NO": case "WifiManager:getNetworks:Return:NO":
@@ -152,7 +186,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:getKnownNetworks:Return:OK": case "WifiManager:getKnownNetworks:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
break; break;
case "WifiManager:getKnownNetworks:Return:NO": case "WifiManager:getKnownNetworks:Return:NO":
@@ -176,7 +210,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:wps:Return:OK": case "WifiManager:wps:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, msg.data);
break; break;
case "WifiManager:wps:Return:NO": case "WifiManager:wps:Return:NO":
@@ -184,7 +218,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:setPowerSavingMode:Return:OK": case "WifiManager:setPowerSavingMode:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, msg.data);
break; break;
case "WifiManager:setPowerSavingMode:Return:NO": case "WifiManager:setPowerSavingMode:Return:NO":
@@ -192,7 +226,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:setHttpProxy:Return:OK": case "WifiManager:setHttpProxy:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, msg.data);
break; break;
case "WifiManager:setHttpProxy:Return:NO": case "WifiManager:setHttpProxy:Return:NO":
@@ -200,7 +234,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:setStaticIpMode:Return:OK": case "WifiManager:setStaticIpMode:Return:OK":
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data)); Services.DOMRequest.fireSuccess(request, msg.data);
break; break;
case "WifiManager:setStaticIpMode:Return:NO": case "WifiManager:setStaticIpMode:Return:NO":
@@ -220,22 +254,19 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:onconnecting": case "WifiManager:onconnecting":
this._currentNetwork = msg.network; this._currentNetwork = this._convertWifiNetwork(msg.network);
exposeCurrentNetwork(this._currentNetwork);
this._connectionStatus = "connecting"; this._connectionStatus = "connecting";
this._fireStatusChangeEvent(); this._fireStatusChangeEvent();
break; break;
case "WifiManager:onassociate": case "WifiManager:onassociate":
this._currentNetwork = msg.network; this._currentNetwork = this._convertWifiNetwork(msg.network);
exposeCurrentNetwork(this._currentNetwork);
this._connectionStatus = "associated"; this._connectionStatus = "associated";
this._fireStatusChangeEvent(); this._fireStatusChangeEvent();
break; break;
case "WifiManager:onconnect": case "WifiManager:onconnect":
this._currentNetwork = msg.network; this._currentNetwork = this._convertWifiNetwork(msg.network);
exposeCurrentNetwork(this._currentNetwork);
this._connectionStatus = "connected"; this._connectionStatus = "connected";
this._fireStatusChangeEvent(); this._fireStatusChangeEvent();
break; break;
@@ -269,7 +300,7 @@ DOMWifiManager.prototype = {
break; break;
case "WifiManager:connectionInfoUpdate": case "WifiManager:connectionInfoUpdate":
this._lastConnectionInfo = msg; this._lastConnectionInfo = this._convertConnectionInfo(msg);
this._fireConnectionInfoUpdate(msg); this._fireConnectionInfoUpdate(msg);
break; break;
case "WifiManager:onconnectingfailed": case "WifiManager:onconnectingfailed":
@@ -282,156 +313,115 @@ DOMWifiManager.prototype = {
}, },
_fireStatusChangeEvent: function StatusChangeEvent() { _fireStatusChangeEvent: function StatusChangeEvent() {
if (this._onStatusChange) { var event = new this._window.MozWifiStatusChangeEvent("statuschange",
debug("StatusChangeEvent");
var event = new this._window.MozWifiStatusChangeEvent("statusChangeEvent",
{ network: this._currentNetwork, { network: this._currentNetwork,
status: this._connectionStatus status: this._connectionStatus
}); });
this._onStatusChange.handleEvent(event); this.__DOM_IMPL__.dispatchEvent(event);
}
}, },
_fireConnectionInfoUpdate: function connectionInfoUpdate(info) { _fireConnectionInfoUpdate: function onConnectionInfoUpdate(info) {
if (this._onConnectionInfoUpdate) { var evt = new this._window.MozWifiConnectionInfoEvent("connectioninfoupdate",
debug("ConnectionInfoEvent");
var evt = new this._window.MozWifiConnectionInfoEvent("connectionInfoEvent",
{ network: this._currentNetwork, { network: this._currentNetwork,
signalStrength: info.signalStrength, signalStrength: info.signalStrength,
relSignalStrength: info.relSignalStrength, relSignalStrength: info.relSignalStrength,
linkSpeed: info.linkSpeed, linkSpeed: info.linkSpeed,
ipAddress: info.ipAddress, ipAddress: info.ipAddress,
}); });
this._onConnectionInfoUpdate.handleEvent(evt); this.__DOM_IMPL__.dispatchEvent(evt);
}
}, },
_fireEnabledOrDisabled: function enabledDisabled(enabled) { _fireEnabledOrDisabled: function enabledDisabled(enabled) {
var handler = enabled ? this._onEnabled : this._onDisabled; var evt = new this._window.Event(enabled ? "enabled" : "disabled");
if (handler) { this.__DOM_IMPL__.dispatchEvent(evt);
var evt = new this._window.Event("WifiEnabled");
handler.handleEvent(evt);
}
}, },
// nsIDOMWifiManager getNetworks: function getNetworks() {
getNetworks: function nsIDOMWifiManager_getNetworks() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:getNetworks", null, request); this._sendMessageForRequest("WifiManager:getNetworks", null, request);
return request; return request;
}, },
getKnownNetworks: function nsIDOMWifiManager_getKnownNetworks() { getKnownNetworks: function getKnownNetworks() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request); this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request);
return request; return request;
}, },
associate: function nsIDOMWifiManager_associate(network) { associate: function associate(network) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:associate", network, request); this._sendMessageForRequest("WifiManager:associate",
this._convertWifiNetworkToJSON(network), request);
return request; return request;
}, },
forget: function nsIDOMWifiManager_forget(network) { forget: function forget(network) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:forget", network, request); this._sendMessageForRequest("WifiManager:forget",
this._convertWifiNetworkToJSON(network), request);
return request; return request;
}, },
wps: function nsIDOMWifiManager_wps(detail) { wps: function wps(detail) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:wps", detail, request); this._sendMessageForRequest("WifiManager:wps", detail, request);
return request; return request;
}, },
setPowerSavingMode: function nsIDOMWifiManager_setPowerSavingMode(enabled) { setPowerSavingMode: function setPowerSavingMode(enabled) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request); this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request);
return request; return request;
}, },
setHttpProxy: function nsIDOMWifiManager_setHttpProxy(network, info) { setHttpProxy: function setHttpProxy(network, info) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:setHttpProxy", {network:network, info:info}, request); this._sendMessageForRequest("WifiManager:setHttpProxy",
{ network: this._convertWifiNetworkToJSON(network), info:info}, request);
return request; return request;
}, },
setStaticIpMode: function nsIDOMWifiManager_setStaticIpMode(network, info) { setStaticIpMode: function setStaticIpMode(network, info) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest(); var request = this.createRequest();
this._sendMessageForRequest("WifiManager:setStaticIpMode", {network: network,info: info}, request); this._sendMessageForRequest("WifiManager:setStaticIpMode",
{ network: this._convertWifiNetworkToJSON(network), info: info}, request);
return request; return request;
}, },
get enabled() { get enabled() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
return this._enabled; return this._enabled;
}, },
get macAddress() { get macAddress() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
return this._macAddress; return this._macAddress;
}, },
get connection() { get connection() {
if (!this._hasPrivileges) let _connection = this._convertConnection({ status: this._connectionStatus,
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE); network: this._currentNetwork,
return exposeReadOnly({ status: this._connectionStatus, });
network: this._currentNetwork }); return _connection;
}, },
get connectionInformation() { get connectionInformation() {
if (!this._hasPrivileges) return this._lastConnectionInfo;
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
return this._lastConnectionInfo
? exposeReadOnly(this._lastConnectionInfo)
: null;
}, },
set onstatuschange(callback) { defineEventHandlerGetterSetter: function(name) {
if (!this._hasPrivileges) Object.defineProperty(this, name, {
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE); get: function() {
this._onStatusChange = callback; return this.__DOM_IMPL__.getEventHandler(name);
}, },
set: function(handler) {
set connectionInfoUpdate(callback) { this.__DOM_IMPL__.setEventHandler(name, handler);
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
this._onConnectionInfoUpdate = callback;
},
set onenabled(callback) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
this._onEnabled = callback;
},
set ondisabled(callback) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
this._onDisabled = callback;
} }
});
},
}; };
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMWifiManager]); this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
DOMWifiManager, MozWifiNetwork, MozWifiConnection, MozWifiConnectionInfo
]);
let debug; let debug;
if (DEBUG) { if (DEBUG) {

View File

@@ -1,4 +1,12 @@
# DOMWifiManager.js # DOMWifiManager.js
component {2cf775a7-1837-410c-9e26-323c42e076da} DOMWifiManager.js component {c9b5f09e-25d2-40ca-aef4-c4d13d93c706} DOMWifiManager.js
contract @mozilla.org/wifimanager;1 {2cf775a7-1837-410c-9e26-323c42e076da} contract @mozilla.org/wifimanager;1 {c9b5f09e-25d2-40ca-aef4-c4d13d93c706}
category JavaScript-navigator-property mozWifiManager @mozilla.org/wifimanager;1
component {c01fd751-43c0-460a-8b64-abf652ec7220} DOMWifiManager.js
contract @mozilla.org/mozwifinetwork;1 {c01fd751-43c0-460a-8b64-abf652ec7220}
component {23579da4-201b-4319-bd42-9b7f337343ac} DOMWifiManager.js
contract @mozilla.org/mozwificonnection;1 {23579da4-201b-4319-bd42-9b7f337343ac}
component {83670352-6ed4-4c35-8de9-402296a1959c} DOMWifiManager.js
contract @mozilla.org/mozwificonnectioninfo;1 {83670352-6ed4-4c35-8de9-402296a1959c}

View File

@@ -58,163 +58,3 @@ interface nsIWifi : nsISupports
*/ */
void getWifiScanResults(in nsIWifiScanResultsReady callback); void getWifiScanResults(in nsIWifiScanResultsReady callback);
}; };
[scriptable, uuid(e5a72295-1c5f-4848-9cbb-f1d3785c16c1)]
interface nsIDOMWifiManager : nsISupports
{
/**
* Returns the list of currently available networks.
* onsuccess: We have obtained the current list of networks. request.value
* is an object whose property names are SSIDs and values are
* network objects.
* onerror: We were unable to obtain a list of property names.
*/
nsIDOMDOMRequest getNetworks();
/**
* Returns the list of networks known to the system that will be
* automatically connected to if they're in range.
* onsuccess: request.value is an object whose property names are
* SSIDs and values are network objects.
* onerror: We were unable to obtain a list of known networks.
*/
nsIDOMDOMRequest getKnownNetworks();
/**
* Takes one of the networks returned from getNetworks and tries to
* connect to it.
* @param network A network object with information about the network,
* such as the SSID, key management desired, etc.
* onsuccess: We have started attempting to associate with the network.
* request.value is true.
* onerror: We were unable to select the network. This most likely means a
* configuration error.
*/
nsIDOMDOMRequest associate(in jsval network);
/**
* Given a network, removes it from the list of networks that we'll
* automatically connect to. In order to re-connect to the network, it is
* necessary to call associate on it.
* @param network A network object with the SSID of the network to remove.
* onsuccess: We have removed this network. If we were previously
* connected to it, we have started reconnecting to the next
* network in the list.
* onerror: We were unable to remove the network.
*/
nsIDOMDOMRequest forget(in jsval network);
/**
* Wi-Fi Protected Setup functionality.
* @param detail WPS detail which has 'method' and 'pin' field.
* The possible method field values are:
* - pbc: The Push Button Configuration.
* - pin: The PIN configuration.
* - cancel: Request to cancel WPS in progress.
* If method field is 'pin', 'pin' field can exist and has
* a PIN number.
* If method field is 'pin', 'bssid' field can exist and has
* a opposite BSSID.
* onsuccess: We have successfully started/canceled wps.
* onerror: We have failed to start/cancel wps.
*/
nsIDOMDOMRequest wps(in jsval detail);
/**
* Turn on/off wifi power saving mode.
* @param enabled true or false.
* onsuccess: We have successfully turn on/off wifi power saving mode.
* onerror: We have failed to turn on/off wifi power saving mode.
*/
nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
/**
* Given a network, configure using static IP instead of running DHCP
* @param network A network object with the SSID of the network to set static ip.
* @param info info should have following field:
* - enabled True to enable static IP, false to use DHCP
* - ipaddr configured static IP address
* - proxy configured proxy server address
* - maskLength configured mask length
* - gateway configured gateway address
* - dns1 configured first DNS server address
* - dns2 configured seconf DNS server address
* onsuccess: We have successfully configure the static ip mode.
* onerror: We have failed to configure the static ip mode.
*/
nsIDOMDOMRequest setStaticIpMode(in jsval network,
in jsval info);
/**
* Given a network, configure http proxy when using wifi.
* @param network A network object with the SSID of the network to set http proxy.
* @param info info should have following field:
* - httpProxyHost ip address of http proxy.
* - httpProxyPort port of http proxy, set 0 to use default port 8080.
* set info to null to clear http proxy.
* onsuccess: We have successfully configure http proxy.
* onerror: We have failed to configure http proxy.
*/
nsIDOMDOMRequest setHttpProxy(in jsval network,
in jsval info);
/**
* Returns whether or not wifi is currently enabled.
*/
readonly attribute boolean enabled;
/**
* Returns the MAC address of the wifi adapter.
*/
readonly attribute DOMString macAddress;
/**
* An non-null object containing the following information:
* - status ("disconnected", "connecting", "associated", "connected")
* - network
*
* Note that the object returned is read only. Any changes required must
* be done by calling other APIs.
*/
readonly attribute jsval connection;
/**
* A connectionInformation object with the same information found in an
* nsIDOMMozWifiConnectionInfoEvent (but without the network).
* If we are not currently connected to a network, this will be null.
*/
readonly attribute jsval connectionInformation;
/**
* State notification listeners. These all take an
* nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
* may be null).
*
* The possible statuses are:
* - connecting: Fires when we start the process of connecting to a
* network.
* - associated: Fires when we have connected to an access point but do
* not yet have an IP address.
* - connected: Fires once we are fully connected to an access point and
* can access the internet.
* - disconnected: Fires when we either fail to connect to an access
* point (transition: associated -> disconnected) or
* when we were connected to a network but have
* disconnected for any reason (transition: connected ->
* disconnected).
*/
attribute nsIDOMEventListener onstatuschange;
/**
* An event listener that is called with information about the signal
* strength and link speed every 5 seconds.
*/
attribute nsIDOMEventListener connectionInfoUpdate;
/**
* These two events fire when the wifi system is brought online or taken
* offline.
*/
attribute nsIDOMEventListener onenabled;
attribute nsIDOMEventListener ondisabled;
};

View File

@@ -878,6 +878,8 @@ ProcessPriorityToString(ProcessPriority aPriority)
switch (aPriority) { switch (aPriority) {
case PROCESS_PRIORITY_MASTER: case PROCESS_PRIORITY_MASTER:
return "MASTER"; return "MASTER";
case PROCESS_PRIORITY_PREALLOC:
return "PREALLOC";
case PROCESS_PRIORITY_FOREGROUND_HIGH: case PROCESS_PRIORITY_FOREGROUND_HIGH:
return "FOREGROUND_HIGH"; return "FOREGROUND_HIGH";
case PROCESS_PRIORITY_FOREGROUND: case PROCESS_PRIORITY_FOREGROUND:
@@ -916,6 +918,13 @@ ProcessPriorityToString(ProcessPriority aPriority,
if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
return "MASTER:CPU_LOW"; return "MASTER:CPU_LOW";
} }
case PROCESS_PRIORITY_PREALLOC:
if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
return "PREALLOC:CPU_NORMAL";
}
if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
return "PREALLOC:CPU_LOW";
}
case PROCESS_PRIORITY_FOREGROUND_HIGH: case PROCESS_PRIORITY_FOREGROUND_HIGH:
if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
return "FOREGROUND_HIGH:CPU_NORMAL"; return "FOREGROUND_HIGH:CPU_NORMAL";

View File

@@ -84,6 +84,9 @@ enum ProcessPriority {
PROCESS_PRIORITY_BACKGROUND_HOMESCREEN, PROCESS_PRIORITY_BACKGROUND_HOMESCREEN,
PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE, PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE,
PROCESS_PRIORITY_FOREGROUND_KEYBOARD, PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
// The special class for the preallocated process, high memory priority but
// low CPU priority.
PROCESS_PRIORITY_PREALLOC,
// Any priority greater than or equal to FOREGROUND is considered // Any priority greater than or equal to FOREGROUND is considered
// "foreground" for the purposes of priority testing, for example // "foreground" for the purposes of priority testing, for example
// CurrentProcessIsForeground(). // CurrentProcessIsForeground().

View File

@@ -1256,6 +1256,9 @@ EnsureKernelLowMemKillerParamsSet()
nsPrintfCString("hal.processPriorityManager.gonk.%s.KillUnderKB", nsPrintfCString("hal.processPriorityManager.gonk.%s.KillUnderKB",
ProcessPriorityToString(priority)).get(), ProcessPriorityToString(priority)).get(),
&killUnderKB))) { &killUnderKB))) {
// ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
// which has only OomScoreAdjust but lacks KillUnderMB value, will not
// create new LMK parameters.
continue; continue;
} }

View File

@@ -41,7 +41,9 @@ GetInterfaces(std::vector<NetworkInterface>* aInterfaces)
int32_t flags = int32_t flags =
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES | nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES |
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES; nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES |
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_IMS_INTERFACES |
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_DUN_INTERFACES;
nsCOMPtr<nsINetworkInterfaceList> networkList; nsCOMPtr<nsINetworkInterfaceList> networkList;
NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags, NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags,
getter_AddRefs(networkList)), getter_AddRefs(networkList)),

View File

@@ -79,6 +79,7 @@
#define AUDIO_MP3 "audio/mpeg" #define AUDIO_MP3 "audio/mpeg"
#define AUDIO_MP4 "audio/mp4" #define AUDIO_MP4 "audio/mp4"
#define AUDIO_AMR "audio/amr" #define AUDIO_AMR "audio/amr"
#define AUDIO_3GPP "audio/3gpp"
#define AUDIO_MIDI "audio/x-midi" #define AUDIO_MIDI "audio/x-midi"
#define BINARY_OCTET_STREAM "binary/octet-stream" #define BINARY_OCTET_STREAM "binary/octet-stream"

View File

@@ -225,6 +225,10 @@ class Emulator(object):
self._get_telnet_response() self._get_telnet_response()
return self._get_telnet_response(command) return self._get_telnet_response(command)
def _run_shell(self, args):
args.insert(0, 'shell')
return self._run_adb(args).split('\r\n')
def close(self): def close(self):
if self.is_running and self._emulator_launched: if self.is_running and self._emulator_launched:
self.proc.kill() self.proc.kill()

View File

@@ -608,8 +608,16 @@ class Marionette(object):
# Process any emulator commands that are sent from a script # Process any emulator commands that are sent from a script
# while it's executing. # while it's executing.
while response.get("emulator_cmd"): while True:
if response.get("emulator_cmd"):
response = self._handle_emulator_cmd(response) response = self._handle_emulator_cmd(response)
continue;
if response.get("emulator_shell"):
response = self._handle_emulator_shell(response)
continue;
break;
if response_key in response: if response_key in response:
return response[response_key] return response[response_key]
@@ -626,6 +634,16 @@ class Marionette(object):
"id": response.get("id"), "id": response.get("id"),
"result": result}) "result": result})
def _handle_emulator_shell(self, response):
args = response.get("emulator_shell")
if not isinstance(args, list) or not self.emulator:
raise MarionetteException(
"No emulator in this test to run shell command against")
result = self.emulator._run_shell(args)
return self.client.send({"name": "emulatorCmdResult",
"id": response.get("id"),
"result": result})
def _handle_error(self, response): def _handle_error(self, response):
if 'error' in response and isinstance(response['error'], dict): if 'error' in response and isinstance(response['error'], dict):
status = response['error'].get('status', 500) status = response['error'].get('status', 500)

View File

@@ -17,6 +17,14 @@ class TestEmulatorContent(MarionetteTestCase):
"""); """);
self.assertEqual(result, expected) self.assertEqual(result, expected)
def test_emulator_shell(self):
self.marionette.set_script_timeout(10000)
expected = ["Hello World!", ""]
result = self.marionette.execute_async_script("""
runEmulatorShell(["echo", "Hello World!"], marionetteScriptFinished)
""");
self.assertEqual(result, expected)
def test_emulator_order(self): def test_emulator_order(self):
self.marionette.set_script_timeout(10000) self.marionette.set_script_timeout(10000)
self.assertRaises(MarionetteException, self.assertRaises(MarionetteException,

View File

@@ -163,6 +163,7 @@ FrameManager.prototype = {
messageManager.addWeakMessageListener("Marionette:shareData", this.server); messageManager.addWeakMessageListener("Marionette:shareData", this.server);
messageManager.addWeakMessageListener("Marionette:register", this.server); messageManager.addWeakMessageListener("Marionette:register", this.server);
messageManager.addWeakMessageListener("Marionette:runEmulatorCmd", this.server); messageManager.addWeakMessageListener("Marionette:runEmulatorCmd", this.server);
messageManager.addWeakMessageListener("Marionette:runEmulatorShell", this.server);
messageManager.addWeakMessageListener("Marionette:switchToModalOrigin", this.server); messageManager.addWeakMessageListener("Marionette:switchToModalOrigin", this.server);
messageManager.addWeakMessageListener("Marionette:switchToFrame", this.server); messageManager.addWeakMessageListener("Marionette:switchToFrame", this.server);
messageManager.addWeakMessageListener("Marionette:switchedToFrame", this.server); messageManager.addWeakMessageListener("Marionette:switchedToFrame", this.server);
@@ -190,6 +191,7 @@ FrameManager.prototype = {
messageManager.removeWeakMessageListener("Marionette:shareData", this.server); messageManager.removeWeakMessageListener("Marionette:shareData", this.server);
messageManager.removeWeakMessageListener("Marionette:register", this.server); messageManager.removeWeakMessageListener("Marionette:register", this.server);
messageManager.removeWeakMessageListener("Marionette:runEmulatorCmd", this.server); messageManager.removeWeakMessageListener("Marionette:runEmulatorCmd", this.server);
messageManager.removeWeakMessageListener("Marionette:runEmulatorShell", this.server);
messageManager.removeWeakMessageListener("Marionette:switchToFrame", this.server); messageManager.removeWeakMessageListener("Marionette:switchToFrame", this.server);
messageManager.removeWeakMessageListener("Marionette:switchedToFrame", this.server); messageManager.removeWeakMessageListener("Marionette:switchedToFrame", this.server);
messageManager.removeWeakMessageListener("MarionetteFrame:handleModal", this); messageManager.removeWeakMessageListener("MarionetteFrame:handleModal", this);

View File

@@ -2019,6 +2019,14 @@ function runEmulatorCmd(cmd, callback) {
_emu_cb_id += 1; _emu_cb_id += 1;
} }
function runEmulatorShell(args, callback) {
if (callback) {
_emu_cbs[_emu_cb_id] = callback;
}
sendAsyncMessage("Marionette:runEmulatorShell", {emulator_shell: args, id: _emu_cb_id});
_emu_cb_id += 1;
}
function emulatorCmdResult(msg) { function emulatorCmdResult(msg) {
let message = msg.json; let message = msg.json;
if (!sandbox) { if (!sandbox) {

View File

@@ -2128,6 +2128,17 @@ MarionetteServerConnection.prototype = {
this._emu_cb_id += 1; this._emu_cb_id += 1;
}, },
runEmulatorShell: function runEmulatorShell(args, callback) {
if (callback) {
if (!this._emu_cbs) {
this._emu_cbs = {};
}
this._emu_cbs[this._emu_cb_id] = callback;
}
this.sendToClient({emulator_shell: args, id: this._emu_cb_id}, -1);
this._emu_cb_id += 1;
},
emulatorCmdResult: function emulatorCmdResult(message) { emulatorCmdResult: function emulatorCmdResult(message) {
if (this.context != "chrome") { if (this.context != "chrome") {
this.sendAsync("emulatorCmdResult", message, -1); this.sendAsync("emulatorCmdResult", message, -1);
@@ -2325,6 +2336,7 @@ MarionetteServerConnection.prototype = {
} }
break; break;
case "Marionette:runEmulatorCmd": case "Marionette:runEmulatorCmd":
case "Marionette:runEmulatorShell":
this.sendToClient(message.json, -1); this.sendToClient(message.json, -1);
break; break;
case "Marionette:switchToFrame": case "Marionette:switchToFrame":

View File

@@ -22,7 +22,7 @@ this.Marionette = function Marionette(scope, window, context, logObj, timeout,
Marionette.prototype = { Marionette.prototype = {
exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor', exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor',
'runEmulatorCmd', 'TEST_PASS', 'TEST_KNOWN_FAIL', 'runEmulatorCmd', 'runEmulatorShell', 'TEST_PASS', 'TEST_KNOWN_FAIL',
'TEST_UNEXPECTED_FAIL'], 'TEST_UNEXPECTED_FAIL'],
ok: function Marionette__ok(condition, name, passString, failString, diag) { ok: function Marionette__ok(condition, name, passString, failString, diag) {
@@ -163,5 +163,10 @@ Marionette.prototype = {
this.scope.runEmulatorCmd(cmd, callback); this.scope.runEmulatorCmd(cmd, callback);
}, },
runEmulatorShell: function runEmulatorShell(args, callback) {
this.heartbeatCallback();
this.scope.runEmulatorShell(args, callback);
},
}; };

View File

@@ -44,9 +44,6 @@ SERV_FILES = \
android.json \ android.json \
androidx86.json \ androidx86.json \
android23.json \ android23.json \
b2g.json \
b2g-desktop.json \
b2g-debug.json \
gl.json \ gl.json \
b2g_start_script.js \ b2g_start_script.js \
$(NULL) $(NULL)

View File

@@ -1,6 +0,0 @@
{
"runtests": {
},
"excludetests": {
}
}

View File

@@ -1,6 +0,0 @@
{
"runtests": {
},
"excludetests": {
}
}

View File

@@ -1,6 +0,0 @@
{
"runtests": {
},
"excludetests": {
}
}

View File

@@ -143,13 +143,6 @@ class MochitestRunner(MozbuildObject):
test_path_dir = True; test_path_dir = True;
options.testPath = test_path options.testPath = test_path
# filter test directiories or all tests according to the manifest
if not test_path or test_path_dir:
if conditions.is_b2g_desktop(self):
options.testManifest = 'b2g-desktop.json'
else:
options.testManifest = 'b2g.json'
for k, v in kwargs.iteritems(): for k, v in kwargs.iteritems():
setattr(options, k, v) setattr(options, k, v)
options.noWindow = no_window options.noWindow = no_window

View File

@@ -47,6 +47,23 @@ typedef hwc_layer_list_t HwcList;
typedef hwc_layer_t HwcLayer; typedef hwc_layer_t HwcLayer;
#endif #endif
/*
* HwcComposer2D provides a way for gecko to render frames
* using hwcomposer.h in the AOSP HAL.
*
* hwcomposer.h defines an interface for display composition
* using dedicated hardware. This hardware is usually faster
* or more power efficient than the GPU. However, in exchange
* for better performance, generality has to be sacrificed:
* no 3d transforms, no intermediate surfaces, no special shader effects,
* and loss of other goodies depending on the platform.
*
* In general, when hwc is enabled gecko tries to compose
* its frames using HwcComposer2D first. Then if HwcComposer2D is
* unable to compose a frame then it falls back to compose it
* using the GPU with OpenGL.
*
*/
class HwcComposer2D : public mozilla::layers::Composer2D { class HwcComposer2D : public mozilla::layers::Composer2D {
public: public:
HwcComposer2D(); HwcComposer2D();