--- a/accessible/jsat/AccessFu.css
+++ b/accessible/jsat/AccessFu.css
@@ -4,19 +4,24 @@
#virtual-cursor-box {
position: fixed;
border: 1px solid orange;
pointer-events: none;
display: none;
border-radius: 2px;
box-shadow: 1px 1px 1px #444;
+ display: none;
}
-#virtual-cursor-inset {
+#virtual-cursor-box.show {
+ display: block;
+}
+
+#virtual-cursor-box > div {
border-radius: 1px;
box-shadow: inset 1px 1px 1px #444;
display: block;
box-sizing: border-box;
width: 100%;
height: 100%;
pointer-events: none;
}
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -389,53 +389,39 @@ this.AccessFu = { // jshint ignore:line
// Layerview is focused
_focused: false,
// Keep track of message managers tha already have a 'content-script.js'
// injected.
_processedMessageManagers: [],
/**
- * Adjusts the given bounds relative to the given browser. Converts from
- * screen or device pixels to either device or CSS pixels.
+ * Adjusts the given bounds relative to the given browser.
* @param {Rect} aJsonBounds the bounds to adjust
* @param {browser} aBrowser the browser we want the bounds relative to
* @param {bool} aToCSSPixels whether to convert to CSS pixels (as opposed to
* device pixels)
- * @param {bool} aFromDevicePixels whether to convert from device pixels (as
- * opposed to screen pixels)
*/
adjustContentBounds:
- function(aJsonBounds, aBrowser, aToCSSPixels, aFromDevicePixels) {
+ function(aJsonBounds, aBrowser, aToCSSPixels) {
let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
aJsonBounds.right - aJsonBounds.left,
aJsonBounds.bottom - aJsonBounds.top);
let win = Utils.win;
let dpr = win.devicePixelRatio;
- let vp = Utils.getViewport(win);
let offset = { left: -win.mozInnerScreenX, top: -win.mozInnerScreenY };
if (!aBrowser.contentWindow) {
// OOP browser, add offset of browser.
// The offset of the browser element in relation to its parent window.
let clientRect = aBrowser.getBoundingClientRect();
let win = aBrowser.ownerDocument.defaultView;
offset.left += clientRect.left + win.mozInnerScreenX;
offset.top += clientRect.top + win.mozInnerScreenY;
}
-
- // Here we scale from screen pixels to layout device pixels by dividing by
- // the resolution (caused by pinch-zooming). The resolution is the
- // viewport zoom divided by the devicePixelRatio. If there's no viewport,
- // then we're on a platform without pinch-zooming and we can just ignore
- // this.
- if (!aFromDevicePixels && vp) {
- bounds = bounds.scale(vp.zoom / dpr, vp.zoom / dpr);
- }
-
// Add the offset; the offset is in CSS pixels, so multiply the
// devicePixelRatio back in before adding to preserve unit consistency.
bounds = bounds.translate(offset.left * dpr, offset.top * dpr);
// If we want to get to CSS pixels from device pixels, this needs to be
// further divided by the devicePixelRatio due to widget scaling.
if (aToCSSPixels) {
bounds = bounds.scale(1 / dpr, 1 / dpr);
@@ -540,44 +526,43 @@ var Output = {
if (!this.highlightBox) {
// Add highlight box
highlightBox = Utils.win.document.
createElementNS('http://www.w3.org/1999/xhtml', 'div');
Utils.win.document.documentElement.appendChild(highlightBox);
highlightBox.id = 'virtual-cursor-box';
// Add highlight inset for inner shadow
- let inset = Utils.win.document.
- createElementNS('http://www.w3.org/1999/xhtml', 'div');
- inset.id = 'virtual-cursor-inset';
+ highlightBox.appendChild(
+ Utils.win.document.createElementNS(
+ 'http://www.w3.org/1999/xhtml', 'div'));
- highlightBox.appendChild(inset);
this.highlightBox = Cu.getWeakReference(highlightBox);
} else {
highlightBox = this.highlightBox.get();
}
let padding = aDetail.padding;
let r = AccessFu.adjustContentBounds(aDetail.bounds, aBrowser, true);
// First hide it to avoid flickering when changing the style.
- highlightBox.style.display = 'none';
+ highlightBox.classList.remove('show');
highlightBox.style.top = (r.top - padding) + 'px';
highlightBox.style.left = (r.left - padding) + 'px';
highlightBox.style.width = (r.width + padding*2) + 'px';
highlightBox.style.height = (r.height + padding*2) + 'px';
- highlightBox.style.display = 'block';
+ highlightBox.classList.add('show');
break;
}
case 'tabstate-change':
{
let highlightBox = this.highlightBox ? this.highlightBox.get() : null;
if (highlightBox) {
- highlightBox.style.display = 'none';
+ highlightBox.classList.remove('show');
}
break;
}
}
},
get androidBridge() {
delete this.androidBridge;
@@ -884,18 +869,17 @@ var Input = {
sendContextMenuMessage: function sendContextMenuMessage() {
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
mm.sendAsyncMessage('AccessFu:ContextMenu', {});
},
activateContextMenu: function activateContextMenu(aDetails) {
if (Utils.MozBuildApp === 'mobile/android') {
let p = AccessFu.adjustContentBounds(aDetails.bounds,
- Utils.CurrentBrowser,
- true, true).center();
+ Utils.CurrentBrowser, true).center();
Services.obs.notifyObservers(null, 'Gesture:LongPress',
JSON.stringify({x: p.x, y: p.y}));
}
},
setEditState: function setEditState(aEditState) {
this.editState = aEditState;
},
@@ -910,18 +894,18 @@ var Input = {
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
mm.sendAsyncMessage('AccessFu:Scroll',
{page: aPage, horizontal: aHorizontal, origin: 'top'});
},
doScroll: function doScroll(aDetails) {
let horizontal = aDetails.horizontal;
let page = aDetails.page;
- let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
- true, true).center();
+ let p = AccessFu.adjustContentBounds(
+ aDetails.bounds, Utils.CurrentBrowser, true).center();
Utils.winUtils.sendWheelEvent(p.x, p.y,
horizontal ? page : 0, horizontal ? 0 : page, 0,
Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
},
get keyMap() {
delete this.keyMap;
this.keyMap = {
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -250,25 +250,16 @@ this.Utils = { // jshint ignore:line
try {
return aBrowser.QueryInterface(Ci.nsIFrameLoaderOwner).
frameLoader.messageManager;
} catch (x) {
return null;
}
},
- getViewport: function getViewport(aWindow) {
- switch (this.MozBuildApp) {
- case 'mobile/android':
- return aWindow.BrowserApp.selectedTab.getViewport();
- default:
- return null;
- }
- },
-
getState: function getState(aAccessibleOrEvent) {
if (aAccessibleOrEvent instanceof Ci.nsIAccessibleStateChangeEvent) {
return new State(
aAccessibleOrEvent.isExtraState ? 0 : aAccessibleOrEvent.state,
aAccessibleOrEvent.isExtraState ? aAccessibleOrEvent.state : 0);
} else {
let state = {};
let extState = {};
@@ -297,28 +288,47 @@ this.Utils = { // jshint ignore:line
getVirtualCursor: function getVirtualCursor(aDocument) {
let doc = (aDocument instanceof Ci.nsIAccessible) ? aDocument :
this.AccRetrieval.getAccessibleFor(aDocument);
return doc.QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
},
- getBounds: function getBounds(aAccessible) {
- let objX = {}, objY = {}, objW = {}, objH = {};
- aAccessible.getBounds(objX, objY, objW, objH);
- return new Rect(objX.value, objY.value, objW.value, objH.value);
+ getContentResolution: function _getContentResolution(aAccessible) {
+ let resX = { value: 1 }, resY = { value: 1 };
+ aAccessible.document.window.QueryInterface(
+ Ci.nsIInterfaceRequestor).getInterface(
+ Ci.nsIDOMWindowUtils).getResolution(resX, resY);
+ return [resX.value, resY.value];
},
- getTextBounds: function getTextBounds(aAccessible, aStart, aEnd) {
- let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
- let objX = {}, objY = {}, objW = {}, objH = {};
- accText.getRangeExtents(aStart, aEnd, objX, objY, objW, objH,
- Ci.nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE);
- return new Rect(objX.value, objY.value, objW.value, objH.value);
+ getBounds: function getBounds(aAccessible, aPreserveContentScale) {
+ let objX = {}, objY = {}, objW = {}, objH = {};
+ aAccessible.getBounds(objX, objY, objW, objH);
+
+ let [scaleX, scaleY] = aPreserveContentScale ? [1, 1] :
+ this.getContentResolution(aAccessible);
+
+ return new Rect(objX.value, objY.value, objW.value, objH.value).scale(
+ scaleX, scaleY);
+ },
+
+ getTextBounds: function getTextBounds(aAccessible, aStart, aEnd,
+ aPreserveContentScale) {
+ let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
+ let objX = {}, objY = {}, objW = {}, objH = {};
+ accText.getRangeExtents(aStart, aEnd, objX, objY, objW, objH,
+ Ci.nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE);
+
+ let [scaleX, scaleY] = aPreserveContentScale ? [1, 1] :
+ this.getContentResolution(aAccessible);
+
+ return new Rect(objX.value, objY.value, objW.value, objH.value).scale(
+ scaleX, scaleY);
},
/**
* Get current display DPI.
*/
get dpi() {
delete this.dpi;
this.dpi = this.winUtils.displayDPI;
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -60,46 +60,38 @@ function forwardToChild(aMessage, aListe
newJSON.x -= content.mozInnerScreenX;
newJSON.y -= content.mozInnerScreenY;
}
mm.sendAsyncMessage(aMessage.name, newJSON);
return true;
}
function activateContextMenu(aMessage) {
- function sendContextMenuCoordinates(aAccessible) {
- let bounds = Utils.getBounds(aAccessible);
- sendAsyncMessage('AccessFu:ActivateContextMenu', {bounds: bounds});
- }
-
let position = Utils.getVirtualCursor(content.document).position;
if (!forwardToChild(aMessage, activateContextMenu, position)) {
- sendContextMenuCoordinates(position);
+ sendAsyncMessage('AccessFu:ActivateContextMenu',
+ { bounds: Utils.getBounds(position, true) });
}
}
function presentCaretChange(aText, aOldOffset, aNewOffset) {
if (aOldOffset !== aNewOffset) {
let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
aOldOffset, aOldOffset, true);
sendAsyncMessage('AccessFu:Present', msg);
}
}
function scroll(aMessage) {
- function sendScrollCoordinates(aAccessible) {
- let bounds = Utils.getBounds(aAccessible);
+ let position = Utils.getVirtualCursor(content.document).position;
+ if (!forwardToChild(aMessage, scroll, position)) {
sendAsyncMessage('AccessFu:DoScroll',
- { bounds: bounds,
+ { bounds: Utils.getBounds(position, true),
page: aMessage.json.page,
horizontal: aMessage.json.horizontal });
- }
-
- let position = Utils.getVirtualCursor(content.document).position;
- if (!forwardToChild(aMessage, scroll, position)) {
sendScrollCoordinates(position);
}
}
function adjustRange(aMessage) {
function sendUpDownKey(aAccessible) {
let acc = Utils.getEmbeddedControl(aAccessible) || aAccessible;
let elem = acc.DOMNode;
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -402,28 +402,28 @@ const nodeResolve = iced(function nodeRe
// Resolve again
id = exports.resolve(id, requirer);
// we assume that extensions are correct, i.e., a directory doesnt't have '.js'
// and a js file isn't named 'file.json.js'
let fullId = join(rootURI, id);
let resolvedPath;
- if (resolvedPath = loadAsFile(fullId))
+ if ((resolvedPath = loadAsFile(fullId)))
return stripBase(rootURI, resolvedPath);
- else if (resolvedPath = loadAsDirectory(fullId))
+ else if ((resolvedPath = loadAsDirectory(fullId)))
return stripBase(rootURI, resolvedPath);
// If manifest has dependencies, attempt to look up node modules
// in the `dependencies` list
else {
let dirs = getNodeModulePaths(dirname(join(rootURI, requirer))).map(dir => join(dir, id));
for (let i = 0; i < dirs.length; i++) {
- if (resolvedPath = loadAsFile(dirs[i]))
+ if ((resolvedPath = loadAsFile(dirs[i])))
return stripBase(rootURI, resolvedPath);
- if (resolvedPath = loadAsDirectory(dirs[i]))
+ if ((resolvedPath = loadAsDirectory(dirs[i])))
return stripBase(rootURI, resolvedPath);
}
}
// We would not find lookup for things like `sdk/tabs`, as that's part of
// the alias mapping. If during `generateMap`, the runtime lookup resolves
// with `resolveURI` -- if during runtime, then `resolve` will throw.
return void 0;
@@ -454,17 +454,17 @@ function loadAsFile (path) {
function loadAsDirectory (path) {
let found;
try {
// If `path/package.json` exists, parse the `main` entry
// and attempt to load that
let main = getManifestMain(JSON.parse(readURI(path + '/package.json')));
if (main != null) {
let tmpPath = join(path, main);
- if (found = loadAsFile(tmpPath))
+ if ((found = loadAsFile(tmpPath)))
return found
}
try {
let tmpPath = path + '/index.js';
readURI(tmpPath);
return tmpPath;
} catch (e) {}
} catch (e) {
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -1196,13 +1196,12 @@ const kTransferCid = Components.ID("{1b4
/**
* Contract ID of the service implementing nsITransfer.
*/
const kTransferContractId = "@mozilla.org/transfer;1";
// Override Toolkit's nsITransfer implementation with the one from the
// JavaScript API for downloads. This will eventually be removed when
-// nsIDownloadManager will not be available anymore (bug 851471). The
-// old code in this module will be removed in bug 899110.
+// nsIDownloadManager will not be available anymore (bug 851471).
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.registerFactory(kTransferCid, "",
kTransferContractId, null);
new file mode 100644
--- /dev/null
+++ b/b2g/config/dolphin/config.json
@@ -0,0 +1,38 @@
+{
+ "config_version": 2,
+ "mock_target": "mozilla-centos6-x86_64",
+ "mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel", "git", "libxml2", "bc"],
+ "mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
+ "build_targets": ["kernelheader", ""],
+ "upload_files": [
+ "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+ "{objdir}/dist/b2g-*.tar.gz",
+ "{workdir}/sources.xml"
+ ],
+ "public_upload_files": [
+ "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+ "{objdir}/dist/b2g-*.tar.gz",
+ "{workdir}/sources.xml"
+ ],
+ "zip_files": [
+ ["{workdir}/out/target/product/scx15_sp7715ga/*.img", "out/target/product/scx15_sp7715ga/"],
+ "{workdir}/flash.sh",
+ "{workdir}/load-config.sh",
+ "{workdir}/.config",
+ "{workdir}/sources.xml"
+ ],
+ "env": {
+ "VARIANT": "user",
+ "MOZILLA_OFFICIAL": "1"
+ },
+ "b2g_manifest": "dolphin.xml",
+ "b2g_manifest_intree": true,
+ "additional_source_tarballs": [],
+ "gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
+ "gaia": {
+ "l10n": {
+ "vcs": "hgtool",
+ "root": "https://hg.mozilla.org/gaia-l10n"
+ }
+ }
+}
new file mode 100644
--- /dev/null
+++ b/b2g/config/dolphin/sources.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" ?><manifest>
+ <!--original fetch url was https://android.googlesource.com/-->
+ <remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
+ <!--original fetch url was git://github.com/mozilla-b2g/-->
+ <remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
+ <!--original fetch url was git://github.com/mozilla/-->
+ <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
+ <!--original fetch url was git://github.com/apitrace/-->
+ <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
+ <!--original fetch url was git://codeaurora.org/-->
+ <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
+ <!--original fetch url was https://git.mozilla.org/releases-->
+ <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
+ <!-- B2G specific things. -->
+ <project name="platform_build" path="build" remote="b2g" revision="1865c6639c51f0290d5778adef146147d5d6a5f0">
+ <copyfile dest="Makefile" src="core/root.mk"/>
+ </project>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
+ <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
+ <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
+ <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
+ <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
+ <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
+ <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
+ <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
+ <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
+ <!-- Stock Android things -->
+ <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
+ <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
+ <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
+ <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
+ <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
+ <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
+ <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
+ <project name="device/sample" path="device/sample" revision="1a3d8efa0ad32ec8f145367a3cf0f54b97385c3c"/>
+ <project name="platform/abi/cpp" path="abi/cpp" revision="18f1b5e28734183ff8073fe86dc46bc4ebba8a59"/>
+ <project name="platform/bionic" path="bionic" revision="86b1f589c313422a7da1812512b9ec8d1cf9ba3c"/>
+ <project name="platform/bootable/recovery" path="bootable/recovery" revision="1f68d4c6a5d2e72bc02fa837af94c0a51afa94de"/>
+ <project name="platform/external/aac" path="external/aac" revision="fa3eba16446cc8f2f5e2dfc20d86a49dbd37299e"/>
+ <project name="platform/external/bison" path="external/bison" revision="c2418b886165add7f5a31fc5609f0ce2d004a90e"/>
+ <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="c50830cae1b748024eec7e73ad98a4e427f663c7"/>
+ <project name="platform/external/bsdiff" path="external/bsdiff" revision="23e322ab19fb7d74c2c37e40ce364d9f709bdcee"/>
+ <project name="platform/external/bzip2" path="external/bzip2" revision="1cb636bd8e9e5cdfd5d5b2909a122f6e80db62de"/>
+ <project name="platform/external/checkpolicy" path="external/checkpolicy" revision="0d73ef7049feee794f14cf1af88d05dae8139914"/>
+ <project name="platform/external/dhcpcd" path="external/dhcpcd" revision="84b7252b0a9d0edc9a1db1e0c518771d26b23058"/>
+ <project name="platform/external/dnsmasq" path="external/dnsmasq" revision="41d356427a632f5336384bfa45c8420ffc274f66"/>
+ <project name="platform/external/dropbear" path="external/dropbear" revision="a34ddbe3819bc465968f3676c734b405e655f8b7"/>
+ <project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="47478a2944a2a17c7fdebe9d92573db92013125c"/>
+ <project name="platform/external/elfutils" path="external/elfutils" revision="b23b2dfb354b3ccf5d1c5d39815f02e7048cf516"/>
+ <project name="platform/external/expat" path="external/expat" revision="0af0cb3bc7519e567bd9daff3dcd315ab0134a99"/>
+ <project name="platform/external/fdlibm" path="external/fdlibm" revision="0da5f683c9ddc9442af3b389b4220e91ccffb320"/>
+ <project name="platform/external/flac" path="external/flac" revision="ab37b6247df0e8c4ec0ccaa870e667f62c74975b"/>
+ <project name="platform/external/freetype" path="external/freetype" revision="899c67b6cfcd2010784fbf08c5415af16c526e0c"/>
+ <project name="platform/external/gcc-demangle" path="external/gcc-demangle" revision="9241386b62c353302c2f9eccda0672685b252b4d"/>
+ <project name="platform/external/genext2fs" path="external/genext2fs" revision="e11a9c7fe6f1cef99aad2f25afaea37b72fe9f93"/>
+ <project name="platform/external/giflib" path="external/giflib" revision="9aef3ea079a57c98a9207f8c3b95a5dc08ee74b5"/>
+ <project name="platform/external/gtest" path="external/gtest" revision="0f1ce3dd0b880b6ae0cf7f5413702b8ef542efb2"/>
+ <project name="platform/external/harfbuzz" path="external/harfbuzz" revision="858f2d28ac741ef139f74bdbdbcefa7560f17c91"/>
+ <project name="platform/external/harfbuzz_ng" path="external/harfbuzz_ng" revision="3309edccdbc2a92eb03a285abb27c1c1c4a88e43"/>
+ <project name="platform/external/iproute2" path="external/iproute2" revision="157d428913c3d738be481f12e8cbf9267b3b2862"/>
+ <project name="platform/external/ipsec-tools" path="external/ipsec-tools" revision="f4cb1ee4b00abbfb6f968dc25818c23b4b47e584"/>
+ <project name="platform/external/iptables" path="external/iptables" revision="93e814c9b08136846335ce463192d90ba59766bb"/>
+ <project name="platform/external/jack" path="external/jack" revision="5ceb2025ac5d25ed48183ac2d3dac4691fe761fb"/>
+ <project name="platform/external/jhead" path="external/jhead" revision="31b17e69a87e4caa50f9c6b1a47c84ef75f79d83"/>
+ <project name="platform/external/jpeg" path="external/jpeg" revision="68f6f73d3157cc0481826e03d0fae9586217a300"/>
+ <project name="platform/external/junit" path="external/junit" revision="3abf41974d8aae44b3bbd15d83487894253d287d"/>
+ <project name="platform/external/libgsm" path="external/libgsm" revision="50761abed8f4734970874165b386cfd4d9599db4"/>
+ <project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
+ <project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="9e987ccb716624d658f98abc7db2097e11e3d8ed"/>
+ <project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
+ <project name="platform/external/libogg" path="external/libogg" revision="ec0b24fb1468abe37be4164a6feb16568e036bde"/>
+ <project name="platform/external/libpcap" path="external/libpcap" revision="3a7bce5dda6a8db92c9248846d0255e68c3a5b2a"/>
+ <project name="platform/external/libpng" path="external/libpng" revision="b5e7fb4c103b3898cb78e9f7615cf7893626a5e9"/>
+ <project name="platform/external/libselinux" path="external/libselinux" revision="1e2cf2c4a2d15a9b1ca2d353b99fb6884413ffe1"/>
+ <project name="platform/external/libsepol" path="external/libsepol" revision="8fd7c65a336d45d5225f32363a9f26c1e3e60c3c"/>
+ <project name="platform/external/libvpx" path="external/libvpx" revision="5e563eddf3e143a4b670766b49f676ce39023322"/>
+ <project name="platform/external/mdnsresponder" path="external/mdnsresponder" revision="c46f53f5e072f23051c4eedef730386f7634dc11"/>
+ <project name="platform/external/mksh" path="external/mksh" revision="f8c396c4d446a038358106a301b329607a04633d"/>
+ <project name="platform/external/netcat" path="external/netcat" revision="444644cfa9a2f3002863caa168fb2d6b34dfd1e8"/>
+ <project name="platform/external/netperf" path="external/netperf" revision="58ecd3b7c76263900e38921360e334a416aec362"/>
+ <project name="platform/external/openssl" path="external/openssl" revision="bb8428f762b3632f493572c4f73957e1281ade79"/>
+ <project name="platform/external/protobuf" path="external/protobuf" revision="48ee66d295979372ed0234cefda42385daae8312"/>
+ <project name="platform/external/safe-iop" path="external/safe-iop" revision="aa0725fb1da35e47676b6da30009322eb5ed59be"/>
+ <project name="platform/external/scrypt" path="external/scrypt" revision="eb05b73c3bba21fff55529813109de4bad5ddbd1"/>
+ <project name="platform/external/sepolicy" path="external/sepolicy" revision="f3525622103090156a6bbd9a8609be8b009d223f"/>
+ <project name="platform/external/sfntly" path="external/sfntly" revision="30d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cd"/>
+ <project name="platform/external/skia" path="external/skia" revision="97c714a01e32e6aee7faf9c57fbbd4d95b41d353"/>
+ <project name="platform/external/sonivox" path="external/sonivox" revision="2dbbd3bac0f0e819d196a80cc7855054148ef8b6"/>
+ <project name="platform/external/speex" path="external/speex" revision="fb7db5853ffb841a4d32fea8b5c3a43e6b875cae"/>
+ <project name="platform/external/sqlite" path="external/sqlite" revision="ac0e0d5f866fbce0ebf00d0ddd615464849aa83b"/>
+ <project name="platform/external/stlport" path="external/stlport" revision="628e14d37c5b239839a466e81c74bf66255b770b"/>
+ <project name="platform/external/strace" path="external/strace" revision="1a4e05d53dec658a061acb9869cb1eb1342cd09d"/>
+ <project name="platform/external/svox" path="external/svox" revision="838228cc17b5798e51bc20d06e54dbd781e441db"/>
+ <project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
+ <project name="platform/external/tcpdump" path="external/tcpdump" revision="532b8f38c144da9a298260a5d8978ab9e8e3856c"/>
+ <project name="platform/external/tinyalsa" path="external/tinyalsa" revision="aa08b9c35638a32de0444a940cf47708e4ba0eda"/>
+ <project name="platform/external/tinycompress" path="external/tinycompress" revision="a85e245a09c028d36cbf04f233be10bc583691f5"/>
+ <project name="platform/external/tinyxml" path="external/tinyxml" revision="494e448824844d866e805831d1d5f5acb654065c"/>
+ <project name="platform/external/tinyxml2" path="external/tinyxml2" revision="c74b546f5af36968ffa56d7fd4529f4273b96f48"/>
+ <project name="platform/external/tremolo" path="external/tremolo" revision="0499204aa97d3e2978ee77d869dd033acb2196e2"/>
+ <project name="platform/external/webp" path="external/webp" revision="513e97bd307573e2adc776eb5368bd129aceaa4a"/>
+ <project name="platform/external/webrtc" path="external/webrtc" revision="446452f84e9cc4c75d8e80f6f05e24793397a19d"/>
+ <project name="platform/external/yaffs2" path="external/yaffs2" revision="a2cff2275e1b501ff478b03757d6e4f05fddc2db"/>
+ <project name="platform/external/zlib" path="external/zlib" revision="a5c7131da47c991585a6c6ac0c063b6d7d56e3fc"/>
+ <project name="platform/frameworks/base" path="frameworks/base" revision="2d12cb68a6c680e1ef50c6fbd19f782f67aec9de"/>
+ <project name="platform/frameworks/native" path="frameworks/native" revision="b6018ccb81af66e0523a4bfdc45f0bd2ab472b55"/>
+ <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="dbbe673145107e99883f62bafd70c5f43f11065c"/>
+ <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="aac6c4bb59a6577c97cbda68699829b507b7490d"/>
+ <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="fbeca55f4695dd07c0291213403533b8fbca4885"/>
+ <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="6e98e2d0762a8e6dc12df228261fd741db98531f"/>
+ <project name="platform/libcore" path="libcore" revision="e195beab082c09217318fc19250caeaf4c1bd800"/>
+ <project name="platform/libnativehelper" path="libnativehelper" revision="feeb36c2bd4adfe285f98f5de92e0f3771b2c115"/>
+ <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
+ <project name="platform/prebuilts/misc" path="prebuilts/misc" revision="ee724654c72825f8d732ba45caf75ca59e06975d"/>
+ <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
+ <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="1a982dd6b02b939c75cd116d2d9de97e6ff3de24"/>
+ <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
+ <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
+ <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
+ <project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
+ <project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
+ <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
+ <project name="platform/system/vold" path="system/vold" revision="118dec582647895a863dbbce8ec26bc7af457bbe"/>
+ <!--original fetch url was http://sprdsource.spreadtrum.com:8085/b2g/android-->
+ <remote fetch="https://git.mozilla.org/external/sprd-aosp" name="sprd-aosp"/>
+ <default remote="sprd-aosp" revision="sprdb2g_gonk4.4" sync-j="4"/>
+ <!-- Stock Android things -->
+ <project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
+ <!-- dolphin specific things -->
+ <project name="device/sprd" path="device/sprd" revision="054d217fc6efdeff296742b58b5bda427d9d4384"/>
+ <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="4e58336019b5cbcfd134caf55b142236cf986618"/>
+ <project name="platform/frameworks/av" path="frameworks/av" revision="cbd80d8c03fc639dd810b17c4b682c67abc06ee8"/>
+ <project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
+ <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
+ <project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
+ <project name="kernel/common" path="kernel" revision="7cd1a292befc685e8be55996cedad1386037cbea"/>
+ <project name="platform/system/core" path="system/core" revision="b5de04ae22343b6bdaa3455aee291bdf9a872738"/>
+ <project name="u-boot" path="u-boot" revision="81522506a5ade829a18bcc8d1f1813129010b6fe"/>
+ <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7feb3df0e150053e0143ef525f6e082bda320aea"/>
+ <project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="da06ca296bccf13e1f775ca5e7ba9b6d98069fc8"/>
+ <project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
+ <project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d994b716d979a5b57b11a61cc05d31fe7ca61d38"/>
+</manifest>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
- <project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
<!--original fetch url was git://codeaurora.org/-->
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="1865c6639c51f0290d5778adef146147d5d6a5f0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
- <project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
{
"git": {
"git_revision": "",
"remote": "",
"branch": ""
},
- "revision": "0aa0d2ae3f0ee2215c18808c88d9366666536e9b",
+ "revision": "03a4bc3b7d10bcc197511ac7accdb05346a0b9dd",
"repo_path": "/integration/gaia-central"
}
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
- <project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
- <project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
- <project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="33d4b999f464fbad1c23d488da4689c5de9967ec"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -975,17 +975,21 @@ pref("browser.safebrowsing.gethashURL",
pref("browser.safebrowsing.reportURL", "https://safebrowsing.google.com/safebrowsing/report?");
pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.malware.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
+
+// Turn off remote lookups in beta and stable channel.
+#ifndef RELEASE_BUILD
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
+#endif
#ifdef MOZILLA_OFFICIAL
// Normally the "client ID" sent in updates is appinfo.name, but for
// official Firefox releases from Mozilla we use a special identifier.
pref("browser.safebrowsing.id", "navclient-auto-ffox");
#endif
// Name of the about: page contributed by safebrowsing to handle display of error
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -433,16 +433,23 @@ var gPopupBlockerObserver = {
if (!this._reportButton && gURLBar)
this._reportButton = document.getElementById("page-report-button");
if (!gBrowser.selectedBrowser.blockedPopups) {
// Hide the icon in the location bar (if the location bar exists)
if (gURLBar)
this._reportButton.hidden = true;
+
+ // Hide the notification box (if it's visible).
+ var notificationBox = gBrowser.getNotificationBox();
+ var notification = notificationBox.getNotificationWithValue("popup-blocked");
+ if (notification) {
+ notificationBox.removeNotification(notification, false);
+ }
return;
}
if (gURLBar)
this._reportButton.hidden = false;
// Only show the notification again if we've not already shown it. Since
// notifications are per-browser, we don't need to worry about re-adding
--- a/browser/devtools/shared/AppCacheUtils.jsm
+++ b/browser/devtools/shared/AppCacheUtils.jsm
@@ -288,17 +288,24 @@ AppCacheUtils.prototype = {
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
let win = wm.getMostRecentWindow("navigator:browser");
win.gBrowser.selectedTab = win.gBrowser.addTab(
"about:cache-entry?storage=appcache&context=&eid=&uri=" + key);
},
clearAll: function ACU_clearAll() {
- Services.cache.evictEntries(Ci.nsICache.STORE_OFFLINE);
+ if (!Services.prefs.getBoolPref("browser.cache.disk.enable")) {
+ throw new Error(l10n.GetStringFromName("cacheDisabled"));
+ }
+
+ let appCacheStorage = Services.cache2.appCacheStorage(LoadContextInfo.default, null);
+ appCacheStorage.asyncEvictStorage({
+ onCacheEntryDoomed: function(result) {}
+ });
},
_getManifestURI: function ACU__getManifestURI() {
let deferred = promise.defer();
let getURI = () => {
let htmlNode = this.doc.querySelector("html[manifest]");
if (htmlNode) {
--- a/browser/devtools/styleinspector/test/browser_computedview_select-and-copy-styles.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_select-and-copy-styles.js
@@ -10,17 +10,17 @@ XPCOMUtils.defineLazyGetter(this, "osStr
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
});
let test = asyncTest(function*() {
yield addTab("data:text/html;charset=utf-8,computed view copy test");
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
- 'span { font-variant: small-caps; color: #000000; } ' +
+ 'span { font-variant-caps: small-caps; color: #000000; } ' +
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
'<h1>Some header text</h1>\n' +
'<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
'<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
'solely to provide some things to <span style="color: yellow">' +
'highlight</span> and <span style="font-weight: bold">count</span> ' +
'style list-items in the box at right. If you are reading this, ' +
@@ -53,17 +53,17 @@ function checkCopySelection(view) {
range.setStart(props[1], 0);
range.setEnd(props[3], 3);
contentDocument.defaultView.getSelection().addRange(range);
info("Checking that cssHtmlTree.siBoundCopy() returns the correct clipboard value");
let expectedPattern = "font-family: helvetica,sans-serif;[\\r\\n]+" +
"font-size: 16px;[\\r\\n]+" +
- "font-variant: small-caps;[\\r\\n]*";
+ "font-variant-caps: small-caps;[\\r\\n]*";
return waitForClipboard(() => {
fireCopyEvent(props[0]);
}, () => {
return checkClipboardData(expectedPattern);
}).then(() => {}, () => {
failedClipboard(expectedPattern);
});
@@ -75,17 +75,17 @@ function checkSelectAll(view) {
let contentDoc = view.styleDocument;
let prop = contentDoc.querySelector(".property-view");
info("Checking that _SelectAll() then copy returns the correct clipboard value");
view._onSelectAll();
let expectedPattern = "color: #FF0;[\\r\\n]+" +
"font-family: helvetica,sans-serif;[\\r\\n]+" +
"font-size: 16px;[\\r\\n]+" +
- "font-variant: small-caps;[\\r\\n]*";
+ "font-variant-caps: small-caps;[\\r\\n]*";
return waitForClipboard(() => {
fireCopyEvent(prop);
}, () => {
return checkClipboardData(expectedPattern);
}).then(() => {}, () => {
failedClipboard(expectedPattern);
});
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -811,16 +811,17 @@ bin/libfreebl_32int64_3.so
@BINPATH@/webapprt/chrome/@AB_CD@@JAREXT@
@BINPATH@/webapprt/chrome/@AB_CD@.manifest
@BINPATH@/webapprt/components/CommandLineHandler.js
@BINPATH@/webapprt/components/ContentPermission.js
@BINPATH@/webapprt/components/DirectoryProvider.js
@BINPATH@/webapprt/components/PaymentUIGlue.js
@BINPATH@/webapprt/components/components.manifest
@BINPATH@/webapprt/defaults/preferences/prefs.js
+@BINPATH@/webapprt/modules/DownloadView.jsm
@BINPATH@/webapprt/modules/Startup.jsm
@BINPATH@/webapprt/modules/WebappRT.jsm
@BINPATH@/webapprt/modules/WebappManager.jsm
@BINPATH@/webapprt/modules/RemoteDebugger.jsm
@BINPATH@/webapprt/modules/WebRTCHandler.jsm
#endif
#ifdef MOZ_METRO
--- a/build/sanitizers/lsan_suppressions.txt
+++ b/build/sanitizers/lsan_suppressions.txt
@@ -23,22 +23,53 @@ leak:pixman_implementation_lookup_compos
# Bug 987918 - Font shutdown leaks when CLEANUP_MEMORY is not enabled.
leak:libfontconfig.so
leak:GI___strdup
# The symbol is really __GI___strdup, but if you have the leading _, it doesn't suppress it.
###
-### Many leaks only affect some test suites. The suite annotations are not checked.
+### Bug 979928 - WebRTC leaks. m2, m3.
###
-# Bug 979928 - WebRTC is leaky. m2, m3
-leak:/media/mtransport/
-leak:/media/webrtc/signaling/
+# WebRTC leaks added for Mochitest 2.
+leak:NR_reg_init
+leak:fsmdef_init
+leak:r_log_register
+leak:nr_reg_set
+leak:ccsnap_device_init
+leak:ccsnap_line_init
+leak:media/webrtc/signaling/src/sipcc/core/common/init.c
+leak:cprPostMessage
+leak:mozilla::NrIceStunServer::Create
+
+# Additional WebRTC leak suppressions added for Mochitest 3.
+leak:mozilla::TransportLayerDtls::Setup
+leak:mozilla::NrIceTurnServer::Create
+# There are about 228KB of leaks from the call to |pmsg->sdp = cpr_malloc(sdp_size);|
+# in send_message_helper.
+leak:send_message_helper
+leak:fsmdef_ev_createoffer
+leak:fsmdef_ev_setremotedesc
+leak:fsmdef_ev_setlocaldesc
+leak:fsmdef_ev_createanswer
+# About 70KB of leaks under this stack.
+leak:vcmRxAllocICE_s
+leak:vcmRxStartICE_m
+# About 50KB of leaks under this stack.
+leak:ccsnap_EscapeStrToLocaleStr
+leak:gsmsdp_add_default_audio_formats_to_local_sdp
+leak:gsmsdp_add_default_video_formats_to_local_sdp
+leak:CCAPI_CallInfo_getMediaStreams
+
+
+###
+### Many leaks only affect some test suites. The suite annotations are not checked.
+###
# Bug 981195 - Small leak in the parser. m4
leak:TypeCompartment::fixObjectType
# Bug 982111 - WebM is leaking. m1
leak:nestegg_read_packet
# Bug 987385 - Various plugin leaks. m3
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -723,30 +723,30 @@ public:
void ScrollIntoView()
{
ScrollIntoView(true);
}
void ScrollIntoView(bool aTop);
int32_t ScrollTop()
{
nsIScrollableFrame* sf = GetScrollFrame();
- return sf ? sf->GetScrollPositionCSSPixels().y : 0;
+ return sf ? sf->GetScrollPositionCSSPixels().y.value : 0;
}
void SetScrollTop(int32_t aScrollTop)
{
nsIScrollableFrame* sf = GetScrollFrame();
if (sf) {
sf->ScrollToCSSPixels(CSSIntPoint(sf->GetScrollPositionCSSPixels().x,
aScrollTop));
}
}
int32_t ScrollLeft()
{
nsIScrollableFrame* sf = GetScrollFrame();
- return sf ? sf->GetScrollPositionCSSPixels().x : 0;
+ return sf ? sf->GetScrollPositionCSSPixels().x.value : 0;
}
void SetScrollLeft(int32_t aScrollLeft)
{
nsIScrollableFrame* sf = GetScrollFrame();
if (sf) {
sf->ScrollToCSSPixels(CSSIntPoint(aScrollLeft,
sf->GetScrollPositionCSSPixels().y));
}
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -400,54 +400,27 @@ public:
static bool CanCallerAccess(nsIDOMNode *aNode);
static bool CanCallerAccess(nsINode* aNode);
// Check if the (JS) caller can access aWindow.
// aWindow can be either outer or inner window.
static bool CanCallerAccess(nsPIDOMWindow* aWindow);
/**
- * Get the window through the JS context that's currently on the stack.
- * If there's no JS context currently on the stack, returns null.
- */
- static nsPIDOMWindow *GetWindowFromCaller();
-
- /**
- * The two GetDocumentFrom* functions below allow a caller to get at a
- * document that is relevant to the currently executing script.
- *
* GetDocumentFromCaller gets its document by looking at the last called
* function and finding the document that the function itself relates to.
* For example, consider two windows A and B in the same origin. B has a
* function which does something that ends up needing the current document.
* If a script in window A were to call B's function, GetDocumentFromCaller
* would find that function (in B) and return B's document.
*
- * GetDocumentFromContext gets its document by looking at the currently
- * executing context's global object and returning its document. Thus,
- * given the example above, GetDocumentFromCaller would see that the
- * currently executing script was in window A, and return A's document.
- */
- /**
- * Get the document from the currently executing function. This will return
- * the document that the currently executing function is in/from.
- *
* @return The document or null if no JS Context.
*/
static nsIDocument* GetDocumentFromCaller();
- /**
- * Get the document through the JS context that's currently on the stack.
- * If there's no JS context currently on the stack it will return null.
- * This will return the document of the calling script.
- *
- * @return The document or null if no JS context
- */
- static nsIDocument* GetDocumentFromContext();
-
// Check if a node is in the document prolog, i.e. before the document
// element.
static bool InProlog(nsINode *aNode);
static nsIParserService* GetParserService();
static nsNameSpaceManager* NameSpaceManager()
{
@@ -2274,19 +2247,17 @@ private:
static nsILineBreaker* sLineBreaker;
static nsIWordBreaker* sWordBreaker;
static nsIBidiKeyboard* sBidiKeyboard;
static bool sInitialized;
static uint32_t sScriptBlockerCount;
-#ifdef DEBUG
static uint32_t sDOMNodeRemovedSuppressCount;
-#endif
static uint32_t sMicroTaskLevel;
// Not an nsCOMArray because removing elements from those is slower
static nsTArray< nsCOMPtr<nsIRunnable> >* sBlockedScriptRunners;
static uint32_t sRunnersCountAtFirstBlocker;
static uint32_t sScriptBlockerCountWhereRunnersPrevented;
static nsIInterfaceRequestor* sSameOriginChecker;
@@ -2333,24 +2304,20 @@ public:
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class MOZ_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved :
public nsAutoScriptBlocker {
public:
nsAutoScriptBlockerSuppressNodeRemoved() {
-#ifdef DEBUG
++nsContentUtils::sDOMNodeRemovedSuppressCount;
-#endif
}
~nsAutoScriptBlockerSuppressNodeRemoved() {
-#ifdef DEBUG
--nsContentUtils::sDOMNodeRemovedSuppressCount;
-#endif
}
};
class MOZ_STACK_CLASS nsAutoMicroTask
{
public:
nsAutoMicroTask()
{
--- a/content/base/public/nsINodeList.h
+++ b/content/base/public/nsINodeList.h
@@ -3,19 +3,17 @@
* 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 nsINodeList_h___
#define nsINodeList_h___
#include "nsIDOMNodeList.h"
#include "nsWrapperCache.h"
-
-class nsIContent;
-class nsINode;
+#include "nsIContent.h"
// IID for the nsINodeList interface
#define NS_INODELIST_IID \
{ 0xadb5e54c, 0x6e96, 0x4102, \
{ 0x8d, 0x40, 0xe0, 0x12, 0x3d, 0xcf, 0x48, 0x7a } }
/**
* An internal interface for a reasonably fast indexOf.
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -681,17 +681,17 @@ WebSocket::Init(JSContext* aCx,
// Don't allow https:// to open ws://
if (!mSecure &&
!Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
false)) {
// Confirmed we are opening plain ws:// and want to prevent this from a
// secure context (e.g. https). Check the principal's uri to determine if
// we were loaded from https.
- nsCOMPtr<nsIGlobalObject> globalObject(BrokenGetEntryGlobal());
+ nsCOMPtr<nsIGlobalObject> globalObject(GetEntryGlobal());
if (globalObject) {
nsCOMPtr<nsIPrincipal> principal(globalObject->PrincipalOrNull());
if (principal) {
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
if (uri) {
bool originIsHttps = false;
rv = uri->SchemeIs("https", &originIsHttps);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -209,19 +209,17 @@ nsCOMArray<nsIAtom>* nsContentUtils::sUs
nsIStringBundleService *nsContentUtils::sStringBundleService;
nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
nsIContentPolicy *nsContentUtils::sContentPolicyService;
bool nsContentUtils::sTriedToGetContentPolicy = false;
nsILineBreaker *nsContentUtils::sLineBreaker;
nsIWordBreaker *nsContentUtils::sWordBreaker;
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
uint32_t nsContentUtils::sScriptBlockerCount = 0;
-#ifdef DEBUG
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
-#endif
uint32_t nsContentUtils::sMicroTaskLevel = 0;
nsTArray< nsCOMPtr<nsIRunnable> >* nsContentUtils::sBlockedScriptRunners = nullptr;
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
bool nsContentUtils::sAllowXULXBL_for_file = false;
@@ -1948,61 +1946,30 @@ nsContentUtils::TraceSafeJSContext(JSTra
}
if (JSObject* global = js::DefaultObjectForContextOrNull(cx)) {
JS::AssertGCThingMustBeTenured(global);
JS_CallUnbarrieredObjectTracer(aTrc, &global, "safe context");
MOZ_ASSERT(global == js::DefaultObjectForContextOrNull(cx));
}
}
-nsPIDOMWindow *
-nsContentUtils::GetWindowFromCaller()
-{
- JSContext *cx = GetCurrentJSContext();
- if (cx) {
- nsCOMPtr<nsPIDOMWindow> win =
- do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
- return win;
- }
-
- return nullptr;
-}
-
nsIDocument*
nsContentUtils::GetDocumentFromCaller()
{
AutoJSContext cx;
nsCOMPtr<nsPIDOMWindow> win =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(cx)));
if (!win) {
return nullptr;
}
return win->GetExtantDoc();
}
-nsIDocument*
-nsContentUtils::GetDocumentFromContext()
-{
- JSContext *cx = GetCurrentJSContext();
- if (cx) {
- nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
-
- if (sgo) {
- nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(sgo);
- if (pwin) {
- return pwin->GetExtantDoc();
- }
- }
- }
-
- return nullptr;
-}
-
bool
nsContentUtils::IsCallerChrome()
{
MOZ_ASSERT(NS_IsMainThread());
if (SubjectPrincipal() == sSystemPrincipal) {
return true;
}
@@ -3915,40 +3882,37 @@ nsContentUtils::HasMutationListeners(nsI
void
nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
nsIDocument* aOwnerDoc)
{
NS_PRECONDITION(aChild, "Missing child");
NS_PRECONDITION(aChild->GetParentNode() == aParent, "Wrong parent");
NS_PRECONDITION(aChild->OwnerDoc() == aOwnerDoc, "Wrong owner-doc");
- // This checks that IsSafeToRunScript is true since we don't want to fire
- // events when that is false. We can't rely on EventDispatcher to assert
- // this in this situation since most of the time there are no mutation
- // event listeners, in which case we won't even attempt to dispatch events.
- // However this also allows for two exceptions. First off, we don't assert
- // if the mutation happens to native anonymous content since we never fire
- // mutation events on such content anyway.
- // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
- // that is a know case when we'd normally fire a mutation event, but can't
- // make that safe and so we suppress it at this time. Ideally this should
- // go away eventually.
- NS_ASSERTION((aChild->IsNodeOfType(nsINode::eCONTENT) &&
- static_cast<nsIContent*>(aChild)->
- IsInNativeAnonymousSubtree()) ||
- IsSafeToRunScript() ||
- sDOMNodeRemovedSuppressCount,
- "Want to fire DOMNodeRemoved event, but it's not safe");
-
// Having an explicit check here since it's an easy mistake to fall into,
// and there might be existing code with problems. We'd rather be safe
// than fire DOMNodeRemoved in all corner cases. We also rely on it for
// nsAutoScriptBlockerSuppressNodeRemoved.
if (!IsSafeToRunScript()) {
- WarnScriptWasIgnored(aOwnerDoc);
+ // This checks that IsSafeToRunScript is true since we don't want to fire
+ // events when that is false. We can't rely on EventDispatcher to assert
+ // this in this situation since most of the time there are no mutation
+ // event listeners, in which case we won't even attempt to dispatch events.
+ // However this also allows for two exceptions. First off, we don't assert
+ // if the mutation happens to native anonymous content since we never fire
+ // mutation events on such content anyway.
+ // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
+ // that is a know case when we'd normally fire a mutation event, but can't
+ // make that safe and so we suppress it at this time. Ideally this should
+ // go away eventually.
+ if (!(aChild->IsContent() && aChild->AsContent()->IsInNativeAnonymousSubtree()) &&
+ !sDOMNodeRemovedSuppressCount) {
+ NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe");
+ WarnScriptWasIgnored(aOwnerDoc);
+ }
return;
}
if (HasMutationListeners(aChild,
NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
InternalMutationEvent mutation(true, NS_MUTATION_NODEREMOVED);
mutation.mRelatedNode = do_QueryInterface(aParent);
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1424,20 +1424,20 @@ nsHTMLDocument::Open(JSContext* cx,
bool inUnload;
shell->GetIsInUnload(&inUnload);
if (inUnload) {
nsCOMPtr<nsIDocument> ret = this;
return ret.forget();
}
- // Note: We want to use GetDocumentFromContext here because this document
+ // Note: We want to use GetEntryDocument here because this document
// should inherit the security information of the document that's opening us,
// (since if it's secure, then it's presumably trusted).
- nsCOMPtr<nsIDocument> callerDoc = nsContentUtils::GetDocumentFromContext();
+ nsCOMPtr<nsIDocument> callerDoc = GetEntryDocument();
if (!callerDoc) {
// If we're called from C++ or in some other way without an originating
// document we can't do a document.open w/o changing the principal of the
// document to something like about:blank (as that's the only sane thing to
// do when we don't know the origin of this call), and since we can't
// change the principals of a document for security reasons we'll have to
// refuse to go ahead with this call.
--- a/content/media/gmp/GMPChild.cpp
+++ b/content/media/gmp/GMPChild.cpp
@@ -123,24 +123,25 @@ GMPChild::Init(const std::string& aPlugi
base::ProcessHandle aParentProcessHandle,
MessageLoop* aIOLoop,
IPC::Channel* aChannel)
{
if (!Open(aChannel, aParentProcessHandle, aIOLoop)) {
return false;
}
+#ifdef MOZ_CRASHREPORTER
+ SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
+#endif
+
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
mPluginPath = aPluginPath;
return true;
#endif
-#ifdef MOZ_CRASHREPORTER
- SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
-#endif
#if defined(XP_WIN)
mozilla::SandboxTarget::Instance()->StartSandbox();
#endif
return LoadPluginLibrary(aPluginPath);
}
bool
--- a/content/media/mediasource/SourceBufferResource.h
+++ b/content/media/mediasource/SourceBufferResource.h
@@ -70,34 +70,30 @@ private:
return nullptr;
}
};
class ResourceQueue : private nsDeque {
public:
ResourceQueue() :
nsDeque(new ResourceQueueDeallocator()),
+ mLogicalLength(0),
mOffset(0)
{
}
// Returns the logical byte offset of the start of the data.
inline uint64_t GetOffset() {
return mOffset;
}
// Returns the length of all items in the queue plus the offset.
// This is the logical length of the resource.
inline uint64_t GetLength() {
- uint64_t s = mOffset;
- for (uint32_t i = 0; i < GetSize(); ++i) {
- ResourceItem* item = ResourceAt(i);
- s += item->mData.Length();
- }
- return s;
+ return mLogicalLength;
}
// Copies aCount bytes from aOffset in the queue into aDest.
inline void CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
uint32_t offset = 0;
uint32_t start = GetAtOffset(aOffset, &offset);
uint32_t end = std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, GetSize());
for (uint32_t i = start; i < end; ++i) {
@@ -108,16 +104,17 @@ private:
offset = 0;
aCount -= bytes;
aDest += bytes;
}
}
}
inline void PushBack(ResourceItem* aItem) {
+ mLogicalLength += aItem->mData.Length();
nsDeque::Push(aItem);
}
// Evict data in queue if the total queue size is greater than
// aThreshold past the offset. Returns true if some data was
// actually evicted.
inline bool Evict(uint64_t aOffset, uint32_t aThreshold) {
bool evicted = false;
@@ -179,18 +176,20 @@ private:
}
return GetSize();
}
inline ResourceItem* PopFront() {
return static_cast<ResourceItem*>(nsDeque::PopFront());
}
- // Logical offset into the resource of the first element
- // in the queue.
+ // Logical length of the resource.
+ uint64_t mLogicalLength;
+
+ // Logical offset into the resource of the first element in the queue.
uint64_t mOffset;
};
public:
SourceBufferResource(nsIPrincipal* aPrincipal,
const nsACString& aType);
protected:
~SourceBufferResource();
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -62,19 +62,16 @@ MOCHITEST_MANIFESTS += ['test/mochitest.
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
EXPORTS += [
'AbstractMediaDecoder.h',
'AudioChannelFormat.h',
'AudioCompactor.h',
'AudioEventTimeline.h',
'AudioMixer.h',
- 'AudioNodeEngine.h',
- 'AudioNodeExternalInputStream.h',
- 'AudioNodeStream.h',
'AudioSampleFormat.h',
'AudioSegment.h',
'AudioStream.h',
'BufferDecoder.h',
'BufferMediaResource.h',
'DecoderTraits.h',
'DOMMediaStream.h',
'EncodedBufferCache.h',
@@ -125,19 +122,16 @@ EXPORTS.mozilla.dom += [
'VideoStreamTrack.h',
'VideoTrack.h',
'VideoTrackList.h',
]
UNIFIED_SOURCES += [
'AudioChannelFormat.cpp',
'AudioCompactor.cpp',
- 'AudioNodeEngine.cpp',
- 'AudioNodeExternalInputStream.cpp',
- 'AudioNodeStream.cpp',
'AudioSegment.cpp',
'AudioSink.cpp',
'AudioStream.cpp',
'AudioStreamTrack.cpp',
'AudioTrack.cpp',
'AudioTrackList.cpp',
'BufferDecoder.cpp',
'DOMMediaStream.cpp',
@@ -180,20 +174,16 @@ UNIFIED_SOURCES += [
# Latency.cpp needs to be built separately because it forces NSPR logging.
SOURCES += [
'DecoderTraits.cpp',
'Latency.cpp',
]
FAIL_ON_WARNINGS = True
-if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
- SOURCES += ['AudioNodeEngineNEON.cpp']
- SOURCES['AudioNodeEngineNEON.cpp'].flags += ['-mfpu=neon']
-
MSVC_ENABLE_PGO = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/content/base/src',
'/layout/generic',
rename from content/media/AudioNodeEngine.cpp
rename to content/media/webaudio/AudioNodeEngine.cpp
rename from content/media/AudioNodeEngine.h
rename to content/media/webaudio/AudioNodeEngine.h
rename from content/media/AudioNodeEngineNEON.cpp
rename to content/media/webaudio/AudioNodeEngineNEON.cpp
rename from content/media/AudioNodeEngineNEON.h
rename to content/media/webaudio/AudioNodeEngineNEON.h
rename from content/media/AudioNodeExternalInputStream.cpp
rename to content/media/webaudio/AudioNodeExternalInputStream.cpp
rename from content/media/AudioNodeExternalInputStream.h
rename to content/media/webaudio/AudioNodeExternalInputStream.h
rename from content/media/AudioNodeStream.cpp
rename to content/media/webaudio/AudioNodeStream.cpp
rename from content/media/AudioNodeStream.h
rename to content/media/webaudio/AudioNodeStream.h
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -14,16 +14,19 @@ MOCHITEST_MANIFESTS += [
]
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
EXPORTS += [
'AudioContext.h',
+ 'AudioNodeEngine.h',
+ 'AudioNodeExternalInputStream.h',
+ 'AudioNodeStream.h',
'AudioParamTimeline.h',
'MediaBufferDecoder.h',
'ThreeDPoint.h',
'WebAudioUtils.h',
]
EXPORTS.mozilla += [
'FFTBlock.h',
@@ -60,16 +63,19 @@ EXPORTS.mozilla.dom += [
UNIFIED_SOURCES += [
'AnalyserNode.cpp',
'AudioBuffer.cpp',
'AudioBufferSourceNode.cpp',
'AudioContext.cpp',
'AudioDestinationNode.cpp',
'AudioListener.cpp',
'AudioNode.cpp',
+ 'AudioNodeEngine.cpp',
+ 'AudioNodeExternalInputStream.cpp',
+ 'AudioNodeStream.cpp',
'AudioParam.cpp',
'AudioProcessingEvent.cpp',
'BiquadFilterNode.cpp',
'ChannelMergerNode.cpp',
'ChannelSplitterNode.cpp',
'ConvolverNode.cpp',
'DelayBuffer.cpp',
'DelayNode.cpp',
@@ -85,13 +91,20 @@ UNIFIED_SOURCES += [
'PannerNode.cpp',
'PeriodicWave.cpp',
'ScriptProcessorNode.cpp',
'ThreeDPoint.cpp',
'WaveShaperNode.cpp',
'WebAudioUtils.cpp',
]
+if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
+ SOURCES += ['AudioNodeEngineNEON.cpp']
+ SOURCES['AudioNodeEngineNEON.cpp'].flags += ['-mfpu=neon']
+
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
+LOCAL_INCLUDES += [
+ '..'
+]
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -123,16 +123,17 @@ skip-if = (toolkit == 'gonk' && !debug)
[test_pannerNode_equalPower.html]
[test_pannerNodeAbove.html]
[test_pannerNodeChannelCount.html]
[test_pannerNodeHRTFSymmetry.html]
[test_pannerNodeTail.html]
[test_periodicWave.html]
[test_scriptProcessorNode.html]
[test_scriptProcessorNodeChannelCount.html]
+[test_scriptProcessorNodePassThrough.html]
[test_scriptProcessorNode_playbackTime1.html]
[test_scriptProcessorNodeZeroInputOutput.html]
[test_scriptProcessorNodeNotConnected.html]
[test_singleSourceDest.html]
[test_stereoPanningWithGain.html]
[test_waveDecoder.html]
[test_waveShaper.html]
[test_waveShaperNoCurve.html]
--- a/content/media/webaudio/test/test_scriptProcessorNode.html
+++ b/content/media/webaudio/test/test_scriptProcessorNode.html
@@ -21,17 +21,17 @@ addLoadEvent(function() {
var buffer = null;
var sourceSP = context.createScriptProcessor(2048);
sourceSP.addEventListener("audioprocess", function(e) {
// generate the audio
for (var i = 0; i < 2048; ++i) {
// Make sure our first sample won't be zero
e.outputBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i + 1) / context.sampleRate);
- e.outputBuffer.getChannelData(0)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
+ e.outputBuffer.getChannelData(1)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
}
// Remember our generated audio
buffer = e.outputBuffer;
sourceSP.removeEventListener("audioprocess", arguments.callee);
}, false);
expectException(function() {
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_scriptProcessorNodePassThrough.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test ScriptProcessorNode with passthrough</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="webaudio.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+// We do not use our generic graph test framework here because
+// the testing logic here is sort of complicated, and would
+// not be easy to map to OfflineAudioContext, as ScriptProcessorNodes
+// can experience delays.
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var context = new AudioContext();
+ var buffer = null;
+
+ var sourceSP = context.createScriptProcessor(2048);
+ sourceSP.addEventListener("audioprocess", function(e) {
+ // generate the audio
+ for (var i = 0; i < 2048; ++i) {
+ // Make sure our first sample won't be zero
+ e.outputBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i + 1) / context.sampleRate);
+ e.outputBuffer.getChannelData(1)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
+ }
+ // Remember our generated audio
+ buffer = e.outputBuffer;
+
+ sourceSP.removeEventListener("audioprocess", arguments.callee);
+ }, false);
+
+ function findFirstNonZeroSample(buffer) {
+ for (var i = 0; i < buffer.length; ++i) {
+ if (buffer.getChannelData(0)[i] != 0) {
+ return i;
+ }
+ }
+ return buffer.length;
+ }
+
+ var sp = context.createScriptProcessor(2048);
+ sourceSP.connect(sp);
+
+ var spWrapped = SpecialPowers.wrap(sp);
+ ok("passThrough" in spWrapped, "ScriptProcessorNode should support the passThrough API");
+ spWrapped.passThrough = true;
+
+ sp.onaudioprocess = function() {
+ ok(false, "The audioprocess event must never be dispatched on the passthrough ScriptProcessorNode");
+ };
+
+ var sp2 = context.createScriptProcessor(2048);
+ sp.connect(sp2);
+ sp2.connect(context.destination);
+
+ var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
+
+ sp2.onaudioprocess = function(e) {
+ // Because of the initial latency added by the second script processor node,
+ // we will never see any generated audio frames in the first callback.
+ compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
+ compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
+
+ sp2.onaudioprocess = function(e) {
+ var firstNonZero = findFirstNonZeroSample(e.inputBuffer);
+ ok(firstNonZero <= 2048, "First non-zero sample within range");
+
+ compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), firstNonZero);
+ compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), firstNonZero);
+ compareChannels(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), 2048 - firstNonZero, firstNonZero, 0);
+ compareChannels(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), 2048 - firstNonZero, firstNonZero, 0);
+
+ if (firstNonZero == 0) {
+ // If we did not experience any delays, the test is done!
+ sp2.onaudioprocess = null;
+
+ SimpleTest.finish();
+ } else if (firstNonZero != 2048) {
+ // In case we just saw a zero buffer this time, wait one more round
+ sp2.onaudioprocess = function(e) {
+ compareChannels(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), firstNonZero, 0, 2048 - firstNonZero);
+ compareChannels(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), firstNonZero, 0, 2048 - firstNonZero);
+ compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), undefined, firstNonZero);
+ compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), undefined, firstNonZero);
+
+ sp2.onaudioprocess = null;
+
+ SimpleTest.finish();
+ };
+ }
+ };
+ };
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/webm/WebMBufferedParser.cpp
+++ b/content/media/webm/WebMBufferedParser.cpp
@@ -55,17 +55,17 @@ void WebMBufferedParser::Append(const un
} else {
mClusterIDPos = 0;
}
// Cluster ID found, it's likely this is a valid sync point. If this
// is a spurious match, the later parse steps will encounter an error
// and return to CLUSTER_SYNC.
if (mClusterIDPos == sizeof(CLUSTER_ID)) {
mClusterIDPos = 0;
- mClusterOffset = mCurrentOffset + (p - aBuffer) - 1;
+ mClusterOffset = mCurrentOffset + (p - aBuffer) - sizeof(CLUSTER_ID);
mState = READ_VINT;
mNextState = TIMECODE_SYNC;
}
break;
case READ_VINT: {
unsigned char c = *p++;
uint32_t mask;
mVIntLength = VIntLength(c, &mask);
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1960,26 +1960,26 @@ Navigator::GetMozCameras(ErrorResult& aR
}
mCameraManager = nsDOMCameraManager::CreateInstance(mWindow);
}
return mCameraManager;
}
-already_AddRefed<workers::ServiceWorkerContainer>
+already_AddRefed<ServiceWorkerContainer>
Navigator::ServiceWorker()
{
MOZ_ASSERT(mWindow);
if (!mServiceWorkerContainer) {
- mServiceWorkerContainer = new workers::ServiceWorkerContainer(mWindow);
+ mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
}
- nsRefPtr<workers::ServiceWorkerContainer> ref = mServiceWorkerContainer;
+ nsRefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
return ref.forget();
}
size_t
Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -31,16 +31,17 @@ class nsIPrincipal;
namespace mozilla {
namespace dom {
class Geolocation;
class systemMessageCallback;
struct MediaStreamConstraints;
class WakeLock;
class ArrayBufferViewOrBlobOrStringOrFormData;
struct MobileIdOptions;
+class ServiceWorkerContainer;
}
}
#ifdef MOZ_B2G_RIL
class nsIDOMMozIccManager;
#endif // MOZ_B2G_RIL
//*****************************************************************************
@@ -99,20 +100,16 @@ class TimeManager;
} // namespace time
namespace system {
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
class AudioChannelManager;
#endif
} // namespace system
-namespace workers {
-class ServiceWorkerContainer;
-} // namespace workers
-
class Navigator : public nsIDOMNavigator
, public nsIMozNavigatorNetwork
, public nsWrapperCache
{
public:
Navigator(nsPIDOMWindow *aInnerWindow);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -257,17 +254,17 @@ public:
ErrorResult& aRv);
void MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError,
uint64_t aInnerWindowID,
ErrorResult& aRv);
#endif // MOZ_MEDIA_NAVIGATOR
- already_AddRefed<workers::ServiceWorkerContainer> ServiceWorker();
+ already_AddRefed<ServiceWorkerContainer> ServiceWorker();
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
ErrorResult& aRv);
void GetLanguages(nsTArray<nsString>& aLanguages);
void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
@@ -335,17 +332,17 @@ private:
#endif
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
nsRefPtr<system::AudioChannelManager> mAudioChannelManager;
#endif
nsRefPtr<nsDOMCameraManager> mCameraManager;
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
nsRefPtr<time::TimeManager> mTimeManager;
- nsRefPtr<workers::ServiceWorkerContainer> mServiceWorkerContainer;
+ nsRefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
nsCOMPtr<nsPIDOMWindow> mWindow;
// Hashtable for saving cached objects newresolve created, so we don't create
// the object twice if asked for it twice, whether due to use of "delete" or
// due to Xrays. We could probably use a nsJSThingHashtable here, but then
// we'd need to figure out exactly how to trace that, and that seems to be
// rocket science. :(
nsInterfaceHashtable<nsStringHashKey, nsISupports> mCachedResolveResults;
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -117,37 +117,28 @@ ScriptSettingsStackEntry::ScriptSettings
ScriptSettingsStackEntry::~ScriptSettingsStackEntry()
{
// We must have an actual JS global for the entire time this is on the stack.
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
ScriptSettingsStack::Pop(this);
}
-// This mostly gets the entry global, but doesn't entirely match the spec in
-// certain edge cases. It's good enough for some purposes, but not others. If
-// you want to call this function, ping bholley and describe your use-case.
nsIGlobalObject*
-BrokenGetEntryGlobal()
+GetEntryGlobal()
{
- // We need the current JSContext in order to check the JS for
- // scripted frames that may have appeared since anyone last
- // manipulated the stack. If it's null, that means that there
- // must be no entry global on the stack.
- JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
- if (!cx) {
- MOZ_ASSERT(ScriptSettingsStack::EntryGlobal() == nullptr);
- return nullptr;
- }
-
- return nsJSUtils::GetDynamicScriptGlobal(cx);
+ return ScriptSettingsStack::EntryGlobal();
}
-// Note: When we're ready to expose it, GetEntryGlobal will look similar to
-// GetIncumbentGlobal below.
+nsIDocument*
+GetEntryDocument()
+{
+ nsCOMPtr<nsPIDOMWindow> entryWin = do_QueryInterface(GetEntryGlobal());
+ return entryWin ? entryWin->GetExtantDoc() : nullptr;
+}
nsIGlobalObject*
GetIncumbentGlobal()
{
// We need the current JSContext in order to check the JS for
// scripted frames that may have appeared since anyone last
// manipulated the stack. If it's null, that means that there
// must be no entry global on the stack, and therefore no incumbent
@@ -166,16 +157,32 @@ GetIncumbentGlobal()
return xpc::GetNativeForGlobal(global);
}
// Ok, nothing from the JS engine. Let's use whatever's on the
// explicit stack.
return ScriptSettingsStack::IncumbentGlobal();
}
+nsIGlobalObject*
+GetCurrentGlobal()
+{
+ JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
+ if (!cx) {
+ return nullptr;
+ }
+
+ JSObject *global = JS::CurrentGlobalOrNull(cx);
+ if (!global) {
+ return nullptr;
+ }
+
+ return xpc::GetNativeForGlobal(global);
+}
+
nsIPrincipal*
GetWebIDLCallerPrincipal()
{
MOZ_ASSERT(NS_IsMainThread());
ScriptSettingsStackEntry *entry = ScriptSettingsStack::EntryPoint();
// If we have an entry point that is not NoJSAPI, we know it must be an
// AutoEntryScript.
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -15,16 +15,17 @@
#include "mozilla/Maybe.h"
#include "jsapi.h"
class nsPIDOMWindow;
class nsGlobalWindow;
class nsIScriptContext;
+class nsIDocument;
namespace mozilla {
namespace dom {
// For internal use only - use AutoJSAPI instead.
namespace danger {
/**
@@ -58,27 +59,67 @@ private:
/*
* System-wide setup/teardown routines. Init and Destroy should be invoked
* once each, at startup and shutdown (respectively).
*/
void InitScriptSettings();
void DestroyScriptSettings();
-// This mostly gets the entry global, but doesn't entirely match the spec in
-// certain edge cases. It's good enough for some purposes, but not others. If
-// you want to call this function, ping bholley and describe your use-case.
-nsIGlobalObject* BrokenGetEntryGlobal();
+// To implement a web-compatible browser, it is often necessary to obtain the
+// global object that is "associated" with the currently-running code. This
+// process is made more complicated by the fact that, historically, different
+// algorithms have operated with different definitions of the "associated"
+// global.
+//
+// HTML5 formalizes this into two concepts: the "incumbent global" and the
+// "entry global". The incumbent global corresponds to the global of the
+// current script being executed, whereas the entry global corresponds to the
+// global of the script where the current JS execution began.
+//
+// There is also a potentially-distinct third global that is determined by the
+// current compartment. This roughly corresponds with the notion of Realms in
+// ECMAScript.
+//
+// Suppose some event triggers an event listener in window |A|, which invokes a
+// scripted function in window |B|, which invokes the |window.location.href|
+// setter in window |C|. The entry global would be |A|, the incumbent global
+// would be |B|, and the current compartment would be that of |C|.
+//
+// In general, it's best to use to use the most-closely-associated global
+// unless the spec says to do otherwise. In 95% of the cases, the global of
+// the current compartment (GetCurrentGlobal()) is the right thing. For
+// example, WebIDL constructors (new C.XMLHttpRequest()) are initialized with
+// the global of the current compartment (i.e. |C|).
+//
+// The incumbent global is very similar, but differs in a few edge cases. For
+// example, if window |B| does |C.location.href = "..."|, the incumbent global
+// used for the navigation algorithm is B, because no script from |C| was ever run.
+//
+// The entry global is used for various things like computing base URIs, mostly
+// for historical reasons.
+//
+// Note that all of these functions return bonafide global objects. This means
+// that, for Windows, they always return the inner.
-// Note: We don't yet expose GetEntryGlobal, because in order for it to be
-// correct, we first need to replace a bunch of explicit cx pushing in the
-// browser with AutoEntryScript. But GetIncumbentGlobal is simpler, because it
-// can mostly be inferred from the JS stack.
+// Returns the global associated with the top-most Candidate Entry Point on
+// the Script Settings Stack. See the HTML spec. This may be null.
+nsIGlobalObject* GetEntryGlobal();
+
+// If the entry global is a window, returns its extant document. Otherwise,
+// returns null.
+nsIDocument* GetEntryDocument();
+
+// Returns the global associated with the top-most entry of the the Script
+// Settings Stack. See the HTML spec. This may be null.
nsIGlobalObject* GetIncumbentGlobal();
+// Returns the global associated with the current compartment. This may be null.
+nsIGlobalObject* GetCurrentGlobal();
+
// JS-implemented WebIDL presents an interesting situation with respect to the
// subject principal. A regular C++-implemented API can simply examine the
// compartment of the most-recently-executed script, and use that to infer the
// responsible party. However, JS-implemented APIs are run with system
// principal, and thus clobber the subject principal of the script that
// invoked the API. So we have to do some extra work to keep track of this
// information.
//
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2496,21 +2496,16 @@ OldBindingConstructorEnabled(const nsGlo
expose = nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal());
}
if (!expose) {
return false;
}
}
- // Don't expose CSSFontFeatureValuesRule unless the pref is enabled
- if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
- return nsCSSFontFeatureValuesRule::PrefEnabled();
- }
-
return true;
}
static nsresult
LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
nsPIDOMWindow *win,
JS::MutableHandle<JSPropertyDescriptor> desc);
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -415,17 +415,17 @@ nsFocusManager::GetFocusedElement(nsIDOM
return NS_OK;
}
NS_IMETHODIMP
nsFocusManager::GetLastFocusMethod(nsIDOMWindow* aWindow, uint32_t* aLastFocusMethod)
{
// the focus method is stored on the inner window
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
- if (window)
+ if (window && window->IsOuterWindow())
window = window->GetCurrentInnerWindow();
if (!window)
window = mFocusedWindow;
*aLastFocusMethod = window ? window->GetFocusMethod() : 0;
NS_ASSERTION((*aLastFocusMethod & FOCUSMETHOD_MASK) == *aLastFocusMethod,
"invalid focus method");
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1477,20 +1477,21 @@ nsGlobalWindow::CleanUp()
mOpener = nullptr; // Forces Release
if (mContext) {
mContext = nullptr; // Forces Release
}
mChromeEventHandler = nullptr; // Forces Release
mParentTarget = nullptr;
- nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
-
- if (inner) {
- inner->CleanUp();
+ if (IsOuterWindow()) {
+ nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
+ if (inner) {
+ inner->CleanUp();
+ }
}
if (IsInnerWindow()) {
DisableGamepadUpdates();
mHasGamepad = false;
} else {
MOZ_ASSERT(!mHasGamepad);
}
@@ -5910,25 +5911,18 @@ nsGlobalWindow::RefreshCompartmentPrinci
JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),
nsJSPrincipals::get(mDoc->NodePrincipal()));
}
static already_AddRefed<nsIDocShellTreeItem>
GetCallerDocShellTreeItem()
{
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- nsCOMPtr<nsIDocShellTreeItem> callerItem;
-
- if (cx) {
- nsCOMPtr<nsIWebNavigation> callerWebNav =
- do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
-
- callerItem = do_QueryInterface(callerWebNav);
- }
+ nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
+ nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
return callerItem.forget();
}
bool
nsGlobalWindow::WindowExists(const nsAString& aName,
bool aLookForCallerOnJSStack)
{
@@ -6552,17 +6546,17 @@ nsGlobalWindow::Focus(ErrorResult& aErro
baseWin->GetVisibility(&isVisible);
}
if (!isVisible) {
// A hidden tab is being focused, ignore this call.
return;
}
- nsIDOMWindow *caller = nsContentUtils::GetWindowFromCaller();
+ nsCOMPtr<nsIDOMWindow> caller = do_QueryInterface(GetEntryGlobal());
nsCOMPtr<nsIDOMWindow> opener;
GetOpener(getter_AddRefs(opener));
// Enforce dom.disable_window_flip (for non-chrome), but still allow the
// window which opened us to raise us at times when popups are allowed
// (bugs 355482 and 369306).
bool canFocus = CanSetProperty("dom.disable_window_flip") ||
(opener == caller &&
@@ -7530,30 +7524,17 @@ nsGlobalWindow::FireAbuseEvents(bool aBl
// build the URI of the would-have-been popup window
// (see nsWindowWatcher::URIfromURL)
// first, fetch the opener's base URI
nsIURI *baseURL = nullptr;
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- nsCOMPtr<nsPIDOMWindow> contextWindow;
-
- if (cx) {
- nsIScriptContext *currentCX = nsJSUtils::GetDynamicScriptContext(cx);
- if (currentCX) {
- contextWindow = do_QueryInterface(currentCX->GetGlobalObject());
- }
- }
- if (!contextWindow) {
- contextWindow = this;
- }
-
- nsCOMPtr<nsIDocument> doc = contextWindow->GetDoc();
+ nsCOMPtr<nsIDocument> doc = GetEntryDocument();
if (doc)
baseURL = doc->GetDocBaseURI();
// use the base URI to build what would have been the popup's URI
nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
if (ios)
ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL,
getter_AddRefs(popupURI));
@@ -8248,17 +8229,17 @@ nsGlobalWindow::PostMessageMoz(JSContext
return;
}
}
// Convert the provided origin string into a URI for comparison purposes.
nsCOMPtr<nsIPrincipal> providedPrincipal;
if (aTargetOrigin.EqualsASCII("/")) {
- providedPrincipal = BrokenGetEntryGlobal()->PrincipalOrNull();
+ providedPrincipal = GetEntryGlobal()->PrincipalOrNull();
if (NS_WARN_IF(!providedPrincipal))
return;
}
// "*" indicates no specific origin is required.
else if (!aTargetOrigin.EqualsASCII("*")) {
nsCOMPtr<nsIURI> originURI;
if (NS_FAILED(NS_NewURI(getter_AddRefs(originURI), aTargetOrigin))) {
@@ -12798,21 +12779,17 @@ nsGlobalWindow::GetScrollFrame()
return presShell->GetRootScrollFrameAsScrollable();
}
return nullptr;
}
nsresult
nsGlobalWindow::SecurityCheckURL(const char *aURL)
{
- nsCOMPtr<nsPIDOMWindow> sourceWindow;
- JSContext* topCx = nsContentUtils::GetCurrentJSContext();
- if (topCx) {
- sourceWindow = do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(topCx));
- }
+ nsCOMPtr<nsPIDOMWindow> sourceWindow = do_QueryInterface(GetEntryGlobal());
if (!sourceWindow) {
sourceWindow = this;
}
AutoJSContext cx;
nsGlobalWindow* sourceWin = static_cast<nsGlobalWindow*>(sourceWindow.get());
JSAutoCompartment ac(cx, sourceWin->GetGlobalJSObject());
// Resolve the baseURI, which could be relative to the calling window.
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -594,16 +594,17 @@ public:
nsGlobalWindow *GetOuterWindowInternal()
{
return static_cast<nsGlobalWindow *>(GetOuterWindow());
}
nsGlobalWindow *GetCurrentInnerWindowInternal() const
{
+ MOZ_ASSERT(IsOuterWindow());
return static_cast<nsGlobalWindow *>(mInnerWindow);
}
nsGlobalWindow *EnsureInnerWindowInternal()
{
return static_cast<nsGlobalWindow *>(EnsureInnerWindow());
}
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -552,56 +552,48 @@ NS_ScriptErrorReporter(JSContext *cx,
xpc->MarkErrorUnreported(cx);
return;
}
}
}
}
}
- // XXX this means we are not going to get error reports on non DOM contexts
- nsIScriptContext *context = nsJSUtils::GetDynamicScriptContext(cx);
-
JS::Rooted<JS::Value> exception(cx);
::JS_GetPendingException(cx, &exception);
- // Note: we must do this before running any more code on cx (if cx is the
- // dynamic script context).
+ // Note: we must do this before running any more code on cx.
::JS_ClearPendingException(cx);
- if (context) {
- nsIScriptGlobalObject *globalObject = context->GetGlobalObject();
-
- if (globalObject) {
-
- nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
- if (win) {
- win = win->GetCurrentInnerWindow();
- }
- nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
- do_QueryInterface(globalObject);
- NS_ASSERTION(scriptPrincipal, "Global objects must implement "
- "nsIScriptObjectPrincipal");
- nsContentUtils::AddScriptRunner(
- new ScriptErrorEvent(JS_GetRuntime(cx),
- report,
- message,
- nsJSPrincipals::get(report->originPrincipals),
- scriptPrincipal->GetPrincipal(),
- win,
- exception,
- /* We do not try to report Out Of Memory via a dom
- * event because the dom event handler would
- * encounter an OOM exception trying to process the
- * event, and then we'd need to generate a new OOM
- * event for that new OOM instance -- this isn't
- * pretty.
- */
- report->errorNumber != JSMSG_OUT_OF_MEMORY));
- }
+ MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
+ nsCOMPtr<nsIGlobalObject> globalObject = GetEntryGlobal();
+ if (globalObject) {
+
+ nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
+ MOZ_ASSERT_IF(win, win->IsInnerWindow());
+ nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
+ do_QueryInterface(globalObject);
+ NS_ASSERTION(scriptPrincipal, "Global objects must implement "
+ "nsIScriptObjectPrincipal");
+ nsContentUtils::AddScriptRunner(
+ new ScriptErrorEvent(JS_GetRuntime(cx),
+ report,
+ message,
+ nsJSPrincipals::get(report->originPrincipals),
+ scriptPrincipal->GetPrincipal(),
+ win,
+ exception,
+ /* We do not try to report Out Of Memory via a dom
+ * event because the dom event handler would
+ * encounter an OOM exception trying to process the
+ * event, and then we'd need to generate a new OOM
+ * event for that new OOM instance -- this isn't
+ * pretty.
+ */
+ report->errorNumber != JSMSG_OUT_OF_MEMORY));
}
if (nsContentUtils::DOMWindowDumpEnabled()) {
// Print it to stderr as well, for the benefit of those invoking
// mozilla with -console.
nsAutoCString error;
error.AssignLiteral("JavaScript ");
if (JSREPORT_IS_STRICT(report->flags))
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -58,31 +58,16 @@ nsJSUtils::GetStaticScriptContext(JSObje
{
nsIScriptGlobalObject *nativeGlobal = GetStaticScriptGlobal(aObj);
if (!nativeGlobal)
return nullptr;
return nativeGlobal->GetScriptContext();
}
-nsIScriptGlobalObject *
-nsJSUtils::GetDynamicScriptGlobal(JSContext* aContext)
-{
- nsIScriptContext *scriptCX = GetDynamicScriptContext(aContext);
- if (!scriptCX)
- return nullptr;
- return scriptCX->GetGlobalObject();
-}
-
-nsIScriptContext *
-nsJSUtils::GetDynamicScriptContext(JSContext *aContext)
-{
- return GetScriptContextFromJSContext(aContext);
-}
-
uint64_t
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext)
{
if (!aContext)
return 0;
uint64_t innerWindowID = 0;
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -27,20 +27,16 @@ class nsJSUtils
public:
static bool GetCallingLocation(JSContext* aContext, const char* *aFilename,
uint32_t* aLineno);
static nsIScriptGlobalObject *GetStaticScriptGlobal(JSObject* aObj);
static nsIScriptContext *GetStaticScriptContext(JSObject* aObj);
- static nsIScriptGlobalObject *GetDynamicScriptGlobal(JSContext *aContext);
-
- static nsIScriptContext *GetDynamicScriptContext(JSContext *aContext);
-
/**
* Retrieve the inner window ID based on the given JSContext.
*
* @param JSContext aContext
* The JSContext from which you want to find the inner window ID.
*
* @returns uint64_t the inner window ID.
*/
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -23,39 +23,33 @@
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsError.h"
#include "nsDOMClassInfoID.h"
#include "nsReadableUtils.h"
#include "nsITextToSubURI.h"
#include "nsJSUtils.h"
#include "nsContentUtils.h"
+#include "nsGlobalWindow.h"
#include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h"
#include "nsNullPrincipal.h"
#include "ScriptSettings.h"
#include "mozilla/dom/LocationBinding.h"
using namespace mozilla;
using namespace mozilla::dom;
static nsresult
GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
{
aCharset.Truncate();
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- if (cx) {
- nsCOMPtr<nsPIDOMWindow> window =
- do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
- NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
- if (nsIDocument* doc = window->GetDoc()) {
- aCharset = doc->GetDocumentCharacterSet();
- }
+ if (nsIDocument* doc = GetEntryDocument()) {
+ aCharset = doc->GetDocumentCharacterSet();
}
return NS_OK;
}
nsLocation::nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell)
: mInnerWindow(aWindow)
{
@@ -540,33 +534,33 @@ nsLocation::SetHrefWithBase(const nsAStr
* we want to do a replace load, in such a situation.
* In other cases, for example if a event handler or a JS timer
* had a location.href in it, we want to do a normal load,
* so that the new url will be appended to Session History.
* This solution is tricky. Hopefully it isn't going to bite
* anywhere else. This is part of solution for bug # 39938, 72197
*
*/
- bool inScriptTag=false;
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- if (cx) {
- nsIScriptContext *scriptContext =
- nsJSUtils::GetDynamicScriptContext(cx);
+ bool inScriptTag = false;
+ nsIScriptContext* scriptContext = nullptr;
+ nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetEntryGlobal());
+ if (win) {
+ scriptContext = static_cast<nsGlobalWindow*>(win.get())->GetContextInternal();
+ }
- if (scriptContext) {
- if (scriptContext->GetProcessingScriptTag()) {
- // Now check to make sure that the script is running in our window,
- // since we only want to replace if the location is set by a
- // <script> tag in the same window. See bug 178729.
- nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
- docShell ? docShell->GetScriptGlobalObject() : nullptr;
- inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
- }
- }
- } //cx
+ if (scriptContext) {
+ if (scriptContext->GetProcessingScriptTag()) {
+ // Now check to make sure that the script is running in our window,
+ // since we only want to replace if the location is set by a
+ // <script> tag in the same window. See bug 178729.
+ nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
+ docShell ? docShell->GetScriptGlobalObject() : nullptr;
+ inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
+ }
+ }
return SetURI(newUri, aReplace || inScriptTag);
}
return result;
}
NS_IMETHODIMP
@@ -1015,32 +1009,30 @@ nsLocation::ValueOf(nsIDOMLocation** aRe
nsCOMPtr<nsIDOMLocation> loc(this);
loc.forget(aReturn);
return NS_OK;
}
nsresult
nsLocation::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
{
-
*sourceURL = nullptr;
- nsCOMPtr<nsIScriptGlobalObject> sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
- // If this JS context doesn't have an associated DOM window, we effectively
- // have no script entry point stack. This doesn't generally happen with the DOM,
+ nsIDocument* doc = GetEntryDocument();
+ // If there's no entry document, we either have no Script Entry Point or one
+ // that isn't a DOM Window. This doesn't generally happen with the DOM,
// but can sometimes happen with extension code in certain IPC configurations.
// If this happens, try falling back on the current document associated with
// the docshell. If that fails, just return null and hope that the caller passed
// an absolute URI.
- if (!sgo && GetDocShell()) {
- sgo = GetDocShell()->GetScriptGlobalObject();
+ if (!doc && GetDocShell()) {
+ nsCOMPtr<nsPIDOMWindow> docShellWin = do_QueryInterface(GetDocShell()->GetScriptGlobalObject());
+ if (docShellWin) {
+ doc = docShellWin->GetDoc();
+ }
}
- NS_ENSURE_TRUE(sgo, NS_OK);
- nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(sgo);
- NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
- nsIDocument* doc = window->GetDoc();
NS_ENSURE_TRUE(doc, NS_OK);
*sourceURL = doc->GetBaseURI().take();
return NS_OK;
}
bool
nsLocation::CallerSubsumes()
{
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -187,22 +187,17 @@ public:
// Internal getter/setter for the frame element, this version of the
// getter crosses chrome boundaries whereas the public scriptable
// one doesn't for security reasons.
mozilla::dom::Element* GetFrameElementInternal() const;
void SetFrameElementInternal(mozilla::dom::Element* aFrameElement);
bool IsLoadingOrRunningTimeout() const
{
- const nsPIDOMWindow *win = GetCurrentInnerWindow();
-
- if (!win) {
- win = this;
- }
-
+ const nsPIDOMWindow* win = IsInnerWindow() ? this : GetCurrentInnerWindow();
return !win->mIsDocumentLoaded || win->mRunningTimeout;
}
// Check whether a document is currently loading
bool IsLoading() const
{
const nsPIDOMWindow *win;
@@ -294,16 +289,17 @@ public:
nsPIDOMWindow *GetOuterWindow()
{
return mIsInnerWindow ? mOuterWindow.get() : this;
}
nsPIDOMWindow *GetCurrentInnerWindow() const
{
+ MOZ_ASSERT(IsOuterWindow());
return mInnerWindow;
}
nsPIDOMWindow *EnsureInnerWindow()
{
NS_ASSERTION(IsOuterWindow(), "EnsureInnerWindow called on inner window");
// GetDoc forces inner window creation if there isn't one already
GetDoc();
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -51,17 +51,18 @@ AddNonJSSizeOfWindowAndItsDescendents(ns
{
// Measure the window.
nsWindowSizes windowSizes(moz_malloc_size_of);
aWindow->AddSizeOfIncludingThis(&windowSizes);
windowSizes.addToTabSizes(aSizes);
// Measure the inner window, if there is one.
nsWindowSizes innerWindowSizes(moz_malloc_size_of);
- nsGlobalWindow* inner = aWindow->GetCurrentInnerWindowInternal();
+ nsGlobalWindow* inner = aWindow->IsOuterWindow() ? aWindow->GetCurrentInnerWindowInternal()
+ : nullptr;
if (inner) {
inner->AddSizeOfIncludingThis(&innerWindowSizes);
innerWindowSizes.addToTabSizes(aSizes);
}
nsCOMPtr<nsIDOMWindowCollection> frames;
nsresult rv = aWindow->GetFrames(getter_AddRefs(frames));
NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2640,10 +2640,17 @@ AssertReturnTypeMatchesJitinfo(const JSJ
default:
// Someone messed up their jitinfo type.
MOZ_ASSERT(false, "Unexpected JSValueType stored in jitinfo");
break;
}
}
#endif
+bool
+CallerSubsumes(JSObject *aObject)
+{
+ nsIPrincipal* objPrin = nsContentUtils::ObjectPrincipal(js::UncheckedUnwrap(aObject));
+ return nsContentUtils::SubjectPrincipal()->Subsumes(objPrin);
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2932,12 +2932,24 @@ AssertReturnTypeMatchesJitinfo(const JSJ
JS::Handle<JS::Value> aValue);
#endif
// Returns true if aObj's global has any of the permissions named in aPermissions
// set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
bool
CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
+bool
+CallerSubsumes(JSObject* aObject);
+
+MOZ_ALWAYS_INLINE bool
+CallerSubsumes(JS::Handle<JS::Value> aValue)
+{
+ if (!aValue.isObject()) {
+ return true;
+ }
+ return CallerSubsumes(&aValue.toObject());
+}
+
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1048,21 +1048,16 @@ DOMInterfaces = {
]
},
'ServiceWorker': {
'nativeType': 'mozilla::dom::workers::ServiceWorker',
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorker.h',
},
-'ServiceWorkerContainer': {
- 'nativeType': 'mozilla::dom::workers::ServiceWorkerContainer',
- 'headerFile': 'mozilla/dom/ServiceWorkerContainer.h',
-},
-
'ServiceWorkerGlobalScope': {
'headerFile': 'mozilla/dom/WorkerScope.h',
'workers': True,
},
'SharedWorker': {
'nativeType': 'mozilla::dom::workers::SharedWorker',
'headerFile': 'mozilla/dom/workers/bindings/SharedWorker.h',
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3567,16 +3567,19 @@ class JSToNativeConversionInfo():
${val} is a handle to the JS::Value in question
${holderName} replaced by the holder's name, if any
${declName} replaced by the declaration's name
${haveValue} replaced by an expression that evaluates to a boolean
for whether we have a JS::Value. Only used when
defaultValue is not None or when True is passed for
checkForValue to instantiateJSToNativeConversion.
+ ${passedToJSImpl} replaced by an expression that evaluates to a boolean
+ for whether this value is being passed to a JS-
+ implemented interface.
declType: A CGThing representing the native C++ type we're converting
to. This is allowed to be None if the conversion code is
supposed to be used as-is.
holderType: A CGThing representing the type of a "holder" which will
hold a possible reference to the C++ thing whose type we
returned in declType, or None if no such holder is needed.
@@ -3822,32 +3825,45 @@ def getJSToNativeConversionInfo(type, de
# Our caller will handle it
pass
else:
assert defaultValue is None
return templateBody
# A helper function for converting things that look like a JSObject*.
- def handleJSObjectType(type, isMember, failureCode):
+ def handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription):
if not isMember:
if isOptional:
# We have a specialization of Optional that will use a
# Rooted for the storage here.
declType = CGGeneric("JS::Handle<JSObject*>")
else:
declType = CGGeneric("JS::Rooted<JSObject*>")
declArgs = "cx"
else:
assert (isMember in
("Sequence", "Variadic", "Dictionary", "OwningUnion", "MozMap"))
# We'll get traced by the sequence or dictionary or union tracer
declType = CGGeneric("JSObject*")
declArgs = None
templateBody = "${declName} = &${val}.toObject();\n"
+
+ # For JS-implemented APIs, we refuse to allow passing objects that the
+ # API consumer does not subsume.
+ if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
+ templateBody = fill("""
+ if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
+ ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
+ $*{exceptionCode}
+ }
+ """,
+ sourceDescription=sourceDescription,
+ exceptionCode=exceptionCode) + templateBody
+
setToNullCode = "${declName} = nullptr;\n"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional,
declArgs=declArgs)
assert not (isEnforceRange and isClamp) # These are mutually exclusive
@@ -3912,17 +3928,18 @@ def getJSToNativeConversionInfo(type, de
arrayRef = "${declName}"
elementConversion = string.Template(elementInfo.template).substitute({
"val": "temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
- "holderName": "tempHolder"
+ "holderName": "tempHolder",
+ "passedToJSImpl": "${passedToJSImpl}"
})
# NOTE: Keep this in sync with variadic conversions as needed
templateBody = fill(
"""
JS::ForOfIterator iter(cx);
if (!iter.init($${val}, JS::ForOfIterator::AllowNonIterable)) {
$*{exceptionCode}
@@ -4016,17 +4033,18 @@ def getJSToNativeConversionInfo(type, de
mozMapRef = "${declName}"
valueConversion = string.Template(valueInfo.template).substitute({
"val": "temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
- "holderName": "tempHolder"
+ "holderName": "tempHolder",
+ "passedToJSImpl": "${passedToJSImpl}"
})
templateBody = fill(
"""
${mozMapType} &mozMap = ${mozMapRef};
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject());
JS::AutoIdArray ids(cx, JS_Enumerate(cx, mozMapObj));
@@ -4109,30 +4127,30 @@ def getJSToNativeConversionInfo(type, de
names = []
interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
if len(interfaceMemberTypes) > 0:
interfaceObject = []
for memberType in interfaceMemberTypes:
name = getUnionMemberName(memberType)
interfaceObject.append(
- CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext" %
+ CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext" %
(unionArgumentObj, name)))
names.append(name)
interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"),
pre="done = ", post=";\n\n", reindent=True)
else:
interfaceObject = None
arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
if len(arrayObjectMemberTypes) > 0:
assert len(arrayObjectMemberTypes) == 1
name = getUnionMemberName(arrayObjectMemberTypes[0])
arrayObject = CGGeneric(
- "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
+ "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
else:
arrayObject = None
dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
if len(dateObjectMemberTypes) > 0:
assert len(dateObjectMemberTypes) == 1
@@ -4146,52 +4164,54 @@ def getJSToNativeConversionInfo(type, de
dateObject = None
callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
if len(callbackMemberTypes) > 0:
assert len(callbackMemberTypes) == 1
memberType = callbackMemberTypes[0]
name = getUnionMemberName(memberType)
callbackObject = CGGeneric(
- "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
+ "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
else:
callbackObject = None
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
if len(dictionaryMemberTypes) > 0:
assert len(dictionaryMemberTypes) == 1
name = getUnionMemberName(dictionaryMemberTypes[0])
setDictionary = CGGeneric(
- "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
+ "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
else:
setDictionary = None
mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes)
if len(mozMapMemberTypes) > 0:
assert len(mozMapMemberTypes) == 1
name = getUnionMemberName(mozMapMemberTypes[0])
mozMapObject = CGGeneric(
- "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
+ "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
else:
mozMapObject = None
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
if len(objectMemberTypes) > 0:
assert len(objectMemberTypes) == 1
# Very important to NOT construct a temporary Rooted here, since the
# SetToObject call can call a Rooted constructor and we need to keep
# stack discipline for Rooted.
- object = CGGeneric("%s.SetToObject(cx, &${val}.toObject());\n"
- "done = true;\n" % unionArgumentObj)
+ object = CGGeneric("if (!%s.SetToObject(cx, &${val}.toObject(), ${passedToJSImpl})) {\n"
+ "%s"
+ "}\n"
+ "done = true;\n" % (unionArgumentObj, indent(exceptionCode)))
names.append(objectMemberTypes[0].name)
else:
object = None
hasObjectTypes = interfaceObject or arrayObject or dateObject or callbackObject or object or mozMapObject
if hasObjectTypes:
# "object" is not distinguishable from other types
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject)
@@ -4420,17 +4440,17 @@ def getJSToNativeConversionInfo(type, de
assert not isEnforceRange and not isClamp
descriptor = descriptorProvider.getDescriptor(
type.unroll().inner.identifier.name)
if descriptor.nativeType == 'JSObject':
# XXXbz Workers code does this sometimes
assert descriptor.workers
- return handleJSObjectType(type, isMember, failureCode)
+ return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
if descriptor.interface.isCallback():
name = descriptor.interface.identifier.name
if type.nullable() or isCallbackReturnValue:
declType = CGGeneric("nsRefPtr<%s>" % name)
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = indent(CGCallbackTempRoot(name).define())
@@ -4502,17 +4522,17 @@ def getJSToNativeConversionInfo(type, de
templateBody += str(FailureFatalCastableObjectUnwrapper(
descriptor,
"&${val}.toObject()",
"${declName}",
exceptionCode,
isCallbackReturnValue,
firstCap(sourceDescription)))
elif descriptor.workers:
- return handleJSObjectType(type, isMember, failureCode)
+ return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
else:
# Either external, or new-binding non-castable. We always have a
# holder for these, because we don't actually know whether we have
# to addref when unwrapping or not. So we just pass an
# getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
# it'll put a non-null pointer in there.
if forceOwningType:
# Don't return a holderType in this case; our declName
@@ -4821,32 +4841,45 @@ def getJSToNativeConversionInfo(type, de
declType = "JS::Value"
else:
assert not isMember
declType = "JS::Rooted<JS::Value>"
declArgs = "cx"
assert not isOptional
templateBody = "${declName} = ${val};\n"
+
+ # For JS-implemented APIs, we refuse to allow passing objects that the
+ # API consumer does not subsume.
+ if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
+ templateBody = fill("""
+ if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
+ ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
+ $*{exceptionCode}
+ }
+ """,
+ sourceDescription=sourceDescription,
+ exceptionCode=exceptionCode) + templateBody
+
# We may not have a default value if we're being converted for
# a setter, say.
if defaultValue:
if isinstance(defaultValue, IDLNullValue):
defaultHandling = "${declName} = JS::NullValue();\n"
else:
assert isinstance(defaultValue, IDLUndefinedValue)
defaultHandling = "${declName} = JS::UndefinedValue();\n"
templateBody = handleDefault(templateBody, defaultHandling)
return JSToNativeConversionInfo(templateBody,
declType=CGGeneric(declType),
declArgs=declArgs)
if type.isObject():
assert not isEnforceRange and not isClamp
- return handleJSObjectType(type, isMember, failureCode)
+ return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
if type.isDictionary():
# There are no nullable dictionaries
assert not type.nullable() or isCallbackReturnValue
# All optional dictionaries always have default values, so we
# should be able to assume not isOptional here.
assert not isOptional
# In the callback return value case we never have to worry
@@ -4886,17 +4919,17 @@ def getJSToNativeConversionInfo(type, de
"!%s(cx, ${val})" % dictionaryTest).define() + "\n"
else:
template = ""
dictLoc = "${declName}"
if type.nullable():
dictLoc += ".SetValue()"
- template += ('if (!%s.Init(cx, %s, "%s")) {\n'
+ template += ('if (!%s.Init(cx, %s, "%s", ${passedToJSImpl})) {\n'
"%s"
"}\n" % (dictLoc, val, firstCap(sourceDescription),
exceptionCodeIndented.define()))
if type.nullable():
declType = CGTemplatedType("Nullable", declType)
template = CGIfElseWrapper("${val}.isNullOrUndefined()",
CGGeneric("${declName}.SetNull();\n"),
@@ -5162,17 +5195,18 @@ class CGArgumentConverter(CGThing):
replacer = {
"index": index,
"argc": "args.length()"
}
self.replacementVariables = {
"declName": "arg%d" % index,
"holderName": ("arg%d" % index) + "_holder",
- "obj": "obj"
+ "obj": "obj",
+ "passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptorProvider))
}
self.replacementVariables["val"] = string.Template(
"args[${index}]").substitute(replacer)
haveValueCheck = string.Template(
"args.hasDefined(${index})").substitute(replacer)
self.replacementVariables["haveValue"] = haveValueCheck
self.descriptorProvider = descriptorProvider
if self.argument.optional and not self.argument.defaultValue:
@@ -5240,17 +5274,18 @@ class CGArgumentConverter(CGThing):
string.Template(typeConversion.template).substitute({
"val": val,
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder",
# Use the same ${obj} as for the variadic arg itself
- "obj": replacer["obj"]
+ "obj": replacer["obj"],
+ "passedToJSImpl": toStringBool(isJSImplementedDescriptor(self.descriptorProvider))
}), 4)
variadicConversion += (" }\n"
"}\n")
return variadicConversion
def getMaybeWrapValueFuncForType(type):
@@ -6736,17 +6771,18 @@ class CGMethodCall(CGThing):
isNullOrUndefined=isNullOrUndefined,
isOptional=argIsOptional,
sourceDescription=(argDesc % (distinguishingIndex + 1))),
{
"declName": "arg%d" % distinguishingIndex,
"holderName": ("arg%d" % distinguishingIndex) + "_holder",
"val": distinguishingArg,
"obj": "obj",
- "haveValue": "args.hasDefined(%d)" % distinguishingIndex
+ "haveValue": "args.hasDefined(%d)" % distinguishingIndex,
+ "passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptor))
},
checkForValue=argIsOptional)
caseBody.append(CGIndenter(testCode, indent))
# If we got this far, we know we unwrapped to the right
# C++ type, so just do the call. Start conversion with
# distinguishingIndex + 1, since we already converted
# distinguishingIndex.
@@ -8311,19 +8347,32 @@ def getUnionTypeTemplateVars(unionType,
mType = eObject;
""")
else:
body = dedent("""
MOZ_ASSERT(mUnion.mType == mUnion.eUninitialized);
mUnion.mValue.mObject.SetValue(cx, obj);
mUnion.mType = mUnion.eObject;
""")
- setter = ClassMethod("SetToObject", "void",
+
+ # It's a bit sketchy to do the security check after setting the value,
+ # but it keeps the code cleaner and lets us avoid rooting |obj| over the
+ # call to CallerSubsumes().
+ body = body + dedent("""
+ if (passedToJSImpl && !CallerSubsumes(obj)) {
+ ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "%s");
+ return false;
+ }
+ return true;
+ """)
+
+ setter = ClassMethod("SetToObject", "bool",
[Argument("JSContext*", "cx"),
- Argument("JSObject*", "obj")],
+ Argument("JSObject*", "obj"),
+ Argument("bool", "passedToJSImpl", default="false")],
inline=True, bodyInHeader=True,
body=body)
else:
# Important: we need to not have our declName involve
# maybe-GCing operations.
if conversionInfo.holderType is not None:
holderArgs = conversionInfo.holderArgs
@@ -8333,17 +8382,18 @@ def getUnionTypeTemplateVars(unionType,
else:
initHolder = ""
jsConversion = fill(
initHolder + conversionInfo.template,
val="value",
declName="memberSlot",
holderName=(holderName if ownsMembers else "%s.ref()" % holderName),
- destroyHolder=destroyHolder)
+ destroyHolder=destroyHolder,
+ passedToJSImpl="passedToJSImpl")
jsConversion = fill(
"""
tryNext = false;
{ // scope for memberSlot
${structType}& memberSlot = RawSetAs${name}(${ctorArgs});
$*{jsConversion}
}
@@ -8352,17 +8402,18 @@ def getUnionTypeTemplateVars(unionType,
structType=structType,
name=name,
ctorArgs=ctorArgs,
jsConversion=jsConversion)
setter = ClassMethod("TrySetTo" + name, "bool",
[Argument("JSContext*", "cx"),
Argument("JS::Handle<JS::Value>", "value"),
- Argument("bool&", "tryNext")],
+ Argument("bool&", "tryNext"),
+ Argument("bool", "passedToJSImpl", default="false")],
inline=not ownsMembers,
bodyInHeader=not ownsMembers,
body=jsConversion)
return {
"name": name,
"structType": structType,
"externalType": externalType,
@@ -9458,17 +9509,18 @@ class CGProxySpecialOperation(CGPerSigna
sourceDescription=("value being assigned to %s setter" %
descriptor.interface.identifier.name))
if argumentMutableValue is None:
argumentMutableValue = "desc.value()"
templateValues = {
"declName": argument.identifier.name,
"holderName": argument.identifier.name + "_holder",
"val": argumentMutableValue,
- "obj": "obj"
+ "obj": "obj",
+ "passedToJSImpl": "false"
}
self.cgRoot.prepend(instantiateJSToNativeConversion(info, templateValues))
elif operation.isGetter() or operation.isDeleter():
if foundVar is None:
self.cgRoot.prepend(CGGeneric("bool found;\n"))
def getArguments(self):
args = [(a, a.identifier.name) for a in self.arguments]
@@ -11082,17 +11134,18 @@ class CGDictionary(CGThing):
""",
memberInits="\n".join(memberInits))
body += "return true;\n"
return ClassMethod("Init", "bool", [
Argument('JSContext*', 'cx'),
Argument('JS::Handle<JS::Value>', 'val'),
- Argument('const char*', 'sourceDescription', default='"Value"')
+ Argument('const char*', 'sourceDescription', default='"Value"'),
+ Argument('bool', 'passedToJSImpl', default='false')
], body=body)
def initFromJSONMethod(self):
return ClassMethod(
"Init", "bool",
[Argument('const nsAString&', 'aJSON')],
body=dedent("""
MOZ_ASSERT(NS_IsMainThread());
@@ -11317,17 +11370,18 @@ class CGDictionary(CGThing):
def getMemberConversion(self, memberInfo):
member, conversionInfo = memberInfo
replacements = {
"val": "temp.ref()",
"declName": self.makeMemberName(member.identifier.name),
# We need a holder name for external interfaces, but
# it's scoped down to the conversion so we can just use
# anything we want.
- "holderName": "holder"
+ "holderName": "holder",
+ "passedToJSImpl": "passedToJSImpl"
}
# We can't handle having a holderType here
assert conversionInfo.holderType is None
if conversionInfo.dealWithOptional:
replacements["declName"] = "(" + replacements["declName"] + ".Value())"
if member.defaultValue:
replacements["haveValue"] = "!isNull && !temp->isUndefined()"
@@ -11453,16 +11507,21 @@ class CGDictionary(CGThing):
trace = CGGeneric('%s.TraceDictionary(trc);\n' % memberData)
elif type.isUnion():
trace = CGGeneric('%s.TraceUnion(trc);\n' % memberData)
else:
assert type.isSpiderMonkeyInterface()
trace = CGGeneric('%s.TraceSelf(trc);\n' % memberData)
if type.nullable():
trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable)
+ elif type.isMozMap():
+ # If you implement this, add a MozMap<object> to
+ # TestInterfaceJSDictionary and test it in test_bug1036214.html
+ # to make sure we end up with the correct security properties.
+ assert False
else:
assert False # unknown type
if not member.defaultValue:
trace = CGIfWrapper(trace, "%s.WasPassed()" % memberLoc)
return trace.define()
@@ -13384,17 +13443,18 @@ class CallbackMember(CGNativeMember):
def getResultConversion(self):
replacements = {
"val": "rval",
"holderName": "rvalHolder",
"declName": "rvalDecl",
# We actually want to pass in a null scope object here, because
# wrapping things into our current compartment (that of mCallback)
# is what we want.
- "obj": "nullptr"
+ "obj": "nullptr",
+ "passedToJSImpl": "false"
}
if isJSImplementedDescriptor(self.descriptorProvider):
isCallbackReturnValue = "JSImpl"
else:
isCallbackReturnValue = "Callback"
sourceDescription = "return value of %s" % self.getPrettyName()
convertType = instantiateJSToNativeConversion(
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -53,8 +53,9 @@ MSG_DEF(MSG_INVALID_ADVANCE_COUNT, 0, "0
MSG_DEF(MSG_DEFINEPROPERTY_ON_GSP, 0, "Not allowed to define a property on the named properties object.")
MSG_DEF(MSG_INVALID_URL, 1, "{0} is not a valid URL.")
MSG_DEF(MSG_METADATA_NOT_CONFIGURED, 0, "Either size or lastModified should be true.")
MSG_DEF(MSG_INVALID_READ_SIZE, 0, "0 (Zero) is not a valid read size.")
MSG_DEF(MSG_HEADERS_IMMUTABLE, 0, "Headers are immutable and cannot be modified.")
MSG_DEF(MSG_INVALID_HEADER_NAME, 1, "{0} is an invalid header name.")
MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, "{0} is an invalid header value.")
MSG_DEF(MSG_INVALID_HEADER_SEQUENCE, 0, "Headers require name/value tuples when being initialized by a sequence.")
+MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, "Permission denied to pass cross-origin object as {0}.")
--- a/dom/bindings/test/TestInterfaceJS.js
+++ b/dom/bindings/test/TestInterfaceJS.js
@@ -4,51 +4,49 @@
const Cu = Components.utils;
const Ci = Components.interfaces;
"use strict";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-var gGlobal = this;
-function checkGlobal(obj) {
- if (Object(obj) === obj && Cu.getGlobalForObject(obj) != gGlobal) {
- // This message may not make it to the caller in a useful form, so dump
- // as well.
- var msg = "TestInterfaceJS received an object from a different scope!";
- dump(msg + "\n");
- throw new Error(msg);
- }
-}
-
function TestInterfaceJS(anyArg, objectArg) {}
TestInterfaceJS.prototype = {
classID: Components.ID("{2ac4e026-cf25-47d5-b067-78d553c3cad8}"),
contractID: "@mozilla.org/dom/test-interface-js;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
- __init: function (anyArg, objectArg) {
+ __init: function (anyArg, objectArg, dictionaryArg) {
this._anyAttr = undefined;
this._objectAttr = null;
this._anyArg = anyArg;
this._objectArg = objectArg;
- checkGlobal(anyArg);
- checkGlobal(objectArg);
+ this._dictionaryArg = dictionaryArg;
},
get anyArg() { return this._anyArg; },
get objectArg() { return this._objectArg; },
+ get dictionaryArg() { return this._dictionaryArg; },
get anyAttr() { return this._anyAttr; },
- set anyAttr(val) { checkGlobal(val); this._anyAttr = val; },
+ set anyAttr(val) { this._anyAttr = val; },
get objectAttr() { return this._objectAttr; },
- set objectAttr(val) { checkGlobal(val); this._objectAttr = val; },
- pingPongAny: function(any) { checkGlobal(any); return any; },
- pingPongObject: function(obj) { checkGlobal(obj); return obj; },
+ set objectAttr(val) { this._objectAttr = val; },
+ get dictionaryAttr() { return this._dictionaryAttr; },
+ set dictionaryAttr(val) { this._dictionaryAttr = val; },
+ pingPongAny: function(any) { return any; },
+ pingPongObject: function(obj) { return obj; },
+ pingPongObjectOrString: function(objectOrString) { return objectOrString; },
+ pingPongDictionary: function(dict) { return dict; },
+ pingPongDictionaryOrLong: function(dictOrLong) { return dictOrLong.anyMember || dictOrLong; },
+ pingPongMap: function(map) { return JSON.stringify(map); },
+ objectSequenceLength: function(seq) { return seq.length; },
+ anySequenceLength: function(seq) { return seq.length; },
+
getCallerPrincipal: function() { return Cu.getWebIDLCallerPrincipal().origin; },
convertSVS: function(svs) { return svs; },
pingPongUnion: function(x) { return x; },
pingPongUnionContainingNull: function(x) { return x; },
pingPongNullableUnion: function(x) { return x; },
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -12,20 +12,18 @@ support-files =
[test_bug560072.html]
[test_bug707564.html]
[test_bug742191.html]
[test_bug759621.html]
[test_bug773326.html]
[test_bug788369.html]
[test_bug852846.html]
[test_bug862092.html]
-# When bug 923904 lands, this test can be turned on, but only for debug builds
-# where we have our test component. So this should become skip-if = debug == false.
-[test_bug923904.html]
-skip-if = true
+[test_bug1036214.html]
+skip-if = debug == false
[test_bug1041646.html]
[test_barewordGetsWindow.html]
[test_callback_default_thisval.html]
[test_cloneAndImportNode.html]
[test_defineProperty.html]
[test_enums.html]
[test_exceptionThrowing.html]
[test_exception_messages.html]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_bug1036214.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1036214
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1036214</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for subsumes-checking |any| and |object| for js-implemented WebIDL. **/
+ SimpleTest.waitForExplicitFinish();
+ var xoObjects = [];
+ function setup() {
+ xoObjects.push(window[0]);
+ xoObjects.push(window[0].location);
+ xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap(window[0]).document));
+ xoObjects.push(SpecialPowers);
+ xoObjects.push(SpecialPowers.wrap);
+ SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, go);
+ }
+
+ function checkThrows(f, msg) {
+ try {
+ f();
+ ok(false, "Should have thrown: " + msg);
+ } catch (e) {
+ ok(true, "Threw correctly: " + msg);
+ ok(/denied|insecure/.test(e), "Threw security exception: " + e);
+ }
+ }
+
+ function go() {
+
+ //
+ // Test the basics of the test interface.
+ //
+
+ var any = { a: 11 };
+ var obj = { b: 22, c: "str" };
+ var obj2 = { foo: "baz" };
+ var myDict = { anyMember: 42, objectMember: { answer: 42 }, objectOrStringMember: { answer: "anobject" },
+ anySequenceMember: [{}, 1, "thirdinsequence"],
+ innerDictionary: { innerObject: { answer: "rabbithole" } } };
+ var t = new TestInterfaceJS(any, obj, myDict);
+ is(Object.getPrototypeOf(t), TestInterfaceJS.prototype, "Prototype setup works correctly");
+ is(t.anyArg, any, "anyArg is correct");
+ is(t.objectArg, obj, "objectArg is correct");
+ is(t.dictionaryArg.anyMember, 42, "dictionaryArg looks correct");
+ is(t.dictionaryArg.objectMember.answer, 42, "dictionaryArg looks correct");
+ t.anyAttr = 2;
+ is(t.anyAttr, 2, "ping-pong any attribute works");
+ t.objAttr = obj2;
+ is(t.objAttr, obj2, "ping-pong object attribute works");
+ t.dictionaryAttr = myDict;
+ is(t.dictionaryAttr.anyMember, 42, "ping-pong dictionary attribute works");
+ is(t.dictionaryAttr.objectMember.answer, 42, "ping-pong dictionary attribute works");
+
+ is(any, t.pingPongAny(any), "ping-pong works with any");
+ is(obj, t.pingPongObject(obj), "ping-pong works with obj");
+ is(obj, t.pingPongObjectOrString(obj), "ping-pong works with obj or string");
+ is("foo", t.pingPongObjectOrString("foo"), "ping-pong works with obj or string");
+ is(t.pingPongDictionary(myDict).anyMember, 42, "ping pong works with dict");
+ is(t.pingPongDictionary(myDict).objectMember.answer, 42, "ping pong works with dict");
+ is(t.pingPongDictionary(myDict).objectOrStringMember.answer, "anobject", "ping pong works with dict");
+ is(t.pingPongDictionary(myDict).anySequenceMember[2], "thirdinsequence", "ping pong works with dict");
+ is(t.pingPongDictionary(myDict).innerDictionary.innerObject.answer, "rabbithole", "ping pong works with layered dicts");
+ is(t.pingPongDictionaryOrLong({anyMember: 42}), 42, "ping pong (dict or long) works with dict");
+ is(t.pingPongDictionaryOrLong(42), 42, "ping pong (dict or long) works with long");
+ ok(/canary/.test(t.pingPongMap({ someVal: 42, someOtherVal: "canary" })), "ping pong works with mozmap");
+ is(t.objectSequenceLength([{}, {}, {}]), 3, "ping pong works with object sequence");
+ is(t.anySequenceLength([42, 'string', {}, undefined]), 4, "ping pong works with any sequence");
+
+ //
+ // Test that we throw in the cross-origin cases.
+ //
+
+ xoObjects.forEach(function(xoObj) {
+ var blank = new TestInterfaceJS();
+ checkThrows(() => new TestInterfaceJS(xoObj, undefined), "any param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, xoObj), "obj param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, undefined, { anyMember: xoObj }), "any dict param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectMember: xoObj }), "object dict param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectOrStringMember: xoObj }), "union dict param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, undefined, { anySequenceMember: [0, xoObj, 'hi' ] }), "sequence dict param for constructor");
+ checkThrows(() => new TestInterfaceJS(undefined, undefined, { innerDictionary: { innerObject: xoObj } }), "inner dict param for constructor");
+ checkThrows(() => t.anyAttr = xoObj, "anyAttr");
+ checkThrows(() => t.objectAttr = xoObj, "objAttr");
+ checkThrows(() => t.dictionaryAttr = { anyMember: xoObj }, "dictionaryAttr any");
+ checkThrows(() => t.dictionaryAttr = { objectMember: xoObj }, "dictionaryAttr object");
+ checkThrows(() => t.pingPongAny(xoObj), "pingpong any");
+ checkThrows(() => t.pingPongObject(xoObj), "pingpong obj");
+ checkThrows(() => t.pingPongObjectOrString(xoObj), "pingpong union");
+ checkThrows(() => t.pingPongDictionary({ anyMember: xoObj }), "dictionary pingpong any");
+ checkThrows(() => t.pingPongDictionary({ objectMember: xoObj }), "dictionary pingpong object");
+ checkThrows(() => t.pingPongDictionary({ anyMember: xoObj, objectMember: xoObj }), "dictionary pingpong both");
+ checkThrows(() => t.pingPongDictionary({ objectOrStringMember: xoObj }), "dictionary pingpong objectorstring");
+ checkThrows(() => t.pingPongDictionaryOrLong({ objectMember: xoObj }), "unionable dictionary");
+ checkThrows(() => t.pingPongDictionaryOrLong({ anyMember: xoObj }), "unionable dictionary");
+ checkThrows(() => t.pingPongMap({ someMember: 42, someOtherMember: {}, crossOriginMember: xoObj }), "mozmap");
+ checkThrows(() => t.objectSequenceLength([{}, {}, xoObj, {}]), "object sequence");
+ checkThrows(() => t.anySequenceLength([42, 'someString', xoObj, {}]), "any sequence");
+ });
+
+
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1036214">Mozilla Bug 1036214</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+<iframe id="ifr" onload="setup();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe>
+</body>
+</html>
deleted file mode 100644
--- a/dom/bindings/test/test_bug923904.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=923904
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 923904</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- /** Test for cloning of |any| and |object| for JS-Implemented WebIDL. **/
- SimpleTest.waitForExplicitFinish();
- SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, go);
-
- function go() {
- var someAny = { a: 11 };
- var someObj = { b: 22, c: "str" };
- var t = new TestInterfaceJS(someAny, someObj);
- is(Object.getPrototypeOf(t), TestInterfaceJS.prototype, "Prototype setup works correctly");
- is(t.anyArg.toSource(), someAny.toSource(), "anyArg comes back looking like what we sent");
- is(t.objectArg.toSource(), someObj.toSource(), "objectArg comes back looking like what we sent");
- isnot(t.anyArg, t.anyArg, "get a new anyArg each time");
- isnot(t.objectArg, t.objectArg, "get a new objectArg each time");
-
- t.anyAttr = 2;
- is(t.anyAttr, 2, "ping-pong works");
- testObjectCloned(t, 'anyAttr');
- testObjectCloned(t, 'objectAttr');
-
- is(someAny.toSource(), t.pingPongAny(someAny).toSource(), "ping-pong works with any");
- is(someObj.toSource(), t.pingPongObject(someObj).toSource(), "ping-pong works with obj");
- isnot(someAny, t.pingPongAny(someAny), "Clone works for ping-pong any");
- isnot(someObj, t.pingPongObject(someObj), "Clone works for ping-pong obj");
-
- SimpleTest.finish();
- }
-
- function testObjectCloned(iface, propname) {
- var obj = { prop: 42 };
- iface[propname] = obj;
- is(iface[propname].prop, 42, "objects come back as well");
- is(iface[propname].__proto__, Object.prototype, "vanilla object");
- isnot(iface[propname], obj, "Should not be the original object");
- isnot(iface[propname], iface[propname], "Should get cloned each time");
- try {
- iface[propname] = { stringProp: "hi", reflectorProp: document };
- ok(false, "Should throw when trying to clone reflector");
- } catch (e) {
- ok(/cloned/.test(e), "Should throw clone error: " + e);
- }
- }
-
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=923904">Mozilla Bug 923904</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1980,17 +1980,17 @@ CanvasRenderingContext2D::ArcTo(double x
bool anticlockwise;
if (p0 == p1 || p1 == p2 || radius == 0) {
LineTo(p1.x, p1.y);
return;
}
// Check for colinearity
- dir = (p2.x - p1.x) * (p0.y - p1.y) + (p2.y - p1.y) * (p1.x - p0.x);
+ dir = (p2.x - p1.x).value * (p0.y - p1.y).value + (p2.y - p1.y).value * (p1.x - p0.x).value;
if (dir == 0) {
LineTo(p1.x, p1.y);
return;
}
// XXX - Math for this code was already available from the non-azure code
// and would be well tested. Perhaps converting to bezier directly might
@@ -4495,17 +4495,17 @@ CanvasPath::ArcTo(double x1, double y1,
bool anticlockwise;
if (p0 == p1 || p1 == p2 || radius == 0) {
LineTo(p1.x, p1.y);
return;
}
// Check for colinearity
- dir = (p2.x - p1.x) * (p0.y - p1.y) + (p2.y - p1.y) * (p1.x - p0.x);
+ dir = (p2.x - p1.x).value * (p0.y - p1.y).value + (p2.y - p1.y).value * (p1.x - p0.x).value;
if (dir == 0) {
LineTo(p1.x, p1.y);
return;
}
// XXX - Math for this code was already available from the non-azure code
// and would be well tested. Perhaps converting to bezier directly might
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -785,17 +785,17 @@ protected:
*/
bool NeedToDrawShadow()
{
const ContextState& state = CurrentState();
// The spec says we should not draw shadows if the operator is OVER.
// If it's over and the alpha value is zero, nothing needs to be drawn.
return NS_GET_A(state.shadowColor) != 0 &&
- (state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
+ (state.shadowBlur != 0.f || state.shadowOffset.x != 0.f || state.shadowOffset.y != 0.f);
}
mozilla::gfx::CompositionOp UsedOperation()
{
if (NeedToDrawShadow()) {
// In this case the shadow rendering will use the operator.
return mozilla::gfx::CompositionOp::OP_OVER;
}
--- a/dom/cellbroadcast/src/CellBroadcast.cpp
+++ b/dom/cellbroadcast/src/CellBroadcast.cpp
@@ -83,16 +83,18 @@ CellBroadcast::CellBroadcast(nsPIDOMWind
CellBroadcast::~CellBroadcast()
{
MOZ_ASSERT(mProvider && mListener);
mListener->Disconnect();
mProvider->UnregisterCellBroadcastMsg(mListener);
}
+NS_IMPL_ISUPPORTS_INHERITED0(CellBroadcast, DOMEventTargetHelper)
+
JSObject*
CellBroadcast::WrapObject(JSContext* aCx)
{
return MozCellBroadcastBinding::Wrap(aCx, this);
}
// Forwarded nsICellBroadcastListener methods
--- a/dom/cellbroadcast/src/CellBroadcast.h
+++ b/dom/cellbroadcast/src/CellBroadcast.h
@@ -12,40 +12,43 @@
#include "nsICellBroadcastProvider.h"
#include "js/TypeDecls.h"
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
-class CellBroadcast MOZ_FINAL : public DOMEventTargetHelper
+class CellBroadcast MOZ_FINAL : public DOMEventTargetHelper,
+ private nsICellBroadcastListener
{
/**
- * Class CellBroadcast doesn't actually inherit nsICellBroadcastListener.
+ * Class CellBroadcast doesn't actually expose nsICellBroadcastListener.
* Instead, it owns an nsICellBroadcastListener derived instance mListener
* and passes it to nsICellBroadcastProvider. The onreceived events are first
* delivered to mListener and then forwarded to its owner, CellBroadcast. See
* also bug 775997 comment #51.
*/
class Listener;
+ // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+ ~CellBroadcast();
+
public:
+ NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICELLBROADCASTLISTENER
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
static already_AddRefed<CellBroadcast>
Create(nsPIDOMWindow* aOwner, ErrorResult& aRv);
CellBroadcast() MOZ_DELETE;
CellBroadcast(nsPIDOMWindow *aWindow,
nsICellBroadcastProvider* aProvider);
- // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
- ~CellBroadcast();
nsPIDOMWindow*
GetParentObject() const { return GetOwner(); }
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
IMPL_EVENT_HANDLER(received)
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1590,18 +1590,19 @@ EventStateManager::GenerateDragGesture(n
pixelThresholdX = 5;
if (!pixelThresholdY)
pixelThresholdY = 5;
}
// fire drag gesture if mouse has moved enough
LayoutDeviceIntPoint pt = aEvent->refPoint +
LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
- if (DeprecatedAbs(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
- DeprecatedAbs(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
+ LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
+ if (Abs(distance.x.value) > SafeCast<uint32_t>(pixelThresholdX) ||
+ Abs(distance.y.value) > SafeCast<uint32_t>(pixelThresholdY)) {
if (Prefs::ClickHoldContextMenu()) {
// stop the click-hold before we fire off the drag gesture, in case
// it takes a long time
KillClickHoldTimer();
}
nsCOMPtr<nsISupports> container = aPresContext->GetContainerWeak();
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
+++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
@@ -3,28 +3,28 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
interface nsIDocument;
interface nsIURI;
-[uuid(cc539f1e-1ce6-4af5-bf94-195b30bde010)]
+[uuid(9b5acea4-2601-4ac7-8836-4352ceb88178)]
interface nsIServiceWorkerManager : nsISupports
{
// Returns a Promise
nsISupports register(in nsIDOMWindow aWindow, in DOMString aScope, in DOMString aScriptURI);
// Returns a Promise
nsISupports unregister(in nsIDOMWindow aWindow, in DOMString aScope);
- // aTarget MUST be a ServiceWorkerContainer.
- [noscript] void AddContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
- [noscript] void RemoveContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
+ // aTarget MUST be a ServiceWorkerRegistration.
+ [noscript] void AddRegistrationEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
+ [noscript] void RemoveRegistrationEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
/**
* Call this to request that document `aDoc` be controlled by a ServiceWorker
* if a registration exists for it's scope.
*
* This MUST only be called once per document!
*/
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc);
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -2097,22 +2097,22 @@ MediaManager::MediaCaptureWindowStateInt
// We need to return the union of all streams in all innerwindows that
// correspond to that outerwindow.
// Iterate the docshell tree to find all the child windows, find
// all the listeners for each one, get the booleans, and merge the
// results.
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (piWin) {
- if (piWin->GetCurrentInnerWindow() || piWin->IsInnerWindow()) {
+ if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) {
uint64_t windowID;
- if (piWin->GetCurrentInnerWindow()) {
+ if (piWin->IsInnerWindow()) {
+ windowID = piWin->WindowID();
+ } else {
windowID = piWin->GetCurrentInnerWindow()->WindowID();
- } else {
- windowID = piWin->WindowID();
}
StreamListeners* listeners = GetActiveWindows()->Get(windowID);
if (listeners) {
uint32_t length = listeners->Length();
for (uint32_t i = 0; i < length; ++i) {
nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
listeners->ElementAt(i);
if (listener->CapturingVideo()) {
--- a/dom/mobileconnection/src/MobileConnection.cpp
+++ b/dom/mobileconnection/src/MobileConnection.cpp
@@ -86,16 +86,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MobileConnection,
DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVoice)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MobileConnection)
+ // MobileConnection does not expose nsIMobileConnectionListener. mListener is
+ // the exposed nsIMobileConnectionListener and forwards the calls it receives
+ // to us.
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(MobileConnection, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MobileConnection, DOMEventTargetHelper)
MobileConnection::MobileConnection(nsPIDOMWindow* aWindow, uint32_t aClientId)
: DOMEventTargetHelper(aWindow)
, mClientId(aClientId)
--- a/dom/mobileconnection/src/MobileConnection.h
+++ b/dom/mobileconnection/src/MobileConnection.h
@@ -12,20 +12,21 @@
#include "mozilla/dom/MozMobileConnectionBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIMobileConnectionProvider.h"
#include "nsWeakPtr.h"
namespace mozilla {
namespace dom {
-class MobileConnection MOZ_FINAL : public DOMEventTargetHelper
+class MobileConnection MOZ_FINAL : public DOMEventTargetHelper,
+ private nsIMobileConnectionListener
{
/**
- * Class MobileConnection doesn't actually inherit
+ * Class MobileConnection doesn't actually expose
* nsIMobileConnectionListener. Instead, it owns an
* nsIMobileConnectionListener derived instance mListener and passes it to
* nsIMobileConnectionProvider. The onreceived events are first delivered to
* mListener and then forwarded to its owner, MobileConnection. See also bug
* 775997 comment #51.
*/
class Listener;
--- a/dom/smil/test/smilTestUtils.js
+++ b/dom/smil/test/smilTestUtils.js
@@ -50,39 +50,43 @@ var SMILUtil =
if (attr.attrType == "XML") {
// XXXdholbert This is appropriate for mapped attributes, but not
// for other attributes.
return SMILUtil.getComputedStyleWrapper(elem, attr.attrName);
}
},
// Smart wrapper for getComputedStyle, which will generate a "fake" computed
- // style for recognized shorthand properties (font, overflow, marker)
+ // style for recognized shorthand properties (font, font-variant, overflow, marker)
getComputedStyleWrapper : function(elem, propName)
{
// Special cases for shorthand properties (which aren't directly queriable
// via getComputedStyle)
var computedStyle;
if (propName == "font") {
- var subProps = ["font-style", "font-variant", "font-weight",
+ var subProps = ["font-style", "font-variant-caps", "font-weight",
"font-size", "line-height", "font-family"];
for (var i in subProps) {
var subPropStyle = SMILUtil.getComputedStyleSimple(elem, subProps[i]);
if (subPropStyle) {
if (subProps[i] == "line-height") {
// There needs to be a "/" before line-height
subPropStyle = "/ " + subPropStyle;
}
if (!computedStyle) {
computedStyle = subPropStyle;
} else {
computedStyle = computedStyle + " " + subPropStyle;
}
}
}
+ } else if (propName == "font-variant") {
+ // xxx - this isn't completely correct but it's sufficient for what's
+ // being tested here
+ computedStyle = SMILUtil.getComputedStyleSimple(elem, "font-variant-caps");
} else if (propName == "marker") {
var subProps = ["marker-end", "marker-mid", "marker-start"];
for (var i in subProps) {
if (!computedStyle) {
computedStyle = SMILUtil.getComputedStyleSimple(elem, subProps[i]);
} else {
is(computedStyle, SMILUtil.getComputedStyleSimple(elem, subProps[i]),
"marker sub-properties should match each other " +
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -11,30 +11,27 @@
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <android/log.h>
-#include <cutils/properties.h>
#include "AutoMounter.h"
#include "nsVolumeService.h"
#include "AutoMounterSetting.h"
#include "base/message_loop.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Hal.h"
#include "mozilla/StaticPtr.h"
#include "MozMtpServer.h"
-#include "MozMtpStorage.h"
#include "nsAutoPtr.h"
-#include "nsCharSeparatedTokenizer.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "OpenFileFinder.h"
#include "Volume.h"
#include "VolumeManager.h"
@@ -88,23 +85,16 @@ USING_MTP_NAMESPACE
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "AutoMounter" , ## args)
#else
#define DBG(args...)
#endif
namespace mozilla {
namespace system {
-#define SYS_USB_CONFIG "sys.usb.config"
-#define PERSIST_SYS_USB_CONFIG "persist.sys.usb.config"
-
-#define USB_FUNC_ADB "adb"
-#define USB_FUNC_MTP "mtp"
-#define USB_FUNC_UMS "mass_storage"
-
class AutoMounter;
static void SetAutoMounterStatus(int32_t aStatus);
/***************************************************************************/
inline const char* SwitchStateStr(const SwitchEvent& aEvent)
{
@@ -120,68 +110,46 @@ IsUsbCablePluggedIn()
// Use this code when bug 745078 gets fixed (or use whatever the
// appropriate method is)
return GetCurrentSwitchEvent(SWITCH_USB) == SWITCH_STATE_ON;
#else
// Until then, just go read the file directly
if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
char usbState[20];
if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbCablePluggedIn: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0 ||
- strcmp(usbState, "CONNECTED") == 0;
+ return strcmp(usbState, "CONFIGURED") == 0;
}
ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
return false;
}
bool configured;
if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
return configured;
}
ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
return false;
#endif
}
-static bool
-IsUsbConfigured()
-{
- if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
- char usbState[20];
- if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbConfigured: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0;
- }
- ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
- return false;
- }
- bool configured;
- if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
- return configured;
- }
- ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
- return false;
-}
-
/***************************************************************************/
// The AutoVolumeManagerStateObserver allows the AutoMounter to know when
// the volume manager changes state (i.e. it has finished initialization)
class AutoVolumeManagerStateObserver : public VolumeManager::StateObserver
{
public:
virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
};
// The AutoVolumeEventObserver allows the AutoMounter to know about card
// insertion and removal, as well as state changes in the volume.
class AutoVolumeEventObserver : public Volume::EventObserver
{
public:
- virtual void Notify(Volume* const& aEvent);
+ virtual void Notify(Volume * const & aEvent);
};
class AutoMounterResponseCallback : public VolumeResponseCallback
{
public:
AutoMounterResponseCallback()
: mErrorCount(0)
{
@@ -201,18 +169,17 @@ private:
class AutoMounter
{
public:
NS_INLINE_DECL_REFCOUNTING(AutoMounter)
typedef nsTArray<RefPtr<Volume>> VolumeArray;
AutoMounter()
- : mState(STATE_IDLE),
- mResponseCallback(new AutoMounterResponseCallback),
+ : mResponseCallback(new AutoMounterResponseCallback),
mMode(AUTOMOUNTER_DISABLE)
{
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
Volume::RegisterObserver(&mVolumeEventObserver);
// It's possible that the VolumeManager is already in the READY state,
// so we call CheckVolumeSettings here to cover that case. Otherwise,
// we'll pick it up when the VolumeManage state changes to VOLUMES_READY.
@@ -260,55 +227,42 @@ public:
// Note: eventually CheckVolumeSettings will call
// AutoMounter::SetSharingMode, which will in turn call
// UpdateState if needed.
}
}
}
- void UpdateState();
-
- void ConfigureUsbFunction(const char* aUsbFunc);
-
void StartMtpServer();
void StopMtpServer();
- void StartUmsSharing();
- void StopUmsSharing();
-
+ void UpdateState();
const char* ModeStr(int32_t aMode)
{
switch (aMode) {
case AUTOMOUNTER_DISABLE: return "Disable";
- case AUTOMOUNTER_ENABLE_UMS: return "Enable-UMS";
+ case AUTOMOUNTER_ENABLE: return "Enable";
case AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED: return "DisableWhenUnplugged";
- case AUTOMOUNTER_ENABLE_MTP: return "Enable-MTP";
}
return "??? Unknown ???";
}
- bool IsModeEnabled(int32_t aMode)
- {
- return aMode == AUTOMOUNTER_ENABLE_MTP ||
- aMode == AUTOMOUNTER_ENABLE_UMS;
- }
-
void SetMode(int32_t aMode)
{
if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
(mMode == AUTOMOUNTER_DISABLE)) {
// If it's already disabled, then leave it as disabled.
// AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED implies "enabled until unplugged"
aMode = AUTOMOUNTER_DISABLE;
}
- if (aMode == AUTOMOUNTER_DISABLE &&
- mMode == AUTOMOUNTER_ENABLE_UMS && IsUsbCablePluggedIn()) {
+ if ((aMode == AUTOMOUNTER_DISABLE) &&
+ (mMode == AUTOMOUNTER_ENABLE) && IsUsbCablePluggedIn()) {
// On many devices (esp non-Samsung), we can't force the disable, so we
// need to defer until the USB cable is actually unplugged.
// See bug 777043.
//
// Otherwise our attempt to disable it will fail, and we'll wind up in a bad
// state where the AutoMounter thinks that Sharing has been turned off, but
// the files are actually still being Shared because the attempt to unshare
// failed.
@@ -387,74 +341,20 @@ public:
vol->SetUnmountRequested(true);
DBG("Calling UpdateState due to volume %s unmounting set to %d",
vol->NameStr(), (int)vol->IsUnmountRequested());
UpdateState();
}
private:
- enum STATE
- {
- // IDLE - Nothing is being shared
- STATE_IDLE,
-
- // We've detected that conditions are right to enable mtp. So we've
- // set sys.usb.config to include mtp, and we're waiting for the USB
- // subsystem to be "configured". Once mtp shows up in
- // then we know
- // that its been configured and we can open /dev/mtp_usb
- STATE_MTP_CONFIGURING,
-
- // mtp has been configured (i.e. mtp now shows up in
- // /sys/devices/virtual/android_usb/android0/functions so we can start
- // the mtp server.
- STATE_MTP_STARTED,
-
- // The mtp server has reported sessionStarted. We'll leave this state
- // when we receive sessionEnded.
- STATE_MTP_CONNECTED,
-
- // We've added mass_storage (aka UMS) to sys.usb.config and we're waiting for
- // mass_storage to appear in /sys/devices/virtual/android_usb/android0/functions
- STATE_UMS_CONFIGURING,
-
- // mass_storage has been configured and we can start sharing once the user
- // enables it.
- STATE_UMS_CONFIGURED,
- };
-
- const char *StateStr(STATE aState)
- {
- switch (aState) {
- case STATE_IDLE: return "IDLE";
- case STATE_MTP_CONFIGURING: return "MTP_CONFIGURING";
- case STATE_MTP_CONNECTED: return "MTP_CONNECTED";
- case STATE_MTP_STARTED: return "MTP_STARTED";
- case STATE_UMS_CONFIGURING: return "UMS_CONFIGURING";
- case STATE_UMS_CONFIGURED: return "UMS_CONFIGURED";
- }
- return "STATE_???";
- }
-
- void SetState(STATE aState)
- {
- const char *oldStateStr = StateStr(mState);
- mState = aState;
- const char *newStateStr = StateStr(mState);
- LOG("AutoMounter state changed from %s to %s", oldStateStr, newStateStr);
- }
-
- STATE mState;
-
AutoVolumeEventObserver mVolumeEventObserver;
AutoVolumeManagerStateObserver mVolumeManagerStateObserver;
RefPtr<VolumeResponseCallback> mResponseCallback;
int32_t mMode;
- MozMtpStorage::Array mMozMtpStorage;
};
static StaticRefPtr<AutoMounter> sAutoMounter;
static StaticRefPtr<MozMtpServer> sMozMtpServer;
/***************************************************************************/
void
@@ -500,114 +400,32 @@ AutoMounterResponseCallback::ResponseRec
aCommand->CmdStr(), ResponseCode(), ResponseStr().get());
if (++mErrorCount < kMaxErrorCount) {
DBG("Calling UpdateState due to VolumeResponseCallback::OnError");
sAutoMounter->UpdateState();
}
}
-static bool
-IsUsbFunctionEnabled(const char* aConfig, const char* aUsbFunc)
-{
- nsAutoCString config(aConfig);
- nsCCharSeparatedTokenizer tokenizer(config, ',');
-
- while (tokenizer.hasMoreTokens()) {
- nsAutoCString token(tokenizer.nextToken());
- if (token.Equals(aUsbFunc)) {
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning true", aConfig, aUsbFunc);
- return true;
- }
- }
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning false", aConfig, aUsbFunc);
- return false;
-}
-
-static void
-SetUsbFunction(const char* aUsbFunc)
-{
- char oldSysUsbConfig[PROPERTY_VALUE_MAX];
- property_get(SYS_USB_CONFIG, oldSysUsbConfig, "");
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, aUsbFunc)) {
- // The function is already configured. Nothing else to do.
- DBG("SetUsbFunction('%s') - already set - nothing to do", aUsbFunc);
- return;
- }
-
- char newSysUsbConfig[PROPERTY_VALUE_MAX];
-
- if (strcmp(aUsbFunc, USB_FUNC_MTP) == 0) {
- // We're enabling MTP. For this we'll wind up using mtp, or mtp,adb
- strlcpy(newSysUsbConfig, USB_FUNC_MTP, sizeof(newSysUsbConfig));
- } else if (strcmp(aUsbFunc, USB_FUNC_UMS) == 0) {
- // We're enabling UMS. For this we make the assumption that the persisted
- // property has mass_storage enabled.
- property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
- } else {
- printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc);
- MOZ_ASSERT(0);
- return;
- }
-
- // Make sure the new value that we write into sys.usb.config keeps the adb
- // (or non-adb) of the current string.
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, USB_FUNC_ADB)) {
- // ADB was turned on - keep it on.
- if (!IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Add adb to the new string
- strlcat(newSysUsbConfig, ",", sizeof(newSysUsbConfig));
- strlcat(newSysUsbConfig, USB_FUNC_ADB, sizeof(newSysUsbConfig));
- }
- } else {
- // ADB was turned off - keep it off
- if (IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Remove ADB from the new string.
- if (strcmp(newSysUsbConfig, USB_FUNC_ADB) == 0) {
- newSysUsbConfig[0] = '\0';
- } else {
- nsAutoCString withoutAdb(newSysUsbConfig);
- withoutAdb.ReplaceSubstring( "," USB_FUNC_ADB, "");
- strlcpy(newSysUsbConfig, withoutAdb.get(), sizeof(newSysUsbConfig));
- }
- }
- }
-
- LOG("SetUsbFunction(%s) %s to '%s'", aUsbFunc, SYS_USB_CONFIG, newSysUsbConfig);
- property_set(SYS_USB_CONFIG, newSysUsbConfig);
-}
-
void
AutoMounter::StartMtpServer()
{
if (sMozMtpServer) {
// Mtp Server is already running - nothing to do
return;
}
LOG("Starting MtpServer");
sMozMtpServer = new MozMtpServer();
sMozMtpServer->Run();
-
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- nsRefPtr<MozMtpStorage> storage = new MozMtpStorage(vol, sMozMtpServer);
- mMozMtpStorage.AppendElement(storage);
- }
}
void
AutoMounter::StopMtpServer()
{
LOG("Stopping MtpServer");
-
- mMozMtpStorage.Clear();
sMozMtpServer = nullptr;
}
/***************************************************************************/
void
AutoMounter::UpdateState()
{
@@ -642,196 +460,76 @@ AutoMounter::UpdateState()
}
if (mResponseCallback->IsPending()) {
// We only deal with one outstanding volume command at a time,
// so we need to wait for it to finish.
return;
}
- // Calling setprop sys.usb.config mtp,adb (or adding mass_storage) will
- // cause /sys/devices/virtual/android_usb/android0/state to go:
- // CONFIGURED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- //
- // Since IsUsbCablePluggedIn returns state == CONFIGURED, it will look
- // like a cable pull and replugin.
-
- bool umsAvail = false;
- bool umsConfigured = false;
- bool umsEnabled = false;
- bool mtpAvail = false;
- bool mtpConfigured = false;
- bool mtpEnabled = false;
- bool usbCablePluggedIn = IsUsbCablePluggedIn();
+ bool umsAvail = false;
+ bool umsEnabled = false;
+ bool mtpAvail = false;
+ bool mtpEnabled = false;
if (access(ICS_SYS_USB_FUNCTIONS, F_OK) == 0) {
char functionsStr[60];
if (!ReadSysFile(ICS_SYS_USB_FUNCTIONS, functionsStr, sizeof(functionsStr))) {
ERR("Error reading file '%s': %s", ICS_SYS_USB_FUNCTIONS, strerror(errno));
functionsStr[0] = '\0';
}
- DBG("UpdateState: USB functions: '%s'", functionsStr);
-
- bool usbConfigured = IsUsbConfigured();
umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
if (umsAvail) {
- umsConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_UMS) != nullptr;
- umsEnabled = (mMode == AUTOMOUNTER_ENABLE_UMS) ||
- (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && umsConfigured;
- } else {
- umsConfigured = false;
- umsEnabled = false;
+ umsEnabled = strstr(functionsStr, "mass_storage") != nullptr;
}
-
mtpAvail = (access(ICS_SYS_MTP_DIRECTORY, F_OK) == 0);
if (mtpAvail) {
- mtpConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_MTP) != nullptr;
- mtpEnabled = (mMode == AUTOMOUNTER_ENABLE_MTP) ||
- (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && mtpConfigured;
- } else {
- mtpConfigured = false;
- mtpEnabled = false;
- }
- }
-
- bool enabled = mtpEnabled || umsEnabled;
-
- if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
- // DISABLE_WHEN_UNPLUGGED implies already enabled.
- enabled = usbCablePluggedIn;
- if (!usbCablePluggedIn) {
- mMode = AUTOMOUNTER_DISABLE;
- mtpEnabled = false;
- umsEnabled = false;
+ mtpEnabled = strstr(functionsStr, "mtp") != nullptr;
}
}
- DBG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d mState:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled,
- mMode, usbCablePluggedIn, StateStr(mState));
-
- switch (mState) {
-
- case STATE_IDLE:
- if (!usbCablePluggedIn) {
- // Stay in the IDLE state. We'll get a CONNECTED or CONFIGURED
- // UEvent when the usb cable is plugged in.
- break;
- }
- if (mtpEnabled) {
- if (mtpConfigured) {
- // The USB layer has already been configured. Now we can go ahead
- // and start the MTP server. This particular codepath will not
- // normally be taken, but it could happen if you stop and restart
- // b2g while sys.usb.config is set to enable mtp.
- StartMtpServer();
- SetState(STATE_MTP_STARTED);
- } else {
- // The MTP USB layer is configuring. Wait for it to finish
- // before we start the MTP server.
- SetUsbFunction(USB_FUNC_MTP);
- SetState(STATE_MTP_CONFIGURING);
- }
- } else if (umsConfigured) {
- // UMS is already configured.
- SetState(STATE_UMS_CONFIGURED);
- } else if (umsAvail) {
- // We do this whether or not UMS is enabled. With UMS, it's the
- // sharing of the volume which is significant. What is important
- // is that we don't leave it in MTP mode when MTP isn't enabled.
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- }
- break;
+ bool usbCablePluggedIn = IsUsbCablePluggedIn();
+ bool enabled = (mMode == AUTOMOUNTER_ENABLE);
- case STATE_MTP_CONFIGURING:
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here.
- if (mtpEnabled && mtpConfigured) {
- // The USB layer has been configured. Now we can go ahead and start
- // the MTP server.
- StartMtpServer();
- SetState(STATE_MTP_STARTED);
- }
- break;
-
- case STATE_MTP_STARTED:
- if (usbCablePluggedIn) {
- if (mtpConfigured && mtpEnabled) {
- // Everything is still good. Leave the MTP server running
- break;
- }
- DBG("STATE_MTP_STARTED: About to StopMtpServer "
- "mtpConfigured = %d mtpEnabled = %d usbCablePluggedIn: %d",
- mtpConfigured, mtpEnabled, usbCablePluggedIn);
- StopMtpServer();
- if (umsAvail) {
- // Switch back to UMS
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- break;
- }
- }
- SetState(STATE_IDLE);
- break;
-
- case STATE_UMS_CONFIGURING:
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here.
- if (umsConfigured) {
- SetState(STATE_UMS_CONFIGURED);
- }
- break;
-
- case STATE_UMS_CONFIGURED:
- if (usbCablePluggedIn) {
- if (mtpEnabled) {
- // MTP was enabled. Start reconfiguring.
- SetState(STATE_MTP_CONFIGURING);
- SetUsbFunction(USB_FUNC_MTP);
- break;
- }
- if (umsConfigured && umsEnabled) {
- // This is the normal state when UMS is enabled.
- break;
- }
- }
- SetState(STATE_IDLE);
- break;
-
- default:
- SetState(STATE_IDLE);
- break;
+ if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
+ enabled = usbCablePluggedIn;
+ if (!usbCablePluggedIn) {
+ mMode = AUTOMOUNTER_DISABLE;
+ }
}
- bool tryToShare = umsEnabled && usbCablePluggedIn;
- LOG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d tryToShare:%d state:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled,
- mMode, usbCablePluggedIn, tryToShare, StateStr(mState));
+ bool tryToShare = (((umsAvail && umsEnabled) || (mtpAvail && mtpEnabled))
+ && enabled && usbCablePluggedIn);
+ LOG("UpdateState: ums:%d%d mtp:%d%d mode:%d usbCablePluggedIn:%d tryToShare:%d",
+ umsAvail, umsEnabled, mtpAvail, mtpEnabled, mMode, usbCablePluggedIn, tryToShare);
+
+ if (mtpAvail && mtpEnabled) {
+ if (enabled && usbCablePluggedIn) {
+ StartMtpServer();
+ } else {
+ StopMtpServer();
+ }
+ return;
+ }
bool filesOpen = false;
static unsigned filesOpenDelayCount = 0;
VolumeArray::index_type volIndex;
VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
Volume::STATE volState = vol->State();
if (vol->State() == nsIVolume::STATE_MOUNTED) {
LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d sharing %s",
vol->NameStr(), vol->StateStr(),
vol->MediaPresent() ? "inserted" : "missing",
vol->MountPoint().get(), vol->MountGeneration(),
(int)vol->IsMountLocked(),
- vol->CanBeShared() ? (vol->IsSharingEnabled() ?
- (vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
+ vol->CanBeShared() ? (vol->IsSharingEnabled() ? (vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
if (vol->IsSharing() && !usbCablePluggedIn) {
// We call SetIsSharing(true) below to indicate intent to share. This
// causes a state change which notifys apps, and they'll close any
// open files, which will initiate the change away from the mounted
// state and into the sharing state. Normally, when the volume
// transitions back to the mounted state, then vol->mIsSharing gets set
// to false. However, if the user pulls the USB cable before we
// actually start sharing, then the volume never actually leaves
@@ -1237,17 +935,16 @@ AutoMounterUnmountVolume(const nsCString
NewRunnableFunction(AutoMounterUnmountVolumeIOThread,
aVolumeName));
}
void
ShutdownAutoMounter()
{
if (sAutoMounter) {
- DBG("ShutdownAutoMounter: About to StopMtpServer");
sAutoMounter->StopMtpServer();
}
sAutoMounterSetting = nullptr;
sUsbCableObserver = nullptr;
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownAutoMounterIOThread));
--- a/dom/system/gonk/AutoMounter.h
+++ b/dom/system/gonk/AutoMounter.h
@@ -9,19 +9,18 @@
class nsCString;
namespace mozilla {
namespace system {
// AutoMounter modes
#define AUTOMOUNTER_DISABLE 0
-#define AUTOMOUNTER_ENABLE_UMS 1
+#define AUTOMOUNTER_ENABLE 1
#define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED 2
-#define AUTOMOUNTER_ENABLE_MTP 3
// Automounter statuses
#define AUTOMOUNTER_STATUS_DISABLED 0
#define AUTOMOUNTER_STATUS_ENABLED 1
#define AUTOMOUNTER_STATUS_FILES_OPEN 2
/**
* Initialize the automounter. This causes some of the phone's
--- a/dom/system/gonk/MozMtpDatabase.cpp
+++ b/dom/system/gonk/MozMtpDatabase.cpp
@@ -35,42 +35,44 @@ ObjectPropertyAsStr(MtpObjectProperty aP
case MTP_PROPERTY_WIDTH: return "MTP_PROPERTY_WIDTH";
case MTP_PROPERTY_HEIGHT: return "MTP_PROPERTY_HEIGHT";
case MTP_PROPERTY_IMAGE_BIT_DEPTH: return "MTP_PROPERTY_IMAGE_BIT_DEPTH";
case MTP_PROPERTY_DISPLAY_NAME: return "MTP_PROPERTY_DISPLAY_NAME";
}
return "MTP_PROPERTY_???";
}
-MozMtpDatabase::MozMtpDatabase()
+MozMtpDatabase::MozMtpDatabase(const char *aDir)
{
- MTP_LOG("constructed");
+ MTP_LOG("");
// We use the index into the array as the handle. Since zero isn't a valid
// index, we stick a dummy entry there.
RefPtr<DbEntry> dummy;
mDb.AppendElement(dummy);
+
+ ReadVolume("sdcard", aDir);
}
//virtual
MozMtpDatabase::~MozMtpDatabase()
{
- MTP_LOG("destructed");
+ MTP_LOG("");
}
void
MozMtpDatabase::AddEntry(DbEntry *entry)
{
entry->mHandle = GetNextHandle();
MOZ_ASSERT(mDb.Length() == entry->mHandle);
mDb.AppendElement(entry);
- MTP_LOG("Handle: 0x%08x Parent: 0x%08x Path:'%s'",
+ MTP_LOG("AddEntry: Handle: 0x%08x Parent: 0x%08x Path:'%s'",
entry->mHandle, entry->mParent, entry->mPath.get());
}
TemporaryRef<MozMtpDatabase::DbEntry>
MozMtpDatabase::GetEntry(MtpObjectHandle aHandle)
{
RefPtr<DbEntry> entry;
@@ -113,108 +115,87 @@ GetPathWithoutFileName(const nsCString&
}
MTP_LOG("returning '%s'", path.get());
return path;
}
void
-MozMtpDatabase::AddDirectory(MtpStorageID aStorageID,
- const char* aPath,
- MtpObjectHandle aParent)
+MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
{
ScopedCloseDir dir;
- if (!(dir = PR_OpenDir(aPath))) {
- MTP_ERR("Unable to open directory '%s'", aPath);
+ if (!(dir = PR_OpenDir(aDir))) {
+ MTP_ERR("Unable to open directory '%s'", aDir);
return;
}
PRDirEntry* dirEntry;
while ((dirEntry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
- nsPrintfCString filename("%s/%s", aPath, dirEntry->name);
+ nsPrintfCString filename("%s/%s", aDir, dirEntry->name);
PRFileInfo64 fileInfo;
if (PR_GetFileInfo64(filename.get(), &fileInfo) != PR_SUCCESS) {
MTP_ERR("Unable to retrieve file information for '%s'", filename.get());
continue;
}
RefPtr<DbEntry> entry = new DbEntry;
- entry->mStorageID = aStorageID;
+ entry->mStorageID = MTP_STORAGE_FIXED_RAM;
entry->mParent = aParent;
entry->mObjectName = dirEntry->name;
entry->mDisplayName = dirEntry->name;
entry->mPath = filename;
entry->mDateCreated = fileInfo.creationTime;
entry->mDateModified = fileInfo.modifyTime;
if (fileInfo.type == PR_FILE_FILE) {
entry->mObjectFormat = MTP_FORMAT_DEFINED;
//TODO: Check how 64-bit filesize are dealt with
entry->mObjectSize = fileInfo.size;
AddEntry(entry);
} else if (fileInfo.type == PR_FILE_DIRECTORY) {
entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
entry->mObjectSize = 0;
AddEntry(entry);
- AddDirectory(aStorageID, filename.get(), entry->mHandle);
+ ParseDirectory(filename.get(), entry->mHandle);
}
}
}
void
-MozMtpDatabase::AddStorage(MtpStorageID aStorageID,
- const char* aPath,
- const char* aName)
+MozMtpDatabase::ReadVolume(const char *volumeName, const char *aDir)
{
//TODO: Add an assert re thread being run on
PRFileInfo fileInfo;
- if (PR_GetFileInfo(aPath, &fileInfo) != PR_SUCCESS) {
- MTP_ERR("'%s' doesn't exist", aPath);
+ if (PR_GetFileInfo(aDir, &fileInfo) != PR_SUCCESS) {
+ MTP_ERR("'%s' doesn't exist", aDir);
return;
}
if (fileInfo.type != PR_FILE_DIRECTORY) {
- MTP_ERR("'%s' isn't a directory", aPath);
+ MTP_ERR("'%s' isn't a directory", aDir);
return;
}
-#if 0
RefPtr<DbEntry> entry = new DbEntry;
- entry->mStorageID = aStorageID;
+ entry->mStorageID = MTP_STORAGE_FIXED_RAM;
entry->mParent = MTP_PARENT_ROOT;
- entry->mObjectName = aName;
- entry->mDisplayName = aName;
- entry->mPath = aPath;
+ entry->mObjectName = volumeName;
+ entry->mDisplayName = volumeName;
+ entry->mPath = aDir;
entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
entry->mObjectSize = 0;
AddEntry(entry);
- AddDirectory(aStorageID, aPath, entry->mHandle);
-#else
- AddDirectory(aStorageID, aPath, MTP_PARENT_ROOT);
-#endif
-}
-
-void
-MozMtpDatabase::RemoveStorage(MtpStorageID aStorageID)
-{
- DbArray::size_type numEntries = mDb.Length();
- DbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mStorageID == aStorageID) {
- mDb[entryIndex] = nullptr;
- }
- }
+ ParseDirectory(aDir, entry->mHandle);
}
// called from SendObjectInfo to reserve a database entry for the incoming file
//virtual
MtpObjectHandle
MozMtpDatabase::beginSendObject(const char* aPath,
MtpObjectFormat aFormat,
MtpObjectHandle aParent,
@@ -246,75 +227,61 @@ MozMtpDatabase::beginSendObject(const ch
// called to report success or failure of the SendObject file transfer
// success should signal a notification of the new object's creation,
// failure should remove the database entry created in beginSendObject
//virtual
void
MozMtpDatabase::endSendObject(const char* aPath,
- MtpObjectHandle aHandle,
- MtpObjectFormat aFormat,
- bool aSucceeded)
+ MtpObjectHandle aHandle,
+ MtpObjectFormat aFormat,
+ bool succeeded)
{
MTP_LOG("Handle: 0x%08x Path: '%s'", aHandle, aPath);
- if (!aSucceeded) {
+ if (!succeeded) {
RemoveEntry(aHandle);
}
}
//virtual
MtpObjectHandleList*
MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
+ MtpObjectFormat aFormat,
+ MtpObjectHandle aParent)
{
MTP_LOG("StorageID: 0x%08x Format: 0x%04x Parent: 0x%08x",
aStorageID, aFormat, aParent);
//TODO: Optimize
ScopedDeletePtr<MtpObjectHandleList> list;
list = new MtpObjectHandleList();
- // Note: objects in the topmost directory of each storage area have a parent
- // of MTP_PARENT_ROOT. So we need to filter on storage ID as well.
-
DbArray::size_type numEntries = mDb.Length();
DbArray::index_type entryIndex;
for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mStorageID == aStorageID && entry->mParent == aParent) {
+ if (entry && entry->mParent == aParent) {
list->push(entry->mHandle);
}
}
return list.forget();
}
//virtual
int
MozMtpDatabase::getNumObjects(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
+ MtpObjectFormat aFormat,
+ MtpObjectHandle aParent)
{
MTP_LOG("");
- int count = 0;
-
- DbArray::size_type numEntries = mDb.Length();
- DbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mStorageID == aStorageID) {
- count++;
- }
- }
-
- return count;
+ return mDb.Length() - 1;
}
//virtual
MtpObjectFormatList*
MozMtpDatabase::getSupportedPlaybackFormats()
{
static const uint16_t init_data[] = {MTP_FORMAT_UNDEFINED, MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
@@ -372,18 +339,18 @@ MozMtpDatabase::getSupportedDeviceProper
MtpDevicePropertyList *list = new MtpDevicePropertyList();
list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
return list;
}
//virtual
MtpResponseCode
MozMtpDatabase::getObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
+ MtpObjectProperty aProperty,
+ MtpDataPacket& aPacket)
{
RefPtr<DbEntry> entry = GetEntry(aHandle);
if (!entry) {
MTP_ERR("Invalid Handle: 0x%08x", aHandle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MTP_LOG("Handle: 0x%08x '%s' Property: %s 0x%08x",
@@ -445,18 +412,18 @@ GetTypeOfObjectProp(MtpObjectProperty aP
}
return type;
}
//virtual
MtpResponseCode
MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
+ MtpObjectProperty aProperty,
+ MtpDataPacket& aPacket)
{
MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
// Only support file name change
if (aProperty != MTP_PROPERTY_OBJECT_FILE_NAME) {
MTP_ERR("property 0x%x not supported", aProperty);
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
}
@@ -491,26 +458,26 @@ MozMtpDatabase::setObjectPropertyValue(M
entry->mDisplayName = entry->mObjectName;
return MTP_RESPONSE_OK;
}
//virtual
MtpResponseCode
MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
+ MtpDataPacket& aPacket)
{
MTP_LOG("(GENERAL ERROR)");
return MTP_RESPONSE_GENERAL_ERROR;
}
//virtual
MtpResponseCode
MozMtpDatabase::setDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
+ MtpDataPacket& aPacket)
{
MTP_LOG("(NOT SUPPORTED)");
return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
}
//virtual
MtpResponseCode
MozMtpDatabase::resetDeviceProperty(MtpDeviceProperty aProperty)
@@ -595,23 +562,23 @@ MozMtpDatabase::QueryEntries(MozMtpDatab
default:
MOZ_ASSERT(!"Invalid MatchType");
}
}
//virtual
MtpResponseCode
MozMtpDatabase::getObjectPropertyList(MtpObjectHandle aHandle,
- uint32_t aFormat,
- uint32_t aProperty,
- int aGroupCode,
- int aDepth,
- MtpDataPacket& aPacket)
+ uint32_t aFormat,
+ uint32_t aProperty,
+ int aGroupCode,
+ int aDepth,
+ MtpDataPacket& aPacket)
{
- MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d",
+ MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d (NOT SUPPORTED)",
aHandle, aFormat, aProperty, aGroupCode, aDepth);
if (aDepth > 1) {
return MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED;
}
if (aGroupCode != 0) {
return MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED;
}
@@ -754,17 +721,17 @@ MozMtpDatabase::getObjectPropertyList(Mt
}
}
return MTP_RESPONSE_OK;
}
//virtual
MtpResponseCode
MozMtpDatabase::getObjectInfo(MtpObjectHandle aHandle,
- MtpObjectInfo& aInfo)
+ MtpObjectInfo& aInfo)
{
RefPtr<DbEntry> entry = GetEntry(aHandle);
if (!entry) {
MTP_ERR("Handle 0x%08x is invalid", aHandle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MTP_LOG("Handle: 0x%08x Display:'%s' Object:'%s'", aHandle, entry->mDisplayName.get(), entry->mObjectName.get());
@@ -808,19 +775,19 @@ MozMtpDatabase::getThumbnail(MtpObjectHa
aOutThumbSize = 0;
return nullptr;
}
//virtual
MtpResponseCode
MozMtpDatabase::getObjectFilePath(MtpObjectHandle aHandle,
- MtpString& aOutFilePath,
- int64_t& aOutFileLength,
- MtpObjectFormat& aOutFormat)
+ MtpString& aOutFilePath,
+ int64_t& aOutFileLength,
+ MtpObjectFormat& aOutFormat)
{
RefPtr<DbEntry> entry = GetEntry(aHandle);
if (!entry) {
MTP_ERR("Handle 0x%08x is invalid", aHandle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MTP_LOG("Handle: 0x%08x FilePath: '%s'", aHandle, entry->mPath.get());
@@ -839,20 +806,16 @@ MozMtpDatabase::deleteFile(MtpObjectHand
RefPtr<DbEntry> entry = GetEntry(aHandle);
if (!entry) {
MTP_ERR("Invalid Handle: 0x%08x", aHandle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MTP_LOG("Handle: 0x%08x '%s'", aHandle, entry->mPath.get());
- //TODO: MtpServer::doDeleteObject calls us, and then calls a private
- // method (deletePath) which recursively deletes the path.
- // We need to tell device storage that these files are gone
-
// File deletion will happen in lower level implementation.
// The only thing we need to do is removing the entry from the db.
RemoveEntry(aHandle);
return MTP_RESPONSE_OK;
}
#if 0
@@ -886,17 +849,17 @@ MozMtpDatabase::getObjectReferences(MtpO
{
MTP_LOG("Handle: 0x%08x (returning nullptr)", aHandle);
return nullptr;
}
//virtual
MtpResponseCode
MozMtpDatabase::setObjectReferences(MtpObjectHandle aHandle,
- MtpObjectHandleList* aReferences)
+ MtpObjectHandleList* aReferences)
{
MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
}
//virtual
MtpProperty*
MozMtpDatabase::getObjectPropertyDesc(MtpObjectProperty aProperty,
--- a/dom/system/gonk/MozMtpDatabase.h
+++ b/dom/system/gonk/MozMtpDatabase.h
@@ -17,19 +17,17 @@
BEGIN_MTP_NAMESPACE // mozilla::system::mtp
using namespace android;
class MozMtpDatabase : public MtpDatabase
{
public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpDatabase)
-
- MozMtpDatabase();
+ MozMtpDatabase(const char *aDir);
virtual ~MozMtpDatabase();
// called from SendObjectInfo to reserve a database entry for the incoming file
virtual MtpObjectHandle beginSendObject(const char* aPath,
MtpObjectFormat aFormat,
MtpObjectHandle aParent,
MtpStorageID aStorageID,
uint64_t aSize,
@@ -103,24 +101,21 @@ public:
MtpObjectFormat aFormat);
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty aProperty);
virtual void sessionStarted();
virtual void sessionEnded();
- void AddStorage(MtpStorageID aStorageID, const char* aPath, const char *aName);
- void RemoveStorage(MtpStorageID aStorageID);
-
private:
struct DbEntry
{
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DbEntry)
+ NS_INLINE_DECL_REFCOUNTING(DbEntry)
MtpObjectHandle mHandle; // uint32_t
MtpStorageID mStorageID; // uint32_t
nsCString mObjectName;
MtpObjectFormat mObjectFormat; // uint16_t
MtpObjectHandle mParent; // uint32_t
uint64_t mObjectSize;
nsCString mDisplayName;
@@ -152,14 +147,15 @@ private:
nsCString BaseName(const nsCString& aPath);
MtpObjectHandle GetNextHandle()
{
return mDb.Length();
}
- void AddDirectory(MtpStorageID aStorageID, const char *aPath, MtpObjectHandle aParent);
+ void ParseDirectory(const char *aDir, MtpObjectHandle aParent);
+ void ReadVolume(const char *aVolumeName, const char *aDir);
};
END_MTP_NAMESPACE
#endif // mozilla_system_mozmtpdatabase_h__
--- a/dom/system/gonk/MozMtpServer.cpp
+++ b/dom/system/gonk/MozMtpServer.cpp
@@ -11,93 +11,70 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-#include "base/message_loop.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Scoped.h"
-#include "mozilla/StaticPtr.h"
-#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#include "Volume.h"
using namespace android;
using namespace mozilla;
-BEGIN_MTP_NAMESPACE
+USING_MTP_NAMESPACE
class MtpServerRunnable : public nsRunnable
{
public:
- MtpServerRunnable(int aMtpUsbFd, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mMtpUsbFd(aMtpUsbFd)
- {
- }
-
nsresult Run()
{
- nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
+ const char *mtpUsbFilename = "/dev/mtp_usb";
+ const char *productName = "FirefoxOS";
+ const char *storageDir = "/storage/sdcard";
+
+ mFd = open(mtpUsbFilename, O_RDWR);
+ if (mFd.get() < 0) {
+ MTP_LOG("open of '%s' failed", mtpUsbFilename);
+ return NS_OK;
+ }
+
+ MTP_LOG("MozMtpServer open done, fd: %d. Start reading.", mFd.get());
+
+ ScopedDeletePtr<MozMtpDatabase> database;
+ ScopedDeletePtr<MtpServer> server;
+ ScopedDeletePtr<MtpStorage> storage;
+
+ database = new MozMtpDatabase(storageDir);
+ server = new MtpServer(mFd.get(), database, false, 1023, 0664, 0775);
+ storage = new MtpStorage(MTP_STORAGE_FIXED_RAM, // id
+ storageDir, // filePath
+ productName, // description
+ 100uLL * 1024uLL * 1024uLL, // reserveSpace
+ false, // removable
+ 2uLL * 1024uLL * 1024uLL * 1024uLL); // maxFileSize
+
+ server->addStorage(storage);
MTP_LOG("MozMtpServer started");
server->run();
MTP_LOG("MozMtpServer finished");
return NS_OK;
}
private:
- nsRefPtr<MozMtpServer> mMozMtpServer;
- ScopedClose mMtpUsbFd; // We want to hold this open while the server runs
+ ScopedClose mFd;
};
-already_AddRefed<RefCountedMtpServer>
-MozMtpServer::GetMtpServer()
-{
- nsRefPtr<RefCountedMtpServer> server = mMtpServer;
- return server.forget();
-}
-
-already_AddRefed<MozMtpDatabase>
-MozMtpServer::GetMozMtpDatabase()
-{
- nsRefPtr<MozMtpDatabase> db = mMozMtpDatabase;
- return db.forget();
-}
-
void
MozMtpServer::Run()
{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- const char *mtpUsbFilename = "/dev/mtp_usb";
- ScopedClose mtpUsbFd(open(mtpUsbFilename, O_RDWR));
- if (mtpUsbFd.get() < 0) {
- MTP_ERR("open of '%s' failed", mtpUsbFilename);
- return;
- }
- MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mtpUsbFd.get());
-
- mMozMtpDatabase = new MozMtpDatabase();
- mMtpServer = new RefCountedMtpServer(mtpUsbFd.get(), // fd
- mMozMtpDatabase.get(), // MtpDatabase
- false, // ptp?
- AID_MEDIA_RW, // file group
- 0664, // file permissions
- 0775); // dir permissions
-
nsresult rv = NS_NewNamedThread("MtpServer", getter_AddRefs(mServerThread));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
MOZ_ASSERT(mServerThread);
- mServerThread->Dispatch(new MtpServerRunnable(mtpUsbFd.forget(), this), NS_DISPATCH_NORMAL);
+ mServerThread->Dispatch(new MtpServerRunnable(), 0);
}
-
-END_MTP_NAMESPACE
--- a/dom/system/gonk/MozMtpServer.h
+++ b/dom/system/gonk/MozMtpServer.h
@@ -3,58 +3,30 @@
/* 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 mozilla_system_mozmtpserver_h__
#define mozilla_system_mozmtpserver_h__
#include "MozMtpCommon.h"
-#include "MozMtpDatabase.h"
-#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIThread.h"
-namespace mozilla {
-namespace system {
- class Volume;
-}
-}
-
BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class RefCountedMtpServer : public MtpServer
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMtpServer)
-
- RefCountedMtpServer(int aFd, MtpDatabase* aDatabase, bool aPtp,
- int aFileGroup, int aFilePerm, int aDirectoryPerm)
- : MtpServer(aFd, aDatabase, aPtp, aFileGroup, aFilePerm, aDirectoryPerm)
- {
- }
-};
class MozMtpServer
{
public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpServer)
+ NS_INLINE_DECL_REFCOUNTING(MozMtpServer)
void Run();
-// void UpdateStorage(android::MtpStorageID id, Volume *vol);
-
- already_AddRefed<RefCountedMtpServer> GetMtpServer();
- already_AddRefed<MozMtpDatabase> GetMozMtpDatabase();
-
private:
- nsRefPtr<RefCountedMtpServer> mMtpServer;
- nsRefPtr<MozMtpDatabase> mMozMtpDatabase;
nsCOMPtr<nsIThread> mServerThread;
};
END_MTP_NAMESPACE
#endif // mozilla_system_mozmtpserver_h__
deleted file mode 100644
--- a/dom/system/gonk/MozMtpStorage.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "MozMtpStorage.h"
-#include "MozMtpDatabase.h"
-#include "MozMtpServer.h"
-
-#include "base/message_loop.h"
-#include "nsXULAppAPI.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-MozMtpStorage::MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mVolume(aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // The MtpStorageID has the physical volume in the top 16 bits, and the
- // logical volumein the lower 16 bits. We treat each volume as a separate
- // phsyical storage;
- mStorageID = mVolume->Id() << 16 | 1;
-
- MTP_LOG("Storage constructed for Volume %s mStorageID 0x%08x",
- aVolume->NameStr(), mStorageID);
-
- Volume::RegisterObserver(this);
-
- // Get things in sync
- Notify(mVolume);
-}
-
-MozMtpStorage::~MozMtpStorage()
-{
- MTP_LOG("Storage destructed for Volume %s mStorageID 0x%08x",
- mVolume->NameStr(), mStorageID);
-
- Volume::UnregisterObserver(this);
- if (mMtpStorage) {
- StorageUnavailable();
- }
-}
-
-// virtual
-void
-MozMtpStorage::Notify(Volume* const& aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (aVolume != mVolume) {
- // Not our volume
- return;
- }
- Volume::STATE volState = aVolume->State();
-
- MTP_LOG("Volume %s mStorageID 0x%08x state changed to %s SharingEnabled: %d",
- aVolume->NameStr(), mStorageID, aVolume->StateStr(),
- aVolume->IsSharingEnabled());
-
- if (mMtpStorage) {
- if (volState != nsIVolume::STATE_MOUNTED || !aVolume->IsSharingEnabled()) {
- // The volume is no longer accessible. We need to remove this storage
- // from the MTP server
- StorageUnavailable();
- }
- } else {
- if (volState == nsIVolume::STATE_MOUNTED && aVolume->IsSharingEnabled()) {
- // The volume is accessible. Tell the MTP server.
- StorageAvailable();
- }
- }
-}
-
-void
-MozMtpStorage::StorageAvailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- nsCString mountPoint = mVolume->MountPoint();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MozMtpDatabase",
- mVolume->NameStr(), mStorageID, mountPoint.get());
-
- nsRefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->AddStorage(mStorageID, mountPoint.get(), mVolume->NameStr());
-
- MOZ_ASSERT(!mMtpStorage);
-
- //TODO: For now we assume that the storage removable unless we're sure it's
- // not. Bug 1033952 will add an isRemovable attribute to the Volume
- // and then we'll know properly.
-
- //TODO: Figure out what to do about maxFileSize.
-
- mMtpStorage.reset(new MtpStorage(mStorageID, // id
- mountPoint.get(), // filePath
- mVolume->NameStr(), // description
- 1024uLL * 1024uLL, // reserveSpace
- true, // removable
- 2uLL * 1024uLL * 1024uLL * 1024uLL)); // maxFileSize
- nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MtpServer",
- mVolume->NameStr(), mStorageID, mountPoint.get());
- server->addStorage(mMtpStorage.get());
-}
-
-void
-MozMtpStorage::StorageUnavailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(mMtpStorage);
-
- MTP_LOG("Removing mStorageID 0x%08x from MtpServer", mStorageID);
-
- nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
- server->removeStorage(mMtpStorage.get());
-
- MTP_LOG("Removing mStorageID 0x%08x from MozMtpDatabse", mStorageID);
-
- nsRefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->RemoveStorage(mStorageID);
-
- mMtpStorage = nullptr;
-}
-
-END_MTP_NAMESPACE
-
-
deleted file mode 100644
--- a/dom/system/gonk/MozMtpStorage.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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 mozilla_system_mozmtpstorage_h__
-#define mozilla_system_mozmtpstorage_h__
-
-#include "MozMtpCommon.h"
-
-#include "nsAutoPtr.h"
-#include "mozilla/UniquePtr.h"
-
-#include "Volume.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class MozMtpServer;
-
-class MozMtpStorage : public Volume::EventObserver
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpStorage)
-
- MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer);
-
- typedef nsTArray<nsRefPtr<MozMtpStorage> > Array;
-
-private:
- virtual ~MozMtpStorage();
- virtual void Notify(Volume* const& aEvent);
-
- void StorageAvailable();
- void StorageUnavailable();
-
- nsRefPtr<MozMtpServer> mMozMtpServer;
- UniquePtr<MtpStorage> mMtpStorage;
- RefPtr<Volume> mVolume;
- MtpStorageID mStorageID;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpstorage_h__
-
-
--- a/dom/system/gonk/Volume.cpp
+++ b/dom/system/gonk/Volume.cpp
@@ -45,34 +45,31 @@ Volume::EventObserverList Volume::mEvent
//
// If the Volume (IOThread) recieves a volume update where the generation
// number mismatches, then the update is simply ignored.
//
// When a Volume (IOThread) initially becomes mounted, we assume it to
// be locked until we get our first update from nsVolume (MainThread).
static int32_t sMountGeneration = 0;
-static uint32_t sNextId = 1;
-
// We don't get media inserted/removed events at startup. So we
// assume it's present, and we'll be told that it's missing.
Volume::Volume(const nsCSubstring& aName)
: mMediaPresent(true),
mState(nsIVolume::STATE_INIT),
mName(aName),
mMountGeneration(-1),
mMountLocked(true), // Needs to agree with nsVolume::nsVolume
mSharingEnabled(false),
mFormatRequested(false),
mMountRequested(false),
mUnmountRequested(false),
mCanBeShared(true),
mIsSharing(false),
- mIsFormatting(false),
- mId(sNextId++)
+ mIsFormatting(false)
{
DBG("Volume %s: created", NameStr());
}
void
Volume::SetIsSharing(bool aIsSharing)
{
if (aIsSharing == mIsSharing) {
@@ -138,17 +135,16 @@ Volume::SetMediaPresent(bool aMediaPrese
void
Volume::SetSharingEnabled(bool aSharingEnabled)
{
mSharingEnabled = aSharingEnabled;
LOG("SetSharingMode for volume %s to %d canBeShared = %d",
NameStr(), (int)mSharingEnabled, (int)mCanBeShared);
- mEventObserverList.Broadcast(this);
}
void
Volume::SetFormatRequested(bool aFormatRequested)
{
mFormatRequested = aFormatRequested;
LOG("SetFormatRequested for volume %s to %d CanBeFormatted = %d",
@@ -178,24 +174,24 @@ Volume::SetState(Volume::STATE aNewState
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (aNewState == mState) {
return;
}
if (aNewState == nsIVolume::STATE_MOUNTED) {
mMountGeneration = ++sMountGeneration;
- LOG("Volume %s (%u): changing state from %s to %s @ '%s' (%d observers) "
+ LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers) "
"mountGeneration = %d, locked = %d",
- NameStr(), mId, StateStr(mState),
+ NameStr(), StateStr(mState),
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length(),
mMountGeneration, (int)mMountLocked);
} else {
- LOG("Volume %s (%u): changing state from %s to %s (%d observers)",
- NameStr(), mId, StateStr(mState),
+ LOG("Volume %s: changing state from %s to %s (%d observers)",
+ NameStr(), StateStr(mState),
StateStr(aNewState), mEventObserverList.Length());
}
switch (aNewState) {
case nsIVolume::STATE_NOMEDIA:
// Cover the startup case where we don't get insertion/removal events
mMediaPresent = false;
mIsSharing = false;
--- a/dom/system/gonk/Volume.h
+++ b/dom/system/gonk/Volume.h
@@ -39,18 +39,16 @@ public:
const nsCString& Name() const { return mName; }
const char* NameStr() const { return mName.get(); }
// The mount point is the name of the directory where the volume is mounted.
// (i.e. path that leads to the files stored on the volume).
const nsCString& MountPoint() const { return mMountPoint; }
- uint32_t Id() const { return mId; }
-
int32_t MountGeneration() const { return mMountGeneration; }
bool IsMountLocked() const { return mMountLocked; }
bool MediaPresent() const { return mMediaPresent; }
bool CanBeShared() const { return mCanBeShared; }
bool CanBeFormatted() const { return CanBeShared(); }
bool CanBeMounted() const { return CanBeShared(); }
bool IsSharingEnabled() const { return mCanBeShared && mSharingEnabled; }
bool IsFormatRequested() const { return CanBeFormatted() && mFormatRequested; }
@@ -107,17 +105,16 @@ private:
bool mMountLocked;
bool mSharingEnabled;
bool mFormatRequested;
bool mMountRequested;
bool mUnmountRequested;
bool mCanBeShared;
bool mIsSharing;
bool mIsFormatting;
- uint32_t mId; // Unique ID (used by MTP)
static EventObserverList mEventObserverList;
};
} // system
} // mozilla
#endif // mozilla_system_volumemanager_h__
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -38,17 +38,16 @@ EXPORTS += [
SOURCES += [
'AudioChannelManager.cpp',
'AudioManager.cpp',
'AutoMounter.cpp',
'AutoMounterSetting.cpp',
'GonkGPSGeolocationProvider.cpp',
'MozMtpDatabase.cpp',
'MozMtpServer.cpp',
- 'MozMtpStorage.cpp',
'NetworkUtils.cpp',
'NetworkWorker.cpp',
'nsVolume.cpp',
'nsVolumeMountLock.cpp',
'nsVolumeService.cpp',
'nsVolumeStat.cpp',
'OpenFileFinder.cpp',
'SystemWorkerManager.cpp',
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -591,16 +591,17 @@ this.READ_RECORD_ABSOLUTE_MODE = 4;
// GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9,
// 'Response data in case of an EF.'
this.GET_RESPONSE_EF_SIZE_BYTES = 15;
// EF path
this.EF_PATH_MF_SIM = "3f00";
this.EF_PATH_DF_PHONEBOOK = "5f3a";
+this.EF_PATH_GRAPHICS = "5f50";
this.EF_PATH_DF_TELECOM = "7f10";
this.EF_PATH_DF_GSM = "7f20";
this.EF_PATH_DF_CDMA = "7f25";
this.EF_PATH_ADF_USIM = "7fff";
// Status code of sw1 for ICC I/O,
// see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
this.ICC_STATUS_NORMAL_ENDING = 0x90;
@@ -667,16 +668,29 @@ this.ICC_USIM_EFANR_TAG = 0xc4;
this.ICC_USIM_EFPBC_TAG = 0xc5;
this.ICC_USIM_EFGRP_TAG = 0xc6;
this.ICC_USIM_EFAAS_TAG = 0xc7;
this.ICC_USIM_EFGSD_TAG = 0xc8;
this.ICC_USIM_EFUID_TAG = 0xc9;
this.ICC_USIM_EFEMAIL_TAG = 0xca;
this.ICC_USIM_EFCCP1_TAG = 0xcb;
+// ICC image coding scheme
+// TS 31.102, sub-clause 4.6.1.1
+this.ICC_IMG_CODING_SCHEME_BASIC = 0x11;
+this.ICC_IMG_CODING_SCHEME_COLOR = 0x21;
+this.ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY = 0x22;
+
+// ICC image header size per coding scheme
+// TS 31.102, Annex B
+this.ICC_IMG_HEADER_SIZE_BASIC = 2;
+this.ICC_IMG_HEADER_SIZE_COLOR = 6;
+
+this.ICC_CLUT_ENTRY_SIZE = 3;
+
this.USIM_PBR_ANR = "anr";
this.USIM_PBR_ANR0 = "anr0";
this.USIM_PBR_EMAIL = "email";
// Current supported fields. Adding more fields to read will increasing I/O
// time dramatically, do check the performance is acceptable when you add
// more fields.
this.USIM_PBR_FIELDS = [USIM_PBR_EMAIL, USIM_PBR_ANR0];
@@ -1241,31 +1255,33 @@ this.GECKO_ICC_SERVICES = {
CBMI: 14,
GID1: 15,
SPN: 17,
SDN: 18,
DATA_DOWNLOAD_SMS_CB: 25,
DATA_DOWNLOAD_SMS_PP: 26,
CBMIR: 30,
BDN: 31,
+ IMG: 39,
PNN: 51,
OPL: 52,
MDN: 53,
MWIS: 54,
SPDI: 56
},
usim: {
FDN: 2,
SDN: 4,
BDN: 6,
CBMI: 15,
CBMIR: 16,
GID1: 17,
SPN: 19,
MSISDN: 21,
+ IMG: 22,
DATA_DOWNLOAD_SMS_PP: 28,
DATA_DOWNLOAD_SMS_CB: 29,
PNN: 45,
OPL: 46,
MDN: 47,
MWIS: 48,
SPDI: 51
},
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -5429,17 +5429,20 @@ RilObject.prototype = {
command: cmdDetails,
resultCode: STK_RESULT_OK});
return;
}
cmdDetails.rilMessageType = "stkcommand";
cmdDetails.options =
this.context.StkCommandParamsFactory.createParam(cmdDetails, ctlvs);
- this.sendChromeMessage(cmdDetails);
+
+ if (!cmdDetails.options || !cmdDetails.options.pending) {
+ this.sendChromeMessage(cmdDetails);
+ }
},
/**
* Send messages to the main thread.
*/
sendChromeMessage: function(message) {
message.rilMessageClientId = this.context.clientId;
postMessage(message);
@@ -10820,16 +10823,57 @@ StkCommandParamsFactoryObject.prototype
menu.isHelpAvailable = true;
}
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_NEXT_ACTION_IND, ctlvs);
if (ctlv) {
menu.nextActionList = ctlv.value;
}
+ let iconId;
+ let ids = [];
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (ctlv) {
+ iconId = ctlv.value;
+ menu.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+ ids[0] = iconId.identifier;
+ }
+
+ let iconIdList;
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID_LIST, ctlvs);
+ if (ctlv) {
+ iconIdList = ctlv.value;
+ menu.itemIconSelfExplanatory = iconIdList.qualifier == 0 ? true : false;
+ ids = ids.concat(iconIdList.identifiers);
+ }
+
+ if (!ids.length ||
+ !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return menu;
+ }
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ if (iconId) {
+ menu.icons = result.shift();
+ }
+
+ for (let i = 0; i < result.length; i++) {
+ menu.items[i].icons = result[i];
+ }
+
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ menu.pending = true;
+ this.context.IconLoader.loadIcons(ids, onsuccess, onerror);
+
return menu;
},
processDisplayText: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let textMsg = {};
let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
@@ -10856,32 +10900,73 @@ StkCommandParamsFactoryObject.prototype
textMsg.isHighPriority = true;
}
// User clear.
if (cmdDetails.commandQualifier & 0x80) {
textMsg.userClear = true;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return textMsg;
+ }
+
+ let iconId = ctlv.value;
+ textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ textMsg.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ textMsg.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return textMsg;
},
processSetUpIdleModeText: function(cmdDetails, ctlvs) {
+ let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let textMsg = {};
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
+ let ctlv = StkProactiveCmdHelper.searchForTag(
+ COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
if (!ctlv) {
this.context.RIL.sendStkTerminalResponse({
command: cmdDetails,
resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
throw new Error("Stk Set Up Idle Text: Required value missing : Text String");
}
textMsg.text = ctlv.value.textString;
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return textMsg;
+ }
+
+ let iconId = ctlv.value;
+ textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ textMsg.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ textMsg.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return textMsg;
},
processGetInkey: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let input = {};
let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
@@ -10919,16 +11004,36 @@ StkCommandParamsFactoryObject.prototype
input.isYesNoRequested = true;
}
// Help information available.
if (cmdDetails.commandQualifier & 0x80) {
input.isHelpAvailable = true;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return input;
+ }
+
+ let iconId = ctlv.value;
+ input.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ input.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ input.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return input;
},
processGetInput: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let input = {};
let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
@@ -10971,28 +11076,70 @@ StkCommandParamsFactoryObject.prototype
input.isPacked = true;
}
// Help information available.
if (cmdDetails.commandQualifier & 0x80) {
input.isHelpAvailable = true;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return input;
+ }
+
+ let iconId = ctlv.value;
+ input.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ input.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ input.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return input;
},
processEventNotify: function(cmdDetails, ctlvs) {
+ let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let textMsg = {};
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
+ let ctlv = StkProactiveCmdHelper.searchForTag(
+ COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
if (ctlv) {
textMsg.text = ctlv.value.identifier;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(
+ COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return textMsg;
+ }
+
+ let iconId = ctlv.value;
+ textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ textMsg.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ textMsg.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return textMsg;
},
processSetupCall: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let call = {};
let iter = Iterator(ctlvs);
@@ -11016,16 +11163,36 @@ StkCommandParamsFactoryObject.prototype
call.address = ctlv.value.number;
// see 3GPP TS 31.111 section 6.4.13
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_DURATION, ctlvs);
if (ctlv) {
call.duration = ctlv.value;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return call;
+ }
+
+ let iconId = ctlv.value;
+ call.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ call.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ call.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return call;
},
processLaunchBrowser: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let browser = {};
let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_URL, ctlvs);
@@ -11039,25 +11206,45 @@ StkCommandParamsFactoryObject.prototype
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
if (ctlv) {
browser.confirmMessage = ctlv.value.identifier;
}
browser.mode = cmdDetails.commandQualifier & 0x03;
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return browser;
+ }
+
+ let iconId = ctlv.value;
+ browser.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ browser.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ browser.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return browser;
},
processPlayTone: function(cmdDetails, ctlvs) {
let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let playTone = {};
let ctlv = StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
+ COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
if (ctlv) {
playTone.text = ctlv.value.identifier;
}
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TONE, ctlvs);
if (ctlv) {
playTone.tone = ctlv.value.tone;
}
@@ -11066,16 +11253,37 @@ StkCommandParamsFactoryObject.prototype
COMPREHENSIONTLV_TAG_DURATION, ctlvs);
if (ctlv) {
playTone.duration = ctlv.value;
}
// vibrate is only defined in TS 102.223
playTone.isVibrate = (cmdDetails.commandQualifier & 0x01) !== 0x00;
+ ctlv = StkProactiveCmdHelper.searchForTag(
+ COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return playTone;
+ }
+
+ let iconId = ctlv.value;
+ playTone.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ playTone.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ playTone.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return playTone;
},
/**
* Construct a param for Provide Local Information
*
* @param cmdDetails
* The value object of CommandDetails TLV.
@@ -11114,24 +11322,45 @@ StkCommandParamsFactoryObject.prototype
* Construct a param for BIP commands.
*
* @param cmdDetails
* The value object of CommandDetails TLV.
* @param ctlvs
* The all TLVs in this proactive command.
*/
processBipMessage: function(cmdDetails, ctlvs) {
+ let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
let bipMsg = {};
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
+ let ctlv = StkProactiveCmdHelper.searchForTag(
+ COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
if (ctlv) {
bipMsg.text = ctlv.value.identifier;
}
+ ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
+ return bipMsg;
+ }
+
+ let iconId = ctlv.value;
+ bipMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
+
+ let onerror = (function() {
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ let onsuccess = (function(result) {
+ bipMsg.icons = result[0];
+ this.context.RIL.sendChromeMessage(cmdDetails);
+ }).bind(this);
+
+ bipMsg.pending = true;
+ this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
+
return bipMsg;
}
};
StkCommandParamsFactoryObject.prototype[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
return this.processRefresh(cmdDetails, ctlvs);
};
StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_INTERVAL] = function STK_CMD_POLL_INTERVAL(cmdDetails, ctlvs) {
return this.processPollInterval(cmdDetails, ctlvs);
@@ -11467,16 +11696,62 @@ StkProactiveCmdHelperObject.prototype =
eventList.push(GsmPDUHelper.readHexOctet());
}
return {
eventList: eventList
};
},
/**
+ * Icon Id.
+ *
+ * | Byte | Description | Length |
+ * | 1 | Icon Identifier Tag | 1 |
+ * | 2 | Length = 02 | 1 |
+ * | 3 | Icon qualifier | 1 |
+ * | 4 | Icon identifier | 1 |
+ */
+ retrieveIconId: function(length) {
+ if (!length) {
+ return null;
+ }
+
+ let iconId = {
+ qualifier: this.context.GsmPDUHelper.readHexOctet(),
+ identifier: this.context.GsmPDUHelper.readHexOctet()
+ };
+ return iconId;
+ },
+
+ /**
+ * Icon Id List.
+ *
+ * | Byte | Description | Length |
+ * | 1 | Icon Identifier Tag | 1 |
+ * | 2 | Length = X | 1 |
+ * | 3 | Icon qualifier | 1 |
+ * | 4~ | Icon identifier | X-1 |
+ * | 4+X-2 | | |
+ */
+ retrieveIconIdList: function(length) {
+ if (!length) {
+ return null;
+ }
+
+ let iconIdList = {
+ qualifier: this.context.GsmPDUHelper.readHexOctet(),
+ identifiers: []
+ };
+ for (let i = 0; i < length - 1; i++) {
+ iconIdList.identifiers.push(this.context.GsmPDUHelper.readHexOctet());
+ }
+ return iconIdList;
+ },
+
+ /**
* Timer Identifier.
*
* | Byte | Description | Length |
* | 1 | Timer Identifier Tag | 1 |
* | 2 | Length = 01 | 1 |
* | 3 | Timer Identifier | 1 |
*/
retrieveTimerId: function(length) {
@@ -11601,16 +11876,22 @@ StkProactiveCmdHelperObject.prototype[CO
return this.retrieveFileList(length);
};
StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEFAULT_TEXT] = function COMPREHENSIONTLV_TAG_DEFAULT_TEXT(length) {
return this.retrieveDefaultText(length);
};
StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_EVENT_LIST] = function COMPREHENSIONTLV_TAG_EVENT_LIST(length) {
return this.retrieveEventList(length);
};
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID] = function COMPREHENSIONTLV_TAG_ICON_ID(length) {
+ return this.retrieveIconId(length);
+};
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID_LIST] = function COMPREHENSIONTLV_TAG_ICON_ID_LIST(length) {
+ return this.retrieveIconIdList(length);
+};
StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER] = function COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER(length) {
return this.retrieveTimerId(length);
};
StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_VALUE] = function COMPREHENSIONTLV_TAG_TIMER_VALUE(length) {
return this.retrieveTimerValue(length);
};
StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE] = function COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE(length) {
return this.retrieveImmediaResponse(length);
@@ -12135,16 +12416,18 @@ ICCFileHelperObject.prototype = {
switch (fileId) {
case ICC_EF_ICCID:
return EF_PATH_MF_SIM;
case ICC_EF_ADN:
case ICC_EF_SDN: // Fall through.
return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
case ICC_EF_PBR:
return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
+ case ICC_EF_IMG:
+ return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_GRAPHICS;
}
return null;
},
/**
* This function handles EFs for SIM.
*/
getSimEFPath: function(fileId) {
@@ -13259,16 +13542,165 @@ SimRecordHelperObject.prototype = {
}
this.context.ICCIOHelper.loadTransparentEF({
fileId: ICC_EF_SPN,
callback: callback.bind(this)
});
},
+ readIMG: function(recordNumber, onsuccess, onerror) {
+ function callback(options) {
+ let RIL = this.context.RIL;
+ let Buf = this.context.Buf;
+ let GsmPDUHelper = this.context.GsmPDUHelper;
+ let strLen = Buf.readInt32();
+ // Each octet is encoded into two chars.
+ let octetLen = strLen / 2;
+
+ let numInstances = GsmPDUHelper.readHexOctet();
+
+ // Correct data length should be 9n+1 or 9n+2. See TS 31.102, sub-clause
+ // 4.6.1.1.
+ if (octetLen != (9 * numInstances + 1) ||
+ octetLen != (9 * numInstances + 2)) {
+ if (onerror) {
+ onerror();
+ }
+ return;
+ }
+
+ let imgDescriptors = [];
+ for (let i = 0; i < numInstances; i++) {
+ imgDescriptors[i] = {
+ width: GsmPDUHelper.readHexOctet(),
+ height: GsmPDUHelper.readHexOctet(),
+ codingScheme: GsmPDUHelper.readHexOctet(),
+ fileId: (GsmPDUHelper.readHexOctet() << 8) |
+ GsmPDUHelper.readHexOctet(),
+ offset: (GsmPDUHelper.readHexOctet() << 8) |
+ GsmPDUHelper.readHexOctet(),
+ dataLen: (GsmPDUHelper.readHexOctet() << 8) |
+ GsmPDUHelper.readHexOctet()
+ };
+ }
+ Buf.readStringDelimiter(strLen);
+
+ let instances = [];
+ let currentInstance = 0;
+ let readNextInstance = (function(img) {
+ instances[currentInstance] = img;
+ currentInstance++;
+
+ if (currentInstance < numInstances) {
+ let imgDescriptor = imgDescriptors[currentInstance];
+ this.readIIDF(imgDescriptor.fileId,
+ imgDescriptor.offset,
+ imgDescriptor.dataLen,
+ imgDescriptor.codingScheme,
+ readNextInstance,
+ onerror);
+ } else {
+ if (onsuccess) {
+ onsuccess(instances);
+ }
+ }
+ }).bind(this);
+
+ this.readIIDF(imgDescriptors[0].fileId,
+ imgDescriptors[0].offset,
+ imgDescriptors[0].dataLen,
+ imgDescriptors[0].codingScheme,
+ readNextInstance,
+ onerror);
+ }
+
+ this.context.ICCIOHelper.loadLinearFixedEF({
+ fileId: ICC_EF_IMG,
+ recordNumber: recordNumber,
+ callback: callback.bind(this),
+ onerror: onerror
+ });
+ },
+
+ readIIDF: function(fileId, offset, dataLen, codingScheme, onsuccess, onerror) {
+ // Valid fileId is '4FXX', see TS 31.102, clause 4.6.1.2.
+ if ((fileId >> 8) != 0x4F) {
+ if (onerror) {
+ onerror();
+ }
+ return;
+ }
+
+ function callback() {
+ let Buf = this.context.Buf;
+ let RIL = this.context.RIL;
+ let GsmPDUHelper = this.context.GsmPDUHelper;
+ let strLen = Buf.readInt32();
+ // Each octet is encoded into two chars.
+ let octetLen = strLen / 2;
+
+ if (octetLen < offset + dataLen) {
+ // Data length is not enough. See TS 31.102, clause 4.6.1.1, the
+ // paragraph "Bytes 8 and 9: Length of Image Instance Data."
+ if (onerror) {
+ onerror();
+ }
+ return;
+ }
+
+ Buf.seekIncoming(offset * Buf.PDU_HEX_OCTET_SIZE);
+
+ let rawData = {
+ width: GsmPDUHelper.readHexOctet(),
+ height: GsmPDUHelper.readHexOctet(),
+ codingScheme: codingScheme
+ };
+
+ switch (codingScheme) {
+ case ICC_IMG_CODING_SCHEME_BASIC:
+ rawData.body = GsmPDUHelper.readHexOctetArray(
+ dataLen - ICC_IMG_HEADER_SIZE_BASIC);
+ Buf.seekIncoming((octetLen - offset - dataLen) * Buf.PDU_HEX_OCTET_SIZE);
+ break;
+
+ case ICC_IMG_CODING_SCHEME_COLOR:
+ case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
+ rawData.bitsPerImgPoint = GsmPDUHelper.readHexOctet();
+ let num = GsmPDUHelper.readHexOctet();
+ // The value 0 shall be interpreted as 256. See TS 31.102, Annex B.2.
+ rawData.numOfClutEntries = (num === 0) ? 0x100 : num;
+ rawData.clutOffset = (GsmPDUHelper.readHexOctet() << 8) |
+ GsmPDUHelper.readHexOctet();
+ rawData.body = GsmPDUHelper.readHexOctetArray(
+ dataLen - ICC_IMG_HEADER_SIZE_COLOR);
+
+ Buf.seekIncoming((rawData.clutOffset - offset - dataLen) *
+ Buf.PDU_HEX_OCTET_SIZE);
+ let clut = GsmPDUHelper.readHexOctetArray(rawData.numOfClutEntries *
+ ICC_CLUT_ENTRY_SIZE);
+
+ rawData.clut = clut;
+ }
+
+ Buf.readStringDelimiter(strLen);
+
+ if (onsuccess) {
+ onsuccess(rawData);
+ }
+ }
+
+ this.context.ICCIOHelper.loadTransparentEF({
+ fileId: fileId,
+ pathId: this.context.ICCFileHelper.getEFPath(ICC_EF_IMG),
+ callback: callback.bind(this),
+ onerror: onerror
+ });
+ },
+
/**
* Read the (U)SIM Service Table from the (U)SIM.
*/
readSST: function() {
function callback() {
let Buf = this.context.Buf;
let RIL = this.context.RIL;
@@ -15292,16 +15724,120 @@ ICCContactHelperObject.prototype = {
let gotIAPCb = function gotIAPCb(iap) {
iap[pbr[field].indexInIAP] = value;
ICCRecordHelper.updateIAP(pbr.iap.fileId, recordNumber, iap, onsuccess, onerror);
}.bind(this);
ICCRecordHelper.readIAP(pbr.iap.fileId, recordNumber, gotIAPCb, onerror);
},
};
+function IconLoaderObject(aContext) {
+ this.context = aContext;
+}
+IconLoaderObject.prototype = {
+ context: null,
+
+ /**
+ * Load icons.
+ *
+ * @param recordNumbers Array of the record identifiers of EF_IMG.
+ * @param onsuccess Callback to be called when success.
+ * @param onerror Callback to be called when error.
+ */
+ loadIcons: function(recordNumbers, onsuccess, onerror) {
+ if (!recordNumbers || !recordNumbers.length) {
+ if (onerror) {
+ onerror();
+ }
+ return;
+ }
+
+ this._start({
+ recordNumbers: recordNumbers,
+ onsuccess: onsuccess,
+ onerror: onerror});
+ },
+
+ _start: function(options) {
+ let callback = (function(icons) {
+ if (!options.icons) {
+ options.icons = [];
+ }
+ for (let i = 0; i < icons.length; i++) {
+ icons[i] = this._parseRawData(icons[i]);
+ }
+ options.icons[options.currentRecordIndex] = icons;
+ options.currentRecordIndex++;
+
+ let recordNumbers = options.recordNumbers;
+ if (options.currentRecordIndex < recordNumbers.length) {
+ let recordNumber = recordNumbers[options.currentRecordIndex];
+ this.context.SimRecordHelper.readIMG(recordNumber,
+ callback,
+ options.onerror);
+ } else {
+ if (options.onsuccess) {
+ options.onsuccess(options.icons);
+ }
+ }
+ }).bind(this);
+
+ options.currentRecordIndex = 0;
+ this.context.SimRecordHelper.readIMG(options.recordNumbers[0],
+ callback,
+ options.onerror);
+ },
+
+ _parseRawData: function(rawData) {
+ let codingScheme = rawData.codingScheme;
+
+ switch (codingScheme) {
+ case ICC_IMG_CODING_SCHEME_BASIC:
+ return {pixels: rawData.body,
+ width: rawData.width,
+ height: rawData.height};
+
+ case ICC_IMG_CODING_SCHEME_COLOR:
+ case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
+ let bitsPerImgPoint = rawData.bitsPerImgPoint;
+ let mask = 0xff >> (8 - bitsPerImgPoint);
+ let bitsStartOffset = 8 - bitsPerImgPoint;
+ let bitIndex = bitsStartOffset;
+ let numOfClutEntries = rawData.numOfClutEntries;
+ let clut = rawData.clut;
+ let body = rawData.body;
+ let numOfPixels = rawData.width * rawData.height;
+ let pixelIndex = 0;
+ let currentByteIndex = 0;
+ let currentByte = body[currentByteIndex++];
+
+ let pixels = [];
+ while (pixelIndex < numOfPixels) {
+ // Reassign data and index for every byte (8 bits).
+ if (bitIndex < 0) {
+ currentByte = body[currentByteIndex++];
+ bitIndex = bitsStartOffset;
+ }
+ let clutEntry = ((currentByte >> bitIndex) & mask);
+ let clutIndex = clutEntry * ICC_CLUT_ENTRY_SIZE;
+ let alpha = codingScheme == ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY &&
+ clutEntry == numOfClutEntries - 1;
+ pixels[pixelIndex++] = {red: clut[clutIndex],
+ green: clut[clutIndex + 1],
+ blue: clut[clutIndex + 2],
+ alpha: alpha ? 0x00 : 0xff};
+ bitIndex -= bitsPerImgPoint;
+ }
+ return {pixels: pixels,
+ width: rawData.width,
+ height: rawData.height};
+ }
+ },
+};
+
/**
* Global stuff.
*/
function Context(aClientId) {
this.clientId = aClientId;
this.Buf = new BufObject(this);
@@ -15321,17 +15857,17 @@ Context.prototype = {
};
(function() {
let lazySymbols = [
"BerTlvHelper", "BitBufferHelper", "CdmaPDUHelper",
"ComprehensionTlvHelper", "GsmPDUHelper", "ICCContactHelper",
"ICCFileHelper", "ICCIOHelper", "ICCPDUHelper", "ICCRecordHelper",
"ICCUtilsHelper", "RuimRecordHelper", "SimRecordHelper",
- "StkCommandParamsFactory", "StkProactiveCmdHelper",
+ "StkCommandParamsFactory", "StkProactiveCmdHelper", "IconLoader",
];
for (let i = 0; i < lazySymbols.length; i++) {
let symbol = lazySymbols[i];
Object.defineProperty(Context.prototype, symbol, {
get: function() {
let real = new GLOBAL[symbol + "Object"](this);
Object.defineProperty(this, symbol, {
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js
@@ -0,0 +1,869 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+ run_next_test();
+}
+
+/**
+ * Verify IconLoader.loadIcons with recordNumbers array length being 1.
+ * Query images of one record at a time.
+ */
+add_test(function test_load_icon_basic() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let ril = context.RIL;
+ let iconLoader = context.IconLoader;
+ let simRecordHelper = context.SimRecordHelper;
+
+ let test_data = [
+ {rawData: [
+ {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ width: 0x10,
+ height: 0x10,
+ body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ expected: [
+ {width: 0x10,
+ height: 0x10,
+ pixels: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}]},
+ {rawData: [
+ {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ width: 0x10,
+ height: 0x10,
+ bitsPerImgPoint: 0x04,
+ numOfClutEntries: 0x10,
+ body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
+ 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
+ 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
+ 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
+ 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
+ 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99],
+ clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
+ 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff]}],
+ expected: [
+ {width: 0x10,
+ height: 0x10,
+ pixels: [
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff}]}]},
+ {rawData: [
+ {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ width: 0x03,
+ height: 0x03,
+ bitsPerImgPoint: 0x05,
+ numOfClutEntries: 0x20,
+ body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
+ clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
+ {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ width: 0x10,
+ height: 0x10,
+ body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ expected: [
+ {width: 0x03,
+ height: 0x03,
+ pixels: [
+ {red: 0x00, green: 0x01, blue: 0x02, alpha: 0xff},
+ {red: 0x06, green: 0x07, blue: 0x08, alpha: 0xff},
+ {red: 0x0c, green: 0x0d, blue: 0x0e, alpha: 0xff},
+ {red: 0x12, green: 0x13, blue: 0x14, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x33, green: 0x34, blue: 0x35, alpha: 0xff}]},
+ {width: 0x10,
+ height: 0x10,
+ pixels: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}]},
+ {rawData: [
+ {codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
+ width: 0x04,
+ height: 0x04,
+ bitsPerImgPoint: 0x04,
+ numOfClutEntries: 0x10,
+ body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
+ clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f]}],
+ expected: [
+ {width: 0x04,
+ height: 0x04,
+ pixels: [
+ {red: 0x2d, green: 0x2e, blue: 0x2f, alpha: 0x00},
+ {red: 0x2d, green: 0x2e, blue: 0x2f, alpha: 0x00},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x27, green: 0x28, blue: 0x29, alpha: 0xff},
+ {red: 0x27, green: 0x28, blue: 0x29, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x21, green: 0x22, blue: 0x23, alpha: 0xff},
+ {red: 0x21, green: 0x22, blue: 0x23, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x1b, green: 0x1c, blue: 0x1d, alpha: 0xff},
+ {red: 0x1b, green: 0x1c, blue: 0x1d, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff}]}]}];
+
+ function do_test(test_data, expected) {
+ simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
+ onsuccess(test_data);
+ };
+
+ let onsuccess = function(icons) {
+ // Query one record at a time.
+ do_check_eq(icons.length, 1);
+ do_check_eq(icons[0].length, expected.length);
+ for (let i = 0; i < icons[0].length; i++) {
+ // Read the i_th image of the record.
+ let icon = icons[0][i];
+ let exp = expected[i];
+ do_check_eq(icon.width, exp.width);
+ do_check_eq(icon.height, exp.height);
+ do_check_eq(icon.pixels.length, exp.pixels.length);
+ for (let j = 0; j < icon.pixels.length; j++) {
+ if (typeof icon.pixels[j] === "object") {
+ do_check_eq(icon.pixels[j].red, exp.pixels[j].red);
+ do_check_eq(icon.pixels[j].green, exp.pixels[j].green);
+ do_check_eq(icon.pixels[j].blue, exp.pixels[j].blue);
+ do_check_eq(icon.pixels[j].alpha, exp.pixels[j].alpha);
+ } else {
+ do_check_eq(icon.pixels[j], exp.pixels[j]);
+ }
+ }
+ }
+ };
+
+ iconLoader.loadIcons([0], onsuccess);
+ }
+
+ for (let i = 0; i < test_data.length; i++) {
+ do_test(test_data[i].rawData, test_data[i].expected);
+ }
+
+ run_next_test();
+});
+
+/**
+ * Verify IconLoader.loadIcons.
+ */
+add_test(function test_load_icons() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let ril = context.RIL;
+ let iconLoader = context.IconLoader;
+ let simRecordHelper = context.SimRecordHelper;
+
+ let test_data = {
+ rawData: [
+ // Record 1.
+ [{codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ width: 0x10,
+ height: 0x10,
+ body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ // Record 2.
+ [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ width: 0x10,
+ height: 0x10,
+ bitsPerImgPoint: 0x04,
+ numOfClutEntries: 0x10,
+ body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
+ 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
+ 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
+ 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
+ 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
+ 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99],
+ clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
+ 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff]}],
+ // Record 3.
+ [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ width: 0x03,
+ height: 0x03,
+ bitsPerImgPoint: 0x05,
+ numOfClutEntries: 0x20,
+ body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
+ clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
+ {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ width: 0x10,
+ height: 0x10,
+ body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ // Record 4.
+ [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
+ width: 0x04,
+ height: 0x04,
+ bitsPerImgPoint: 0x04,
+ numOfClutEntries: 0x10,
+ body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
+ clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f]}]],
+ expected: [
+ // Record 1.
+ [{width: 0x10,
+ height: 0x10,
+ pixels: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ // Record 2.
+ [{width: 0x10,
+ height: 0x10,
+ pixels: [
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0x00, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0x00, green: 0xff, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0xff, blue: 0xff, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff},
+ {red: 0xff, green: 0x00, blue: 0x00, alpha: 0xff}]}],
+ // Record 3.
+ [{width: 0x03,
+ height: 0x03,
+ pixels: [
+ {red: 0x00, green: 0x01, blue: 0x02, alpha: 0xff},
+ {red: 0x06, green: 0x07, blue: 0x08, alpha: 0xff},
+ {red: 0x0c, green: 0x0d, blue: 0x0e, alpha: 0xff},
+ {red: 0x12, green: 0x13, blue: 0x14, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x33, green: 0x34, blue: 0x35, alpha: 0xff}]},
+ {width: 0x10,
+ height: 0x10,
+ pixels: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
+ 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff]}],
+ // Record 4.
+ [{width: 0x04,
+ height: 0x04,
+ pixels: [
+ {red: 0x2d, green: 0x2e, blue: 0x2f, alpha: 0x00},
+ {red: 0x2d, green: 0x2e, blue: 0x2f, alpha: 0x00},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x2a, green: 0x2b, blue: 0x2c, alpha: 0xff},
+ {red: 0x27, green: 0x28, blue: 0x29, alpha: 0xff},
+ {red: 0x27, green: 0x28, blue: 0x29, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x24, green: 0x25, blue: 0x26, alpha: 0xff},
+ {red: 0x21, green: 0x22, blue: 0x23, alpha: 0xff},
+ {red: 0x21, green: 0x22, blue: 0x23, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x1e, green: 0x1f, blue: 0x20, alpha: 0xff},
+ {red: 0x1b, green: 0x1c, blue: 0x1d, alpha: 0xff},
+ {red: 0x1b, green: 0x1c, blue: 0x1d, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff},
+ {red: 0x18, green: 0x19, blue: 0x1a, alpha: 0xff}]}]]};
+
+ function do_test() {
+ simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
+ onsuccess(test_data.rawData[recordNumber]);
+ };
+
+ let onsuccess = function(icons) {
+ do_check_eq(icons.length, test_data.expected.length);
+ for (let i = 0; i < icons.length; i++) {
+ for (let j = 0; j < icons[i].length; j++) {
+ // Read the j_th image from the i_th record.
+ let icon = icons[i][j];
+ let expected = test_data.expected[i][j];
+ do_check_eq(icon.width, expected.width);
+ do_check_eq(icon.height, expected.height);
+ do_check_eq(icon.pixels.length, expected.pixels.length);
+ for (let k = 0; k < icon.pixels.length; k++) {
+ if (typeof icon.pixels[k] === "object") {
+ do_check_eq(icon.pixels[k].red, expected.pixels[k].red);
+ do_check_eq(icon.pixels[k].green, expected.pixels[k].green);
+ do_check_eq(icon.pixels[k].blue, expected.pixels[k].blue);
+ do_check_eq(icon.pixels[k].alpha, expected.pixels[k].alpha);
+ } else {
+ do_check_eq(icon.pixels[k], expected.pixels[k]);
+ }
+ }
+ }
+ }
+ };
+
+ let recordNumbers = [0, 1, 2, 3];
+ iconLoader.loadIcons(recordNumbers, onsuccess);
+ }
+
+ do_test();
+ run_next_test();
+});
--- a/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
@@ -597,8 +597,677 @@ add_test(function test_update_display_co
ril.operator.mnc = 01;
do_test_spn(0x00, true, true);
do_test_spn(0x01, true, true);
do_test_spn(0x02, true, false);
do_test_spn(0x03, true, false);
run_next_test();
});
+
+/**
+ * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_BASIC
+ */
+add_test(function test_reading_img_basic() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ let test_data = [
+ {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06],
+ iidf: [
+ [/* Header */
+ 0x05, 0x05,
+ /* Image body */
+ 0x11, 0x33, 0x55, 0xfe]],
+ expected: [
+ {width: 0x05,
+ height: 0x05,
+ codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ body: [0x11, 0x33, 0x55, 0xfe]}]},
+ {img: [0x02, 0x10, 0x01, 0x11, 0x4f, 0x04, 0x00, 0x05, 0x00, 0x04, 0x10,
+ 0x01, 0x11, 0x4f, 0x05, 0x00, 0x05, 0x00, 0x04],
+ iidf: [
+ [/* Data offset */
+ 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* Header */
+ 0x10, 0x01,
+ /* Image body */
+ 0x11, 0x99,
+ /* Trailing data */
+ 0xff, 0xff, 0xff],
+ [/* Data offset */
+ 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* Header */
+ 0x10, 0x01,
+ /* Image body */
+ 0x99, 0x11]],
+ expected: [
+ {width: 0x10,
+ height: 0x01,
+ codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ body: [0x11, 0x99]},
+ {width: 0x10,
+ height: 0x01,
+ codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ body: [0x99, 0x11]}]},
+ {img: [0x01, 0x28, 0x20, 0x11, 0x4f, 0xac, 0x00, 0x0b, 0x00, 0xa2],
+ iidf: [
+ [/* Data offset */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* Header */
+ 0x28, 0x20,
+ /* Image body */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+ 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+ 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
+ 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]],
+ expected: [
+ {width: 0x28,
+ height: 0x20,
+ codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
+ body: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
+ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]}]}];
+
+ function do_test(img, iidf, expected) {
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img.length * 2);
+
+ // Write data
+ for (let i = 0; i < img.length; i++) {
+ helper.writeHexOctet(img[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let instanceIndex = 0;
+ io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+ // Write data size
+ buf.writeInt32(iidf[instanceIndex].length * 2);
+
+ // Write data
+ for (let i = 0; i < iidf[instanceIndex].length; i++) {
+ helper.writeHexOctet(iidf[instanceIndex][i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
+
+ instanceIndex++;
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function(icons) {
+ do_check_eq(icons.length, expected.length);
+ for (let i = 0; i < icons.length; i++) {
+ let icon = icons[i];
+ let exp = expected[i];
+ do_check_eq(icon.width, exp.width);
+ do_check_eq(icon.height, exp.height);
+ do_check_eq(icon.codingScheme, exp.codingScheme);
+
+ do_check_eq(icon.body.length, exp.body.length);
+ for (let j = 0; j < icon.body.length; j++) {
+ do_check_eq(icon.body[j], exp.body[j]);
+ }
+ }
+ };
+ record.readIMG(0, onsuccess);
+ }
+
+ for (let i = 0; i< test_data.length; i++) {
+ do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
+ }
+ run_next_test();
+});
+
+/**
+ * Verify reading EF_IMG and EF_IIDF with the case data length is not enough
+ */
+add_test(function test_reading_img_length_error() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ // Offset is 0x0004.
+ let img_test = [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x04, 0x00, 0x06];
+ let iidf_test = [0xff, 0xff, 0xff, // Offset length not enough.
+ 0x05, 0x05, 0x11, 0x22, 0x33, 0xfe];
+
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img_test.length * 2);
+
+ // Write data
+ for (let i = 0; i < img_test.length; i++) {
+ helper.writeHexOctet(img_test[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img_test.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+ // Write data size
+ buf.writeInt32(iidf_test.length * 2);
+
+ // Write data
+ for (let i = 0; i < iidf_test.length; i++) {
+ helper.writeHexOctet(iidf_test[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(iidf_test.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function() {
+ do_print("onsuccess shouldn't be called.");
+ do_check_true(false);
+ };
+
+ let onerror = function() {
+ do_print("onerror called as expected.");
+ do_check_true(true);
+ };
+
+ record.readIMG(0, onsuccess, onerror);
+
+ run_next_test();
+});
+
+/**
+ * Verify reading EF_IMG and EF_IIDF with an invalid fileId
+ */
+add_test(function test_reading_img_invalid_fileId() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ // Test invalid fileId: 0x5f00.
+ let img_test = [0x01, 0x05, 0x05, 0x11, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x06];
+ let iidf_test = [0x05, 0x05, 0x11, 0x22, 0x33, 0xfe];
+
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img_test.length * 2);
+
+ // Write data
+ for (let i = 0; i < img_test.length; i++) {
+ helper.writeHexOctet(img_test[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img_test.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+ // Write data size
+ buf.writeInt32(iidf_test.length * 2);
+
+ // Write data
+ for (let i = 0; i < iidf_test.length; i++) {
+ helper.writeHexOctet(iidf_test[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(iidf_test.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function() {
+ do_print("onsuccess shouldn't be called.");
+ do_check_true(false);
+ };
+
+ let onerror = function() {
+ do_print("onerror called as expected.");
+ do_check_true(true);
+ };
+
+ record.readIMG(0, onsuccess, onerror);
+
+ run_next_test();
+});
+
+/**
+ * Verify reading EF_IMG with a wrong record length
+ */
+add_test(function test_reading_img_wrong_record_length() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ let test_data = [
+ [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xff, 0xff],
+ [0x02, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06]];
+
+ function do_test(img) {
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img.length * 2);
+
+ // Write data
+ for (let i = 0; i < img.length; i++) {
+ helper.writeHexOctet(img[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function() {
+ do_print("onsuccess shouldn't be called.");
+ do_check_true(false);
+ };
+
+ let onerror = function() {
+ do_print("onerror called as expected.");
+ do_check_true(true);
+ };
+
+ record.readIMG(0, onsuccess, onerror);
+ }
+
+ for (let i = 0; i < test_data.length; i++) {
+ do_test(test_data[i]);
+ }
+ run_next_test();
+});
+
+/**
+ * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_COLOR
+ */
+add_test(function test_reading_img_color() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ let test_data = [
+ {img: [0x01, 0x05, 0x05, 0x21, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
+ iidf: [
+ [/* Header */
+ 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
+ /* Image body */
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
+ 0xb0, 0xc0, 0xd0,
+ /* Clut entries */
+ 0x00, 0x01, 0x02,
+ 0x10, 0x11, 0x12,
+ 0x20, 0x21, 0x22,
+ 0x30, 0x31, 0x32,
+ 0x40, 0x41, 0x42,
+ 0x50, 0x51, 0x52,
+ 0x60, 0x61, 0x62,
+ 0x70, 0x71, 0x72]],
+ expected: [
+ {width: 0x05,
+ height: 0x05,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ bitsPerImgPoint: 0x03,
+ numOfClutEntries: 0x08,
+ body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0,
+ 0xc0, 0xd0],
+ clut: [0x00, 0x01, 0x02,
+ 0x10, 0x11, 0x12,
+ 0x20, 0x21, 0x22,
+ 0x30, 0x31, 0x32,
+ 0x40, 0x41, 0x42,
+ 0x50, 0x51, 0x52,
+ 0x60, 0x61, 0x62,
+ 0x70, 0x71, 0x72]}]},
+ {img: [0x02, 0x01, 0x06, 0x21, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
+ 0x06, 0x21, 0x4f, 0x44, 0x00, 0x02, 0x00, 0x08],
+ iidf: [
+ [/* Data offset */
+ 0xff, 0xff,
+ /* Header */
+ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
+ /* Image body */
+ 0x40, 0x50,
+ /* Clut offset */
+ 0xaa, 0xbb, 0xcc,
+ /* Clut entries */
+ 0x01, 0x03, 0x05,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65],
+ [/* Data offset */
+ 0xff, 0xff,
+ /* Header */
+ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
+ /* Image body */
+ 0x4f, 0x5f,
+ /* Clut offset */
+ 0xaa, 0xbb, 0xcc,
+ /* Clut entries */
+ 0x11, 0x13, 0x15,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]],
+ expected: [
+ {width: 0x01,
+ height: 0x06,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ bitsPerImgPoint: 0x02,
+ numOfClutEntries: 0x04,
+ body: [0x40, 0x50],
+ clut: [0x01, 0x03, 0x05,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]},
+ {width: 0x01,
+ height: 0x06,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
+ bitsPerImgPoint: 0x02,
+ numOfClutEntries: 0x04,
+ body: [0x4f, 0x5f],
+ clut: [0x11, 0x13, 0x15,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]}]}];
+
+ function do_test(img, iidf, expected) {
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img.length * 2);
+
+ // Write data
+ for (let i = 0; i < img.length; i++) {
+ helper.writeHexOctet(img[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let instanceIndex = 0;
+ io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+ // Write data size
+ buf.writeInt32(iidf[instanceIndex].length * 2);
+
+ // Write data
+ for (let i = 0; i < iidf[instanceIndex].length; i++) {
+ helper.writeHexOctet(iidf[instanceIndex][i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
+
+ instanceIndex++;
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function(icons) {
+ do_check_eq(icons.length, expected.length);
+ for (let i = 0; i < icons.length; i++) {
+ let icon = icons[i];
+ let exp = expected[i];
+ do_check_eq(icon.width, exp.width);
+ do_check_eq(icon.height, exp.height);
+ do_check_eq(icon.codingScheme, exp.codingScheme);
+
+ do_check_eq(icon.body.length, exp.body.length);
+ for (let j = 0; j < icon.body.length; j++) {
+ do_check_eq(icon.body[j], exp.body[j]);
+ }
+
+ do_check_eq(icon.clut.length, exp.clut.length);
+ for (let j = 0; j < icon.clut.length; j++) {
+ do_check_eq(icon.clut[j], exp.clut[j]);
+ }
+ }
+ };
+
+ record.readIMG(0, onsuccess);
+ }
+
+ for (let i = 0; i< test_data.length; i++) {
+ do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
+ }
+ run_next_test();
+});
+
+/**
+ * Verify reading EF_IMG and EF_IIDF with
+ * ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY
+ */
+add_test(function test_reading_img_color() {
+ let worker = newUint8Worker();
+ let context = worker.ContextPool._contexts[0];
+ let record = context.SimRecordHelper;
+ let helper = context.GsmPDUHelper;
+ let ril = context.RIL;
+ let buf = context.Buf;
+ let io = context.ICCIOHelper;
+
+ let test_data = [
+ {img: [0x01, 0x05, 0x05, 0x22, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
+ iidf: [
+ [/* Header */
+ 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
+ /* Image body */
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
+ 0xb0, 0xc0, 0xd0,
+ /* Clut entries */
+ 0x00, 0x01, 0x02,
+ 0x10, 0x11, 0x12,
+ 0x20, 0x21, 0x22,
+ 0x30, 0x31, 0x32,
+ 0x40, 0x41, 0x42,
+ 0x50, 0x51, 0x52,
+ 0x60, 0x61, 0x62,
+ 0x70, 0x71, 0x72]],
+ expected: [
+ {width: 0x05,
+ height: 0x05,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
+ bitsPerImgPoint: 0x03,
+ numOfClutEntries: 0x08,
+ body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,
+ 0xa0, 0xb0, 0xc0, 0xd0],
+ clut: [0x00, 0x01, 0x02,
+ 0x10, 0x11, 0x12,
+ 0x20, 0x21, 0x22,
+ 0x30, 0x31, 0x32,
+ 0x40, 0x41, 0x42,
+ 0x50, 0x51, 0x52,
+ 0x60, 0x61, 0x62,
+ 0x70, 0x71, 0x72]}]},
+ {img: [0x02, 0x01, 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
+ 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08],
+ iidf: [
+ [/* Data offset */
+ 0xff, 0xff,
+ /* Header */
+ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
+ /* Image body */
+ 0x40, 0x50,
+ /* Clut offset */
+ 0x0a, 0x0b, 0x0c,
+ /* Clut entries */
+ 0x01, 0x03, 0x05,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65],
+ [/* Data offset */
+ 0xff, 0xff,
+ /* Header */
+ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
+ /* Image body */
+ 0x4f, 0x5f,
+ /* Clut offset */
+ 0x0a, 0x0b, 0x0c,
+ /* Clut entries */
+ 0x11, 0x13, 0x15,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]],
+ expected: [
+ {width: 0x01,
+ height: 0x06,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
+ bitsPerImgPoint: 0x02,
+ numOfClutEntries: 0x04,
+ body: [0x40, 0x50],
+ clut: [0x01, 0x03, 0x05,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]},
+ {width: 0x01,
+ height: 0x06,
+ codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
+ bitsPerImgPoint: 0x02,
+ numOfClutEntries: 0x04,
+ body: [0x4f, 0x5f],
+ clut: [0x11, 0x13, 0x15,
+ 0x21, 0x23, 0x25,
+ 0x41, 0x43, 0x45,
+ 0x61, 0x63, 0x65]}]}];
+
+ function do_test(img, iidf, expected) {
+ io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+ // Write data size
+ buf.writeInt32(img.length * 2);
+
+ // Write data
+ for (let i = 0; i < img.length; i++) {
+ helper.writeHexOctet(img[i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(img.length * 2);
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let instanceIndex = 0;
+ io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+ // Write data size
+ buf.writeInt32(iidf[instanceIndex].length * 2);
+
+ // Write data
+ for (let i = 0; i < iidf[instanceIndex].length; i++) {
+ helper.writeHexOctet(iidf[instanceIndex][i]);
+ }
+
+ // Write string delimiter
+ buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
+
+ instanceIndex++;
+
+ if (options.callback) {
+ options.callback(options);
+ }
+ };
+
+ let onsuccess = function(icons) {
+ do_check_eq(icons.length, expected.length);
+ for (let i = 0; i < icons.length; i++) {
+ let icon = icons[i];
+ let exp = expected[i];
+ do_check_eq(icon.width, exp.width);
+ do_check_eq(icon.height, exp.height);
+ do_check_eq(icon.codingScheme, exp.codingScheme);
+
+ do_check_eq(icon.body.length, exp.body.length);
+ for (let j = 0; j < icon.body.length; j++) {
+ do_check_eq(icon.body[j], exp.body[j]);
+ }
+
+ do_check_eq(icon.clut.length, exp.clut.length);
+ for (let j = 0; j < icon.clut.length; j++) {
+ do_check_eq(icon.clut[j], exp.clut[j]);
+ }
+ }
+ };
+
+ record.readIMG(0, onsuccess);
+ }
+
+ for (let i = 0; i< test_data.length; i++) {
+ do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
+ }
+ run_next_test();
+});
--- a/dom/system/gonk/tests/test_ril_worker_stk.js
+++ b/dom/system/gonk/tests/test_ril_worker_stk.js
@@ -409,25 +409,30 @@ add_test(function test_stk_proactive_com
* Verify Proactive Command : Play Tone
*/
add_test(function test_stk_proactive_command_play_tone() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let tone_1 = [
0xD0,
- 0x1B,
+ 0x1F,
0x81, 0x03, 0x01, 0x20, 0x00,
0x82, 0x02, 0x81, 0x03,
0x85, 0x09, 0x44, 0x69, 0x61, 0x6C, 0x20, 0x54, 0x6F, 0x6E, 0x65,
0x8E, 0x01, 0x01,
- 0x84, 0x02, 0x01, 0x05];
+ 0x84, 0x02, 0x01, 0x05,
+ 0x9E, 0x02, 0x00, 0x01];
for (let i = 0; i < tone_1.length; i++) {
pduHelper.writeHexOctet(tone_1[i]);
}
let berTlv = berHelper.decode(tone_1.length);
let ctlvs = berTlv.value;
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
@@ -440,16 +445,20 @@ add_test(function test_stk_proactive_com
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_TONE, ctlvs);
do_check_eq(tlv.value.tone, STK_TONE_TYPE_DIAL_TONE);
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_DURATION, ctlvs);
do_check_eq(tlv.value.timeUnit, STK_TIME_UNIT_SECOND);
do_check_eq(tlv.value.timeInterval, 5);
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
run_next_test();
});
/**
* Verify Proactive Command : Poll Interval
*/
add_test(function test_stk_proactive_command_poll_interval() {
let worker = newUint8Worker();
@@ -487,36 +496,45 @@ add_test(function test_stk_proactive_com
* Verify Proactive Command: Display Text
*/
add_test(function test_read_septets_to_string() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let display_text_1 = [
0xd0,
- 0x28,
+ 0x2c,
0x81, 0x03, 0x01, 0x21, 0x80,
0x82, 0x02, 0x81, 0x02,
0x0d, 0x1d, 0x00, 0xd3, 0x30, 0x9b, 0xfc, 0x06, 0xc9, 0x5c, 0x30, 0x1a,
0xa8, 0xe8, 0x02, 0x59, 0xc3, 0xec, 0x34, 0xb9, 0xac, 0x07, 0xc9, 0x60,
0x2f, 0x58, 0xed, 0x15, 0x9b, 0xb9, 0x40,
+ 0x9e, 0x02, 0x00, 0x01
];
for (let i = 0; i < display_text_1.length; i++) {
pduHelper.writeHexOctet(display_text_1[i]);
}
let berTlv = berHelper.decode(display_text_1.length);
let ctlvs = berTlv.value;
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
do_check_eq(tlv.value.textString, "Saldo 2.04 E. Validez 20/05/13. ");
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
run_next_test();
});
/**
* Verify Proactive Command: Set Up Event List.
*/
add_test(function test_stk_proactive_command_event_list() {
let worker = newUint8Worker();
@@ -557,25 +575,30 @@ add_test(function test_stk_proactive_com
*/
add_test(function test_stk_proactive_command_get_input() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
let stkCmdHelper = context.StkCommandParamsFactory;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let get_input_1 = [
0xD0,
- 0x1E,
+ 0x22,
0x81, 0x03, 0x01, 0x23, 0x8F,
0x82, 0x02, 0x81, 0x82,
0x8D, 0x05, 0x04, 0x54, 0x65, 0x78, 0x74,
0x91, 0x02, 0x01, 0x10,
- 0x17, 0x08, 0x04, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74];
+ 0x17, 0x08, 0x04, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74,
+ 0x9E, 0x02, 0x00, 0x01];
for (let i = 0; i < get_input_1.length; i++) {
pduHelper.writeHexOctet(get_input_1[i]);
}
let berTlv = berHelper.decode(get_input_1.length);
let ctlvs = berTlv.value;
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
@@ -588,16 +611,20 @@ add_test(function test_stk_proactive_com
do_check_eq(input.isUCS2, true);
do_check_eq(input.hideInput, true);
do_check_eq(input.isPacked, true);
do_check_eq(input.isHelpAvailable, true);
do_check_eq(input.minLength, 0x01);
do_check_eq(input.maxLength, 0x10);
do_check_eq(input.defaultText, "Default");
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
let get_input_2 = [
0xD0,
0x11,
0x81, 0x03, 0x01, 0x23, 0x00,
0x82, 0x02, 0x81, 0x82,
0x8D, 0x00,
0x91, 0x02, 0x01, 0x10,
0x17, 0x00];
@@ -656,28 +683,34 @@ add_test(function test_stk_proactive_com
*/
add_test(function test_stk_proactive_command_select_item() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
let stkFactory = context.StkCommandParamsFactory;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let select_item_1 = [
0xD0,
- 0x33,
+ 0x3C,
0x81, 0x03, 0x01, 0x24, 0x00,
0x82, 0x02, 0x81, 0x82,
0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
0x18, 0x03, 0x10, 0x15, 0x20,
- 0x90, 0x01, 0x01
+ 0x90, 0x01, 0x01,
+ 0x9E, 0x02, 0x00, 0x01,
+ 0x9F, 0x03, 0x00, 0x01, 0x02
];
for(let i = 0 ; i < select_item_1.length; i++) {
pduHelper.writeHexOctet(select_item_1[i]);
}
let berTlv = berHelper.decode(select_item_1.length);
let ctlvs = berTlv.value;
@@ -694,16 +727,25 @@ add_test(function test_stk_proactive_com
do_check_eq(menu.items[1].text, "item 2");
do_check_eq(menu.items[2].identifier, 3);
do_check_eq(menu.items[2].text, "item 3");
do_check_eq(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
do_check_eq(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
do_check_eq(menu.nextActionList[2], STK_CMD_PLAY_TONE);
do_check_eq(menu.defaultItem, 0x00);
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID_LIST, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifiers[0], 0x01);
+ do_check_eq(tlv.value.identifiers[1], 0x02);
+
let select_item_2 = [
0xD0,
0x33,
0x81, 0x03, 0x01, 0x24, 0x00,
0x82, 0x02, 0x81, 0x82,
0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
@@ -744,27 +786,33 @@ add_test(function test_stk_proactive_com
*/
add_test(function test_stk_proactive_command_set_up_menu() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
let stkFactory = context.StkCommandParamsFactory;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let set_up_menu_1 = [
0xD0,
- 0x30,
+ 0x39,
0x81, 0x03, 0x01, 0x25, 0x00,
0x82, 0x02, 0x81, 0x82,
0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x10, 0x15, 0x20
+ 0x18, 0x03, 0x10, 0x15, 0x20,
+ 0x9E, 0x02, 0x00, 0x01,
+ 0x9F, 0x03, 0x00, 0x01, 0x02
];
for(let i = 0 ; i < set_up_menu_1.length; i++) {
pduHelper.writeHexOctet(set_up_menu_1[i]);
}
let berTlv = berHelper.decode(set_up_menu_1.length);
let ctlvs = berTlv.value;
@@ -780,16 +828,25 @@ add_test(function test_stk_proactive_com
do_check_eq(menu.items[1].identifier, 2);
do_check_eq(menu.items[1].text, "item 2");
do_check_eq(menu.items[2].identifier, 3);
do_check_eq(menu.items[2].text, "item 3");
do_check_eq(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
do_check_eq(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
do_check_eq(menu.nextActionList[2], STK_CMD_PLAY_TONE);
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID_LIST, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifiers[0], 0x01);
+ do_check_eq(tlv.value.identifiers[1], 0x02);
+
let set_up_menu_2 = [
0xD0,
0x30,
0x81, 0x03, 0x01, 0x25, 0x00,
0x82, 0x02, 0x81, 0x82,
0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
@@ -828,41 +885,50 @@ add_test(function test_stk_proactive_com
*/
add_test(function test_stk_proactive_command_set_up_call() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let berHelper = context.BerTlvHelper;
let stkHelper = context.StkProactiveCmdHelper;
let cmdFactory = context.StkCommandParamsFactory;
+ let ril = context.RIL;
+ ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10];
+ ril.appType = CARD_APPTYPE_SIM;
let set_up_call_1 = [
0xD0,
- 0x29,
+ 0x2d,
0x81, 0x03, 0x01, 0x10, 0x04,
0x82, 0x02, 0x81, 0x82,
0x05, 0x0A, 0x44, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74,
0x86, 0x09, 0x81, 0x10, 0x32, 0x04, 0x21, 0x43, 0x65, 0x1C, 0x2C,
- 0x05, 0x07, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
+ 0x05, 0x07, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x9E, 0x02, 0x00, 0x01];
for (let i = 0 ; i < set_up_call_1.length; i++) {
pduHelper.writeHexOctet(set_up_call_1[i]);
}
let berTlv = berHelper.decode(set_up_call_1.length);
let ctlvs = berTlv.value;
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
do_check_eq(tlv.value.commandNumber, 0x01);
do_check_eq(tlv.value.typeOfCommand, STK_CMD_SET_UP_CALL);
let setupCall = cmdFactory.createParam(tlv.value, ctlvs);
do_check_eq(setupCall.address, "012340123456,1,2");
do_check_eq(setupCall.confirmMessage, "Disconnect");
do_check_eq(setupCall.callMessage, "Message");
+ tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
+ do_check_eq(tlv.value.qualifier, 0x00);
+ do_check_eq(tlv.value.identifier, 0x01);
+
run_next_test();
});
/**
* Verify Proactive Command : Timer Management
*/
add_test(function test_stk_proactive_command_timer_management() {
let worker = newUint8Worker();
--- a/dom/system/gonk/tests/xpcshell.ini
+++ b/dom/system/gonk/tests/xpcshell.ini
@@ -5,16 +5,17 @@ tail =
[test_ril_worker_buf.js]
[test_ril_worker_icc_CardLock.js]
[test_ril_worker_icc_BerTlvHelper.js]
[test_ril_worker_icc_GsmPDUHelper.js]
[test_ril_worker_icc_ICCContactHelper.js]
[test_ril_worker_icc_ICCIOHelper.js]
[test_ril_worker_icc_ICCPDUHelper.js]
[test_ril_worker_icc_ICCRecordHelper.js]
+[test_ril_worker_icc_IconLoader.js]
[test_ril_worker_icc_ICCUtilsHelper.js]
[test_ril_worker_icc_SimRecordHelper.js]
[test_ril_worker_sms.js]
# Bug 916067 - B2G RIL: test_ril_worker_sms.js takes too long to finish
skip-if = true
[test_ril_worker_sms_cdma.js]
[test_ril_worker_sms_cdmapduhelper.js]
[test_ril_worker_sms_nl_tables.js]
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -361,16 +361,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCalls)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallsList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroup)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony)
+ // Telephony does not expose nsITelephonyListener. mListener is the exposed
+ // nsITelephonyListener and forwards the calls it receives to us.
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(Telephony, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(Telephony, DOMEventTargetHelper)
NS_IMPL_ISUPPORTS(Telephony::Listener, nsITelephonyListener)
NS_IMPL_ISUPPORTS(Telephony::Callback, nsITelephonyCallback)
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -19,20 +19,21 @@
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class OwningTelephonyCallOrTelephonyCallGroup;
-class Telephony MOZ_FINAL : public DOMEventTargetHelper
+class Telephony MOZ_FINAL : public DOMEventTargetHelper,
+ private nsITelephonyListener
{
/**
- * Class Telephony doesn't actually inherit nsITelephonyListener.
+ * Class Telephony doesn't actually expose nsITelephonyListener.
* Instead, it owns an nsITelephonyListener derived instance mListener
* and passes it to nsITelephonyService. The onreceived events are first
* delivered to mListener and then forwarded to its owner, Telephony. See
* also bug 775997 comment #51.
*/
class Listener;
class Callback;
--- a/dom/voicemail/Voicemail.cpp
+++ b/dom/voicemail/Voicemail.cpp
@@ -64,16 +64,18 @@ Voicemail::Voicemail(nsPIDOMWindow* aWin
Voicemail::~Voicemail()
{
MOZ_ASSERT(mProvider && mListener);
mListener->Disconnect();
mProvider->UnregisterVoicemailMsg(mListener);
}
+NS_IMPL_ISUPPORTS_INHERITED0(Voicemail, DOMEventTargetHelper)
+
JSObject*
Voicemail::WrapObject(JSContext* aCx)
{
return MozVoicemailBinding::Wrap(aCx, this);
}
bool
Voicemail::IsValidServiceId(uint32_t aServiceId) const
--- a/dom/voicemail/Voicemail.h
+++ b/dom/voicemail/Voicemail.h
@@ -17,36 +17,38 @@ struct JSContext;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class MozVoicemailStatus;
-class Voicemail MOZ_FINAL : public DOMEventTargetHelper
+class Voicemail MOZ_FINAL : public DOMEventTargetHelper,
+ private nsIVoicemailListener
{
/**
- * Class Voicemail doesn't actually inherit nsIVoicemailListener. Instead, it
+ * Class Voicemail doesn't actually expose nsIVoicemailListener. Instead, it
* owns an nsIVoicemailListener derived instance mListener and passes it to
* nsIVoicemailProvider. The onreceived events are first delivered to
* mListener and then forwarded to its owner, Voicemail. See also bug 775997
* comment #51.
*/
class Listener;
+ virtual ~Voicemail();
+
public:
+ NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIVOICEMAILLISTENER
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
Voicemail(nsPIDOMWindow* aWindow, nsIVoicemailProvider* aProvider);
- virtual ~Voicemail();
-
nsPIDOMWindow*
GetParentObject() const
{
return GetOwner();
}
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
--- a/dom/webidl/ServiceWorkerContainer.webidl
+++ b/dom/webidl/ServiceWorkerContainer.webidl
@@ -3,39 +3,37 @@
* 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/.
*
* The origin of this IDL file is
* http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
*
*/
-[Pref="dom.serviceWorkers.enabled"]
-interface ServiceWorkerContainer {
+[Pref="dom.serviceWorkers.enabled",
+ Exposed=Window]
+interface ServiceWorkerContainer : EventTarget {
// FIXME(nsm):
// https://github.com/slightlyoff/ServiceWorker/issues/198
// and discussion at https://etherpad.mozilla.org/serviceworker07apr
- [Unforgeable] readonly attribute ServiceWorker? installing;
- [Unforgeable] readonly attribute ServiceWorker? waiting;
- [Unforgeable] readonly attribute ServiceWorker? active;
[Unforgeable] readonly attribute ServiceWorker? controller;
[Throws]
- readonly attribute Promise<any> ready;
-
- [Throws]
- Promise<any> getAll();
+ readonly attribute Promise<ServiceWorkerRegistration> ready;
[Throws]
- Promise<ServiceWorker> register(DOMString url, optional RegistrationOptionList options);
+ Promise<ServiceWorkerRegistration> register(ScalarValueString scriptURL,
+ optional RegistrationOptionList options);
[Throws]
- Promise<any> unregister(DOMString? scope);
+ Promise<ServiceWorkerRegistration> getRegistration(optional ScalarValueString documentURL = "");
- attribute EventHandler onupdatefound;
+ [Throws]
+ Promise<sequence<ServiceWorkerRegistration>> getRegistrations();
+
attribute EventHandler oncontrollerchange;
attribute EventHandler onreloadpage;
attribute EventHandler onerror;
};
// Testing only.
partial interface ServiceWorkerContainer {
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
@@ -44,10 +42,10 @@ partial interface ServiceWorkerContainer
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
DOMString getScopeForUrl(DOMString url);
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
DOMString getControllingWorkerScriptURLForPath(DOMString path);
};
dictionary RegistrationOptionList {
- DOMString scope = "/*";
+ ScalarValueString scope = "/*";
};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ServiceWorkerRegistration.webidl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
+ *
+ */
+
+[Pref="dom.serviceWorkers.enabled",
+ Exposed=Window]
+interface ServiceWorkerRegistration : EventTarget {
+ [Unforgeable] readonly attribute ServiceWorker? installing;
+ [Unforgeable] readonly attribute ServiceWorker? waiting;
+ [Unforgeable] readonly attribute ServiceWorker? active;
+
+ readonly attribute ScalarValueString scope;
+
+ [Throws]
+ Promise<boolean> unregister();
+
+ // event
+ attribute EventHandler onupdatefound;
+};
--- a/dom/webidl/TestInterfaceJS.webidl
+++ b/dom/webidl/TestInterfaceJS.webidl
@@ -1,24 +1,37 @@
/* -*- Mode: IDL; 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/.
*/
+dictionary TestInterfaceJSUnionableDictionary {
+ object objectMember;
+ any anyMember;
+};
+
[JSImplementation="@mozilla.org/dom/test-interface-js;1",
Pref="dom.expose_test_interfaces",
- Constructor(optional any anyArg, optional object objectArg)]
+ Constructor(optional any anyArg, optional object objectArg, optional TestInterfaceJSDictionary dictionaryArg)]
interface TestInterfaceJS {
readonly attribute any anyArg;
readonly attribute object objectArg;
+ [Cached, Pure] readonly attribute TestInterfaceJSDictionary dictionaryArg;
attribute any anyAttr;
attribute object objectAttr;
+ [Cached, Pure] attribute TestInterfaceJSDictionary dictionaryAttr;
any pingPongAny(any arg);
- object pingPongObject(any obj);
+ object pingPongObject(object obj);
+ any pingPongObjectOrString((object or DOMString) objOrString);
+ TestInterfaceJSDictionary pingPongDictionary(optional TestInterfaceJSDictionary dict);
+ long pingPongDictionaryOrLong(optional (TestInterfaceJSUnionableDictionary or long) dictOrLong);
+ DOMString pingPongMap(MozMap<any> map);
+ long objectSequenceLength(sequence<object> seq);
+ long anySequenceLength(sequence<any> seq);
// For testing bug 968335.
DOMString getCallerPrincipal();
DOMString convertSVS(ScalarValueString svs);
(TestInterfaceJS or long) pingPongUnion((TestInterfaceJS or long) something);
(DOMString or TestInterfaceJS?) pingPongUnionContainingNull((TestInterfaceJS? or DOMString) something);
new file mode 100644
--- /dev/null
+++ b/dom/webidl/TestInterfaceJSDictionaries.webidl
@@ -0,0 +1,27 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+//
+// These dictionaries are in a separate WebIDL file to avoid circular include
+// problems. One of the dictionary includes a union as a member, so that
+// dictionary's header needs to include UnionTypes.h. But the API in
+// TestInterfaceJS also declares a union of dictionaries, so _that_
+// dictionary's header needs to be included _by_ UnionTypes.h. The solution
+// is to separate those two dictionaries into separate header files.
+//
+
+dictionary TestInterfaceJSDictionary2 {
+ object innerObject;
+};
+
+dictionary TestInterfaceJSDictionary {
+ TestInterfaceJSDictionary2 innerDictionary;
+ object objectMember;
+ any anyMember;
+ (object or DOMString) objectOrStringMember;
+ sequence<any> anySequenceMember;
+};
+
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -321,16 +321,17 @@ WEBIDL_FILES = [
'RTCStatsReport.webidl',
'Screen.webidl',
'ScriptProcessorNode.webidl',
'ScrollAreaEvent.webidl',
'Selection.webidl',
'ServiceWorker.webidl',
'ServiceWorkerContainer.webidl',
'ServiceWorkerGlobalScope.webidl',
+ 'ServiceWorkerRegistration.webidl',
'SettingsManager.webidl',
'ShadowRoot.webidl',
'SharedWorker.webidl',
'SharedWorkerGlobalScope.webidl',
'SimpleGestureEvent.webidl',
'SourceBuffer.webidl',
'SourceBufferList.webidl',
'Storage.webidl',
@@ -558,17 +559,17 @@ WEBIDL_FILES += [
'StyleRuleChangeEvent.webidl',
'StyleSheetApplicableStateChangeEvent.webidl',
'StyleSheetChangeEvent.webidl',
]
# We only expose our prefable test interfaces in debug builds, just to be on
# the safe side.
if CONFIG['MOZ_DEBUG']:
- WEBIDL_FILES += ['TestInterfaceJS.webidl']
+ WEBIDL_FILES += ['TestInterfaceJS.webidl', 'TestInterfaceJSDictionaries.webidl']
if CONFIG['MOZ_B2G_BT']:
if CONFIG['MOZ_B2G_BT_API_V2']:
WEBIDL_FILES += [
'BluetoothAdapter2.webidl',
'BluetoothClassOfDevice.webidl',
'BluetoothDevice2.webidl',
'BluetoothDiscoveryHandle.webidl',
new file mode 100644
--- /dev/null
+++ b/dom/workers/ServiceWorkerCommon.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_dom_ServiceWorkerCommon_h
+#define mozilla_dom_ServiceWorkerCommon_h
+
+namespace mozilla {
+namespace dom {
+
+// Use multiples of 2 since they can be bitwise ORed when calling
+// InvalidateServiceWorkerRegistrationWorker.
+MOZ_BEGIN_ENUM_CLASS(WhichServiceWorker)
+ INSTALLING_WORKER = 1,
+ WAITING_WORKER = 2,
+ ACTIVE_WORKER = 4,
+MOZ_END_ENUM_CLASS(WhichServiceWorker)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(WhichServiceWorker)
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_ServiceWorkerCommon_h
--- a/dom/workers/ServiceWorkerContainer.cpp
+++ b/dom/workers/ServiceWorkerContainer.cpp
@@ -17,40 +17,34 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ServiceWorkerContainerBinding.h"
#include "mozilla/dom/workers/bindings/ServiceWorker.h"
#include "ServiceWorker.h"
namespace mozilla {
namespace dom {
-namespace workers {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper,
- mInstallingWorker,
- mWaitingWorker,
- mActiveWorker,
mControllerWorker)
ServiceWorkerContainer::ServiceWorkerContainer(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
{
SetIsDOMBinding();
- StartListeningForEvents();
}
ServiceWorkerContainer::~ServiceWorkerContainer()
{
- StopListeningForEvents();
}
JSObject*
ServiceWorkerContainer::WrapObject(JSContext* aCx)
{
return ServiceWorkerContainerBinding::Wrap(aCx, this);
}
@@ -72,178 +66,65 @@ ServiceWorkerContainer::Register(const n
return nullptr;
}
nsRefPtr<Promise> ret = static_cast<Promise*>(promise.get());
MOZ_ASSERT(ret);
return ret.forget();
}
-already_AddRefed<Promise>
-ServiceWorkerContainer::Unregister(const nsAString& aScope,
- ErrorResult& aRv)
-{
- nsCOMPtr<nsISupports> promise;
-
- nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
- if (!swm) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- aRv = swm->Unregister(mWindow, aScope, getter_AddRefs(promise));
- if (aRv.Failed()) {
- return nullptr;
- }
-
- nsRefPtr<Promise> ret = static_cast<Promise*>(promise.get());
- MOZ_ASSERT(ret);
- return ret.forget();
-}
-
-already_AddRefed<workers::ServiceWorker>
-ServiceWorkerContainer::GetInstalling()
-{
- if (!mInstallingWorker) {
- mInstallingWorker = GetWorkerReference(WhichServiceWorker::INSTALLING_WORKER);
- }
-
- nsRefPtr<ServiceWorker> ret = mInstallingWorker;
- return ret.forget();
-}
-
-already_AddRefed<workers::ServiceWorker>
-ServiceWorkerContainer::GetWaiting()
-{
- if (!mWaitingWorker) {
- mWaitingWorker = GetWorkerReference(WhichServiceWorker::WAITING_WORKER);
- }
-
- nsRefPtr<ServiceWorker> ret = mWaitingWorker;
- return ret.forget();
-}
-
-already_AddRefed<workers::ServiceWorker>
-ServiceWorkerContainer::GetActive()
-{
- if (!mActiveWorker) {
- mActiveWorker = GetWorkerReference(WhichServiceWorker::ACTIVE_WORKER);
- }
-
- nsRefPtr<ServiceWorker> ret = mActiveWorker;
- return ret.forget();
-}
-
already_AddRefed<workers::ServiceWorker>
ServiceWorkerContainer::GetController()
{
if (!mControllerWorker) {
nsresult rv;
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
if (!swm) {
return nullptr;
}
nsCOMPtr<nsISupports> serviceWorker;
rv = swm->GetDocumentController(mWindow, getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
- mControllerWorker = static_cast<ServiceWorker*>(serviceWorker.get());
+ mControllerWorker =
+ static_cast<workers::ServiceWorker*>(serviceWorker.get());
}
- nsRefPtr<ServiceWorker> ref = mControllerWorker;
+ nsRefPtr<workers::ServiceWorker> ref = mControllerWorker;
return ref.forget();
}
already_AddRefed<Promise>
-ServiceWorkerContainer::GetAll(ErrorResult& aRv)
+ServiceWorkerContainer::GetRegistrations(ErrorResult& aRv)
+{
+ // FIXME(nsm): Bug 1002571
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+}
+
+already_AddRefed<Promise>
+ServiceWorkerContainer::GetRegistration(const nsAString& aDocumentURL,
+ ErrorResult& aRv)
{
// FIXME(nsm): Bug 1002571
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
already_AddRefed<Promise>
ServiceWorkerContainer::GetReady(ErrorResult& aRv)
{
// FIXME(nsm): Bug 1025077
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
return Promise::Create(global, aRv);
}
-// XXXnsm, maybe this can be optimized to only add when a event handler is
-// registered.
-void
-ServiceWorkerContainer::StartListeningForEvents()
-{
- nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
- if (swm) {
- swm->AddContainerEventListener(mWindow->GetDocumentURI(), this);
- }
-}
-
-void
-ServiceWorkerContainer::StopListeningForEvents()
-{
- nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
- if (swm) {
- swm->RemoveContainerEventListener(mWindow->GetDocumentURI(), this);
- }
-}
-
-void
-ServiceWorkerContainer::InvalidateWorkerReference(WhichServiceWorker aWhichOnes)
-{
- if (aWhichOnes & WhichServiceWorker::INSTALLING_WORKER) {
- mInstallingWorker = nullptr;
- }
-
- if (aWhichOnes & WhichServiceWorker::WAITING_WORKER) {
- mWaitingWorker = nullptr;
- }
-
- if (aWhichOnes & WhichServiceWorker::ACTIVE_WORKER) {
- mActiveWorker = nullptr;
- }
-}
-
-already_AddRefed<workers::ServiceWorker>
-ServiceWorkerContainer::GetWorkerReference(WhichServiceWorker aWhichOne)
-{
- nsresult rv;
- nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
- if (!swm) {
- return nullptr;
- }
-
- nsCOMPtr<nsISupports> serviceWorker;
- switch(aWhichOne) {
- case WhichServiceWorker::INSTALLING_WORKER:
- rv = swm->GetInstalling(mWindow, getter_AddRefs(serviceWorker));
- break;
- case WhichServiceWorker::WAITING_WORKER:
- rv = swm->GetWaiting(mWindow, getter_AddRefs(serviceWorker));
- break;
- case WhichServiceWorker::ACTIVE_WORKER:
- rv = swm->GetActive(mWindow, getter_AddRefs(serviceWorker));
- break;
- default:
- MOZ_CRASH("Invalid enum value");
- }
-
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
-
- nsRefPtr<ServiceWorker> ref = static_cast<ServiceWorker*>(serviceWorker.get());
- return ref.forget();
-}
-
// Testing only.
already_AddRefed<Promise>
ServiceWorkerContainer::ClearAllServiceWorkerData(ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
@@ -266,11 +147,10 @@ ServiceWorkerContainer::GetScopeForUrl(c
void
ServiceWorkerContainer::GetControllingWorkerScriptURLForPath(
const nsAString& aPath,
nsString& aScriptURL,
ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
-} // namespace workers
} // namespace dom
} // namespace mozilla
--- a/dom/workers/ServiceWorkerContainer.h
+++ b/dom/workers/ServiceWorkerContainer.h
@@ -1,41 +1,38 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 mozilla_dom_workers_serviceworkercontainer_h__
-#define mozilla_dom_workers_serviceworkercontainer_h__
+#ifndef mozilla_dom_serviceworkercontainer_h__
+#define mozilla_dom_serviceworkercontainer_h__
#include "mozilla/DOMEventTargetHelper.h"
-#include "ServiceWorkerManager.h"
-
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class Promise;
struct RegistrationOptionList;
namespace workers {
-
class ServiceWorker;
+}
// Lightweight serviceWorker APIs collection.
class ServiceWorkerContainer MOZ_FINAL : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
- IMPL_EVENT_HANDLER(updatefound)
IMPL_EVENT_HANDLER(controllerchange)
IMPL_EVENT_HANDLER(reloadpage)
IMPL_EVENT_HANDLER(error)
explicit ServiceWorkerContainer(nsPIDOMWindow* aWindow);
nsPIDOMWindow*
GetParentObject() const
@@ -46,83 +43,49 @@ public:
JSObject*
WrapObject(JSContext* aCx);
already_AddRefed<Promise>
Register(const nsAString& aScriptURL,
const RegistrationOptionList& aOptions,
ErrorResult& aRv);
- already_AddRefed<Promise>
- Unregister(const nsAString& scope, ErrorResult& aRv);
-
- already_AddRefed<ServiceWorker>
- GetInstalling();
-
- already_AddRefed<ServiceWorker>
- GetWaiting();
-
- already_AddRefed<ServiceWorker>
- GetActive();
-
- already_AddRefed<ServiceWorker>
+ already_AddRefed<workers::ServiceWorker>
GetController();
already_AddRefed<Promise>
- GetAll(ErrorResult& aRv);
+ GetRegistration(const nsAString& aDocumentURL,
+ ErrorResult& aRv);
+
+ already_AddRefed<Promise>
+ GetRegistrations(ErrorResult& aRv);
already_AddRefed<Promise>
GetReady(ErrorResult& aRv);
- nsIURI*
- GetDocumentURI() const
- {
- return mWindow->GetDocumentURI();
- }
-
- void
- InvalidateWorkerReference(WhichServiceWorker aWhichOnes);
-
- already_AddRefed<workers::ServiceWorker>
- GetWorkerReference(WhichServiceWorker aWhichOne);
-
// Testing only.
already_AddRefed<Promise>
ClearAllServiceWorkerData(ErrorResult& aRv);
// Testing only.
void
GetScopeForUrl(const nsAString& aUrl, nsString& aScope, ErrorResult& aRv);
// Testing only.
void
GetControllingWorkerScriptURLForPath(const nsAString& aPath,
nsString& aScriptURL,
ErrorResult& aRv);
private:
~ServiceWorkerContainer();
- void
- StartListeningForEvents();
-
- void
- StopListeningForEvents();
-
nsCOMPtr<nsPIDOMWindow> mWindow;
- // The following properties are cached here to ensure JS equality is satisfied
- // instead of acquiring a new worker instance from the ServiceWorkerManager
- // for every access. A null value is considered a cache miss.
- // These three may change to a new worker at any time.
- nsRefPtr<ServiceWorker> mInstallingWorker;
- nsRefPtr<ServiceWorker> mWaitingWorker;
- nsRefPtr<ServiceWorker> mActiveWorker;
// This only changes when a worker hijacks everything in its scope by calling
// replace().
// FIXME(nsm): Bug 982711. Provide API to let SWM invalidate this.
- nsRefPtr<ServiceWorker> mControllerWorker;
+ nsRefPtr<workers::ServiceWorker> mControllerWorker;
};
-} // namespace workers
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_workers_serviceworkercontainer_h__ */
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -19,29 +19,29 @@
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
#include "nsTArray.h"
#include "RuntimeService.h"
#include "ServiceWorker.h"
-#include "ServiceWorkerContainer.h"
+#include "ServiceWorkerRegistration.h"
#include "ServiceWorkerEvents.h"
#include "WorkerInlines.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"
using namespace mozilla;
using namespace mozilla::dom;
BEGIN_WORKERS_NAMESPACE
-NS_IMPL_ISUPPORTS0(ServiceWorkerRegistration)
+NS_IMPL_ISUPPORTS0(ServiceWorkerRegistrationInfo)
UpdatePromise::UpdatePromise()
: mState(Pending)
{
MOZ_COUNT_CTOR(UpdatePromise);
}
UpdatePromise::~UpdatePromise()
@@ -75,44 +75,52 @@ UpdatePromise::ResolveAllPromises(const
MOZ_ASSERT(go);
AutoSafeJSContext cx;
JS::Rooted<JSObject*> global(cx, go->GetGlobalJSObject());
JSAutoCompartment ac(cx, global);
GlobalObject domGlobal(cx, global);
+ // The service worker is created and kept alive as a SharedWorker.
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv = rs->CreateServiceWorker(domGlobal,
NS_ConvertUTF8toUTF16(aScriptSpec),
aScope,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
pendingPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
continue;
}
- pendingPromise->MaybeResolve(serviceWorker);
+ // Since ServiceWorkerRegistration is only exposed to windows we can be
+ // certain about this cast.
+ nsCOMPtr<nsPIDOMWindow> window =
+ do_QueryInterface(pendingPromise->GetParentObject());
+ nsRefPtr<ServiceWorkerRegistration> swr =
+ new ServiceWorkerRegistration(window, NS_ConvertUTF8toUTF16(aScope));
+
+ pendingPromise->MaybeResolve(swr);
}
}
}
void
UpdatePromise::RejectAllPromises(nsresult aRv)
{
AssertIsOnMainThread();
MOZ_ASSERT(mState == Pending);
mState = Rejected;
nsTArray<WeakPtr<Promise>> array;
array.SwapElements(mPromises);
for (uint32_t i = 0; i < array.Length(); ++i) {
WeakPtr<Promise>& pendingPromise = array.ElementAt(i);
if (pendingPromise) {
- // Since ServiceWorkerContainer is only exposed to windows we can be
+ // Since ServiceWorkerRegistration is only exposed to windows we can be
// certain about this cast.
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(pendingPromise->GetParentObject());
MOZ_ASSERT(window);
nsRefPtr<DOMError> domError = new DOMError(window, aRv);
pendingPromise->MaybeRejectBrokenly(domError);
}
}
@@ -124,17 +132,17 @@ UpdatePromise::RejectAllPromises(const E
MOZ_ASSERT(mState == Pending);
mState = Rejected;
nsTArray<WeakPtr<Promise>> array;
array.SwapElements(mPromises);
for (uint32_t i = 0; i < array.Length(); ++i) {
WeakPtr<Promise>& pendingPromise = array.ElementAt(i);
if (pendingPromise) {
- // Since ServiceWorkerContainer is only exposed to windows we can be
+ // Since ServiceWorkerRegistration is only exposed to windows we can be
// certain about this cast.
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(pendingPromise->GetParentObject());
MOZ_ASSERT(go);
AutoJSAPI jsapi;
jsapi.Init(go);
JSContext* cx = jsapi.cx();
@@ -203,28 +211,28 @@ public:
// Allows newer calls to Update() to 'abort' older calls.
// Each call to Update() creates the instance which handles creating the
// worker and queues up a runnable to resolve the update promise once the
// worker has successfully been parsed.
class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
{
// Owner of this instance.
- ServiceWorkerRegistration* mRegistration;
+ ServiceWorkerRegistrationInfo* mRegistration;
nsCString mScriptSpec;
nsCOMPtr<nsPIDOMWindow> mWindow;
bool mAborted;
~ServiceWorkerUpdateInstance() {}
public:
NS_DECL_ISUPPORTS
- ServiceWorkerUpdateInstance(ServiceWorkerRegistration *aRegistration,
+ ServiceWorkerUpdateInstance(ServiceWorkerRegistrationInfo *aRegistration,
nsPIDOMWindow* aWindow)
: mRegistration(aRegistration),
// Capture the current script spec in case register() gets called.
mScriptSpec(aRegistration->mScriptSpec),
mWindow(aWindow),
mAborted(false)
{
AssertIsOnMainThread();
@@ -292,23 +300,23 @@ NS_IMPL_ISUPPORTS0(ServiceWorkerUpdateIn
NS_IMETHODIMP
FinishFetchOnMainThreadRunnable::Run()
{
AssertIsOnMainThread();
mUpdateInstance->FetchDone();
return NS_OK;
}
-ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
+ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& aScope)
: mControlledDocumentsCounter(0),
mScope(aScope),
mPendingUninstall(false)
{ }
-ServiceWorkerRegistration::~ServiceWorkerRegistration()
+ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
{
MOZ_ASSERT(!IsControllingDocuments());
}
//////////////////////////
// ServiceWorkerManager //
//////////////////////////
@@ -334,17 +342,17 @@ ServiceWorkerManager::~ServiceWorkerMana
mDomainMap.Clear();
}
/* static */ PLDHashOperator
ServiceWorkerManager::CleanupServiceWorkerInformation(const nsACString& aDomain,
ServiceWorkerDomainInfo* aDomainInfo,
void *aUnused)
{
- aDomainInfo->mServiceWorkerRegistrations.Clear();
+ aDomainInfo->mServiceWorkerRegistrationInfos.Clear();
return PL_DHASH_NEXT;
}
/*
* Implements the async aspects of the register algorithm.
*/
class RegisterRunnable : public nsRunnable
{
@@ -371,17 +379,17 @@ public:
mPromise->MaybeReject(rv);
return NS_OK;
}
domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
swm->mDomainMap.Put(domain, domainInfo);
}
- nsRefPtr<ServiceWorkerRegistration> registration =
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration =
domainInfo->GetRegistration(mScope);
nsCString spec;
nsresult rv = mScriptURI->GetSpec(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPromise->MaybeReject(rv);
return NS_OK;
}
@@ -407,17 +415,21 @@ public:
info->GetScriptSpec(),
registration->mScope,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
- mPromise->MaybeResolve(serviceWorker);
+ nsRefPtr<ServiceWorkerRegistration> swr =
+ new ServiceWorkerRegistration(mWindow,
+ NS_ConvertUTF8toUTF16(registration->mScope));
+
+ mPromise->MaybeResolve(swr);
return NS_OK;
}
}
} else {
registration = domainInfo->CreateNewRegistration(mScope);
}
registration->mScriptSpec = spec;
@@ -523,41 +535,41 @@ ServiceWorkerManager::Register(nsIDOMWin
nsRefPtr<nsIRunnable> registerRunnable =
new RegisterRunnable(window, cleanedScope, scriptURI, promise);
promise.forget(aPromise);
return NS_DispatchToCurrentThread(registerRunnable);
}
void
-ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
nsresult aRv)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration->HasUpdatePromise());
aRegistration->mUpdatePromise->RejectAllPromises(aRv);
aRegistration->mUpdatePromise = nullptr;
}
void
-ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
const ErrorEventInit& aErrorDesc)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration->HasUpdatePromise());
aRegistration->mUpdatePromise->RejectAllPromises(aErrorDesc);
aRegistration->mUpdatePromise = nullptr;
}
/*
* Update() does not return the Promise that the spec says it should. Callers
* may access the registration's (new) Promise after calling this method.
*/
NS_IMETHODIMP
-ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::Update(ServiceWorkerRegistrationInfo* aRegistration,
nsPIDOMWindow* aWindow)
{
if (aRegistration->HasUpdatePromise()) {
NS_WARNING("Already had a UpdatePromise. Aborting that one!");
RejectUpdatePromiseObservers(aRegistration, NS_ERROR_DOM_ABORT_ERR);
MOZ_ASSERT(aRegistration->mUpdateInstance);
aRegistration->mUpdateInstance->Abort();
aRegistration->mUpdateInstance = nullptr;
@@ -566,33 +578,33 @@ ServiceWorkerManager::Update(ServiceWork
if (aRegistration->mInstallingWorker) {
// FIXME(nsm): Terminate the worker. We still haven't figured out worker
// instance ownership when not associated with a window, so let's wait on
// this.
// FIXME(nsm): We should be setting the state on the actual worker
// instance.
// FIXME(nsm): Fire "statechange" on installing worker instance.
aRegistration->mInstallingWorker = nullptr;
- InvalidateServiceWorkerContainerWorker(aRegistration,
- WhichServiceWorker::INSTALLING_WORKER);
+ InvalidateServiceWorkerRegistrationWorker(aRegistration,
+ WhichServiceWorker::INSTALLING_WORKER);
}
aRegistration->mUpdatePromise = new UpdatePromise();
// FIXME(nsm): Bug 931249. If we don't need to fetch & install, resolve
// promise and skip this.
// FIXME(nsm): Bug 931249. Force cache update if > 1 day.
aRegistration->mUpdateInstance =
new ServiceWorkerUpdateInstance(aRegistration, aWindow);
aRegistration->mUpdateInstance->Update();
return NS_OK;
}
-// If we return an error, ServiceWorkerContainer will reject the Promise.
+// If we return an error, ServiceWorkerREgistration will reject the Promise.
NS_IMETHODIMP
ServiceWorkerManager::Unregister(nsIDOMWindow* aWindow, const nsAString& aScope,
nsISupports** aPromise)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
// XXXnsm Don't allow chrome callers for now.
@@ -608,34 +620,34 @@ already_AddRefed<ServiceWorkerManager>
ServiceWorkerManager::GetInstance()
{
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
nsRefPtr<ServiceWorkerManager> concrete = do_QueryObject(swm);
return concrete.forget();
}
void
-ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistrationInfo* aRegistration,
const nsACString& aWorkerScriptSpec)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration->HasUpdatePromise());
if (aRegistration->mUpdatePromise->IsRejected()) {
aRegistration->mUpdatePromise = nullptr;
return;
}
aRegistration->mUpdatePromise->ResolveAllPromises(aWorkerScriptSpec,
aRegistration->mScope);
aRegistration->mUpdatePromise = nullptr;
}
// Must NS_Free() aString
void
-ServiceWorkerManager::FinishFetch(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::FinishFetch(ServiceWorkerRegistrationInfo* aRegistration,
nsPIDOMWindow* aWindow)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration->HasUpdatePromise());
MOZ_ASSERT(aRegistration->mUpdateInstance);
aRegistration->mUpdateInstance = nullptr;
if (aRegistration->mUpdatePromise->IsRejected()) {
@@ -683,17 +695,17 @@ ServiceWorkerManager::HandleError(JSCont
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(uri);
if (!domainInfo) {
return;
}
nsCString scope;
scope.Assign(aScope);
- nsRefPtr<ServiceWorkerRegistration> registration = domainInfo->GetRegistration(scope);
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration = domainInfo->GetRegistration(scope);
MOZ_ASSERT(registration);
RootedDictionary<ErrorEventInit> init(aCx);
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
init.mColno = aColumnNumber;
@@ -712,21 +724,21 @@ ServiceWorkerManager::HandleError(JSCont
registration->mUpdateInstance = nullptr;
} else {
// FIXME(nsm): Bug 983497 Fire 'error' on ServiceWorkerContainers.
}
}
class FinishInstallRunnable MOZ_FINAL : public nsRunnable
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
explicit FinishInstallRunnable(
- const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
NS_IMETHOD
Run() MOZ_OVERRIDE
{
@@ -735,20 +747,20 @@ public:
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->FinishInstall(mRegistration.get());
return NS_OK;
}
};
class FinishActivationRunnable : public nsRunnable
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
- FinishActivationRunnable(const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ FinishActivationRunnable(const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
NS_IMETHODIMP
Run()
{
@@ -758,53 +770,53 @@ public:
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->FinishActivate(mRegistration.get());
return NS_OK;
}
};
class CancelServiceWorkerInstallationRunnable MOZ_FINAL : public nsRunnable
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
explicit CancelServiceWorkerInstallationRunnable(
- const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
}
NS_IMETHOD
Run() MOZ_OVERRIDE
{
AssertIsOnMainThread();
// FIXME(nsm): Change installing worker state to redundant.
// FIXME(nsm): Fire statechange.
mRegistration->mInstallingWorker = nullptr;
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
- swm->InvalidateServiceWorkerContainerWorker(mRegistration,
- WhichServiceWorker::INSTALLING_WORKER);
+ swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
+ WhichServiceWorker::INSTALLING_WORKER);
return NS_OK;
}
};
/*
* Used to handle InstallEvent::waitUntil() and proceed with installation.
*/
class FinishInstallHandler MOZ_FINAL : public PromiseNativeHandler
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
virtual
~FinishInstallHandler()
{ }
public:
explicit FinishInstallHandler(
- const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) MOZ_OVERRIDE
{
@@ -822,20 +834,20 @@ public:
nsRefPtr<CancelServiceWorkerInstallationRunnable> r =
new CancelServiceWorkerInstallationRunnable(mRegistration);
NS_DispatchToMainThread(r);
}
};
class FinishActivateHandler : public PromiseNativeHandler
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
- FinishActivateHandler(const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ FinishActivateHandler(const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
virtual
~FinishActivateHandler()
{ }
@@ -861,23 +873,23 @@ public:
/*
* Fires 'install' event on the ServiceWorkerGlobalScope. Modifies busy count
* since it fires the event. This is ok since there can't be nested
* ServiceWorkers, so the parent thread -> worker thread requirement for
* runnables is satisfied.
*/
class InstallEventRunnable MOZ_FINAL : public WorkerRunnable
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
nsCString mScope;
public:
InstallEventRunnable(
WorkerPrivate* aWorkerPrivate,
- const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mRegistration(aRegistration),
mScope(aRegistration.get()->mScope) // copied for access on worker thread.
{
AssertIsOnMainThread();
MOZ_ASSERT(aWorkerPrivate);
}
@@ -930,21 +942,21 @@ private:
new FinishInstallHandler(mRegistration);
waitUntilPromise->AppendNativeHandler(handler);
return true;
}
};
class ActivateEventRunnable : public WorkerRunnable
{
- nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
ActivateEventRunnable(WorkerPrivate* aWorkerPrivate,
- const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
+ const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mRegistration(aRegistration)
{
MOZ_ASSERT(aWorkerPrivate);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
@@ -993,27 +1005,27 @@ private:
nsRefPtr<FinishActivateHandler> handler = new FinishActivateHandler(mRegistration);
waitUntilPromise->AppendNativeHandler(handler);
return true;
}
};
void
-ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::Install(ServiceWorkerRegistrationInfo* aRegistration,
ServiceWorkerInfo* aServiceWorkerInfo)
{
AssertIsOnMainThread();
aRegistration->mInstallingWorker = aServiceWorkerInfo;
MOZ_ASSERT(aRegistration->mInstallingWorker);
- InvalidateServiceWorkerContainerWorker(aRegistration,
- WhichServiceWorker::INSTALLING_WORKER);
+ InvalidateServiceWorkerRegistrationWorker(aRegistration,
+ WhichServiceWorker::INSTALLING_WORKER);
- nsMainThreadPtrHandle<ServiceWorkerRegistration> handle(
- new nsMainThreadPtrHolder<ServiceWorkerRegistration>(aRegistration));
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> handle(
+ new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(aRegistration));
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv =
CreateServiceWorker(aServiceWorkerInfo->GetScriptSpec(),
aRegistration->mScope,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1037,74 +1049,74 @@ ServiceWorkerManager::Install(ServiceWor
// the event dispatch. On the other hand, networking, IDB and so on do keep
// the worker alive, so the waitUntil() is only relevant if the Promise is
// gated on those actions. I (nsm) am not sure if it is worth requiring
// a special spec mention saying the install event should keep the worker
// alive indefinitely purely on the basis of calling waitUntil(), since
// a wait is likely to be required only when performing networking or storage
// transactions in the first place.
- FireEventOnServiceWorkerContainers(aRegistration,
- NS_LITERAL_STRING("updatefound"));
+ FireEventOnServiceWorkerRegistrations(aRegistration,
+ NS_LITERAL_STRING("updatefound"));
}
class ActivationRunnable : public nsRunnable
{
- nsRefPtr<ServiceWorkerRegistration> mRegistration;
+ nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
public:
- explicit ActivationRunnable(ServiceWorkerRegistration* aRegistration)
+ explicit ActivationRunnable(ServiceWorkerRegistrationInfo* aRegistration)
: mRegistration(aRegistration)
{
}
NS_IMETHODIMP
Run() MOZ_OVERRIDE
{
if (mRegistration->mCurrentWorker) {
// FIXME(nsm). Steps 3.1-3.4 of the algorithm.
}
mRegistration->mCurrentWorker = mRegistration->mWaitingWorker.forget();
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
- swm->InvalidateServiceWorkerContainerWorker(mRegistration,
- WhichServiceWorker::ACTIVE_WORKER | WhichServiceWorker::WAITING_WORKER);
+ swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
+ WhichServiceWorker::ACTIVE_WORKER | WhichServiceWorker::WAITING_WORKER);
// FIXME(nsm): Steps 7 of the algorithm.
- swm->FireEventOnServiceWorkerContainers(mRegistration,
- NS_LITERAL_STRING("controllerchange"));
+ swm->FireEventOnServiceWorkerRegistrations(mRegistration,
+ NS_LITERAL_STRING("controllerchange"));
MOZ_ASSERT(mRegistration->mCurrentWorker);
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv =
swm->CreateServiceWorker(mRegistration->mCurrentWorker->GetScriptSpec(),
mRegistration->mScope,
getter_AddRefs(serviceWorker));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- nsMainThreadPtrHandle<ServiceWorkerRegistration> handle(
- new nsMainThreadPtrHolder<ServiceWorkerRegistration>(mRegistration));
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> handle(
+ new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(mRegistration));
nsRefPtr<ActivateEventRunnable> r =
new ActivateEventRunnable(serviceWorker->GetWorkerPrivate(), handle);
AutoSafeJSContext cx;
if (!r->Dispatch(cx)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
};
void
-ServiceWorkerManager::FinishInstall(ServiceWorkerRegistration* aRegistration)
+ServiceWorkerManager::FinishInstall(ServiceWorkerRegistrationInfo* aRegistration)
{
AssertIsOnMainThread();
if (aRegistration->mWaitingWorker) {
// FIXME(nsm): Actually update the state of active ServiceWorker instances.
}
if (!aRegistration->mInstallingWorker) {
@@ -1113,18 +1125,18 @@ ServiceWorkerManager::FinishInstall(Serv
// a different script leading to [[Update]] terminating the
// installingWorker and setting it to null. The FinishInstallRunnable may
// already have been dispatched, hence the check.
return;
}
aRegistration->mWaitingWorker = aRegistration->mInstallingWorker.forget();
MOZ_ASSERT(aRegistration->mWaitingWorker);
- InvalidateServiceWorkerContainerWorker(aRegistration,
- WhichServiceWorker::WAITING_WORKER | WhichServiceWorker::INSTALLING_WORKER);
+ InvalidateServiceWorkerRegistrationWorker(aRegistration,
+ WhichServiceWorker::WAITING_WORKER | WhichServiceWorker::INSTALLING_WORKER);
// FIXME(nsm): Actually update state of active ServiceWorker instances to
// installed.
// FIXME(nsm): Fire statechange on the instances.
// FIXME(nsm): Handle replace().
if (!aRegistration->IsControllingDocuments()) {
@@ -1135,17 +1147,17 @@ ServiceWorkerManager::FinishInstall(Serv
if (NS_WARN_IF(NS_FAILED(rv))) {
// FIXME(nsm): Handle error.
// How likely is this to happen and can we really do anything about it?
}
}
}
void
-ServiceWorkerManager::FinishActivate(ServiceWorkerRegistration* aRegistration)
+ServiceWorkerManager::FinishActivate(ServiceWorkerRegistrationInfo* aRegistration)
{
// FIXME(nsm): Set aRegistration->mCurrentWorker state to activated.
// Fire statechange.
}
NS_IMETHODIMP
ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
const nsACString& aScriptSpec,
@@ -1173,32 +1185,32 @@ ServiceWorkerManager::CreateServiceWorke
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
serviceWorker.forget(aServiceWorker);
return rv;
}
-already_AddRefed<ServiceWorkerRegistration>
-ServiceWorkerManager::GetServiceWorkerRegistration(nsPIDOMWindow* aWindow)
+already_AddRefed<ServiceWorkerRegistrationInfo>
+ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsPIDOMWindow* aWindow)
{
nsCOMPtr<nsIDocument> document = aWindow->GetExtantDoc();
- return GetServiceWorkerRegistration(document);
+ return GetServiceWorkerRegistrationInfo(document);
}
-already_AddRefed<ServiceWorkerRegistration>
-ServiceWorkerManager::GetServiceWorkerRegistration(nsIDocument* aDoc)
+already_AddRefed<ServiceWorkerRegistrationInfo>
+ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIDocument* aDoc)
{
nsCOMPtr<nsIURI> documentURI = aDoc->GetDocumentURI();
- return GetServiceWorkerRegistration(documentURI);
+ return GetServiceWorkerRegistrationInfo(documentURI);
}
-already_AddRefed<ServiceWorkerRegistration>
-ServiceWorkerManager::GetServiceWorkerRegistration(nsIURI* aURI)
+already_AddRefed<ServiceWorkerRegistrationInfo>
+ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIURI* aURI)
{
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aURI);
if (!domainInfo) {
return nullptr;
}
nsCString spec;
nsresult rv = aURI->GetSpec(spec);
@@ -1206,18 +1218,18 @@ ServiceWorkerManager::GetServiceWorkerRe
return nullptr;
}
nsCString scope = FindScopeForPath(domainInfo->mOrderedScopes, spec);
if (scope.IsEmpty()) {
return nullptr;
}
- nsRefPtr<ServiceWorkerRegistration> registration;
- domainInfo->mServiceWorkerRegistrations.Get(scope, getter_AddRefs(registration));
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration;
+ domainInfo->mServiceWorkerRegistrationInfos.Get(scope, getter_AddRefs(registration));
// ordered scopes and registrations better be in sync.
MOZ_ASSERT(registration);
return registration.forget();
}
namespace {
/*
@@ -1352,18 +1364,18 @@ ServiceWorkerManager::MaybeStartControll
return;
}
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDoc);
if (!domainInfo) {
return;
}
- nsRefPtr<ServiceWorkerRegistration> registration =
- GetServiceWorkerRegistration(aDoc);
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration =
+ GetServiceWorkerRegistrationInfo(aDoc);
if (registration && registration->mCurrentWorker) {
MOZ_ASSERT(!domainInfo->mControlledDocuments.Contains(aDoc));
registration->StartControllingADocument();
// Use the already_AddRefed<> form of Put to avoid the addref-deref since
// we don't need the registration pointer in this function anymore.
domainInfo->mControlledDocuments.Put(aDoc, registration.forget());
}
}
@@ -1376,17 +1388,17 @@ ServiceWorkerManager::MaybeStopControlli
return;
}
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDoc);
if (!domainInfo) {
return;
}
- nsRefPtr<ServiceWorkerRegistration> registration;
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration;
domainInfo->mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
// A document which was uncontrolled does not maintain that state itself, so
// it will always call MaybeStopControlling() even if there isn't an
// associated registration. So this check is required.
if (registration) {
registration->StopControllingADocument();
}
}
@@ -1395,75 +1407,76 @@ NS_IMETHODIMP
ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
{
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
- nsRefPtr<ServiceWorkerRegistration> r = GetServiceWorkerRegistration(uri);
+ nsRefPtr<ServiceWorkerRegistrationInfo> r = GetServiceWorkerRegistrationInfo(uri);
if (!r) {
return NS_ERROR_FAILURE;
}
aScope = NS_ConvertUTF8toUTF16(r->mScope);
return NS_OK;
}
NS_IMETHODIMP
-ServiceWorkerManager::AddContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
+ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
{
MOZ_ASSERT(aDocumentURI);
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
if (!domainInfo) {
nsCString domain;
nsresult rv = aDocumentURI->GetHost(domain);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
domainInfo = new ServiceWorkerDomainInfo;
mDomainMap.Put(domain, domainInfo);
}
MOZ_ASSERT(domainInfo);
- ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
- domainInfo->mServiceWorkerContainers.AppendElement(container);
+ // TODO: this is very very bad:
+ ServiceWorkerRegistration* registration = static_cast<ServiceWorkerRegistration*>(aListener);
+ domainInfo->mServiceWorkerRegistrations.AppendElement(registration);
return NS_OK;
}
NS_IMETHODIMP
-ServiceWorkerManager::RemoveContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
+ServiceWorkerManager::RemoveRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
{
MOZ_ASSERT(aDocumentURI);
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
if (!domainInfo) {
return NS_OK;
}
- ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
- domainInfo->mServiceWorkerContainers.RemoveElement(container);
+ ServiceWorkerRegistration* registration = static_cast<ServiceWorkerRegistration*>(aListener);
+ domainInfo->mServiceWorkerRegistrations.RemoveElement(registration);
return NS_OK;
}
void
-ServiceWorkerManager::FireEventOnServiceWorkerContainers(
- ServiceWorkerRegistration* aRegistration,
+ServiceWorkerManager::FireEventOnServiceWorkerRegistrations(
+ ServiceWorkerRegistrationInfo* aRegistration,
const nsAString& aName)
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerDomainInfo> domainInfo =
GetDomainInfo(aRegistration->mScriptSpec);
if (domainInfo) {
- nsTObserverArray<ServiceWorkerContainer*>::ForwardIterator it(domainInfo->mServiceWorkerContainers);
+ nsTObserverArray<ServiceWorkerRegistration*>::ForwardIterator it(domainInfo->mServiceWorkerRegistrations);
while (it.HasMore()) {
- nsRefPtr<ServiceWorkerContainer> target = it.GetNext();
+ nsRefPtr<ServiceWorkerRegistration> target = it.GetNext();
nsIURI* targetURI = target->GetDocumentURI();
if (!targetURI) {
NS_WARNING("Controlled domain cannot have page with null URI!");
continue;
}
nsCString path;
nsresult rv = targetURI->GetSpec(path);
@@ -1489,18 +1502,18 @@ ServiceWorkerManager::FireEventOnService
NS_IMETHODIMP
ServiceWorkerManager::GetServiceWorkerForWindow(nsIDOMWindow* aWindow,
WhichServiceWorker aWhichWorker,
nsISupports** aServiceWorker)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
MOZ_ASSERT(window);
- nsRefPtr<ServiceWorkerRegistration> registration =
- GetServiceWorkerRegistration(window);
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration =
+ GetServiceWorkerRegistrationInfo(window);
if (!registration) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ServiceWorkerInfo> info;
if (aWhichWorker == WhichServiceWorker::INSTALLING_WORKER) {
info = registration->mInstallingWorker;
@@ -1544,17 +1557,17 @@ ServiceWorkerManager::GetDocumentControl
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(doc);
if (!domainInfo) {
return NS_ERROR_FAILURE;
}
- nsRefPtr<ServiceWorkerRegistration> registration;
+ nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!domainInfo->mControlledDocuments.Get(doc, getter_AddRefs(registration))) {
return NS_ERROR_FAILURE;
}
// If the document is controlled, the current worker MUST be non-null.
MOZ_ASSERT(registration->mCurrentWorker);
nsRefPtr<ServiceWorker> serviceWorker;
@@ -1610,17 +1623,17 @@ ServiceWorkerManager::CreateServiceWorke
rv = info.mBaseURI->GetHost(info.mDomain);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// FIXME(nsm): Create correct principal based on app-ness.
// Would it make sense to store the nsIPrincipal of the first register() in
- // the ServiceWorkerRegistration and use that?
+ // the ServiceWorkerRegistrationInfo and use that?
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
rv = ssm->GetNoAppCodebasePrincipal(info.mBaseURI, getter_AddRefs(info.mPrincipal));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
AutoSafeJSContext cx;
@@ -1637,27 +1650,27 @@ ServiceWorkerManager::CreateServiceWorke
return rv;
}
serviceWorker.forget(aServiceWorker);
return NS_OK;
}
void
-ServiceWorkerManager::InvalidateServiceWorkerContainerWorker(ServiceWorkerRegistration* aRegistration,
- WhichServiceWorker aWhichOnes)
+ServiceWorkerManager::InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
+ WhichServiceWorker aWhichOnes)
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerDomainInfo> domainInfo =
GetDomainInfo(aRegistration->mScriptSpec);
if (domainInfo) {
- nsTObserverArray<ServiceWorkerContainer*>::ForwardIterator it(domainInfo->mServiceWorkerContainers);
+ nsTObserverArray<ServiceWorkerRegistration*>::ForwardIterator it(domainInfo->mServiceWorkerRegistrations);
while (it.HasMore()) {
- nsRefPtr<ServiceWorkerContainer> target = it.GetNext();
+ nsRefPtr<ServiceWorkerRegistration> target = it.GetNext();
nsIURI* targetURI = target->GetDocumentURI();
nsCString path;
nsresult rv = targetURI->GetSpec(path);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
--- a/dom/workers/ServiceWorkerManager.h
+++ b/dom/workers/ServiceWorkerManager.h
@@ -11,28 +11,31 @@
#include "mozilla/Attributes.h"
#include "mozilla/LinkedList.h"