Merge latest green fx-team changeset and mozilla-central

This commit is contained in:
Ed Morley 2014-03-03 14:48:02 +00:00
commit 031fb4f43b
246 changed files with 3796 additions and 2166 deletions

View File

@ -186,7 +186,8 @@ pref("privacy.item.siteSettings", true);
pref("privacy.item.syncAccount", true);
// base url for the wifi geolocation network provider
pref("geo.wifi.uri", "https://maps.googleapis.com/maps/api/browserlocation/json");
pref("geo.provider.use_mls", false);
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
// enable geo
pref("geo.enabled", true);

View File

@ -19,7 +19,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -17,7 +17,7 @@
</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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b2f773d8320d30648b89767dfe5b25ef94bc7e62"/>

View File

@ -19,7 +19,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -4,6 +4,6 @@
"branch": "",
"revision": ""
},
"revision": "d0ed050535c3a5337c09c0de720de78954a42f31",
"revision": "3d294ffa51afd8a8daafcdaa97cda8e38de81cb8",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
@ -96,7 +96,7 @@
<project name="platform/system/netd" path="system/netd" revision="2e226e6e636ca0a8cc4c51093e46f4baba1ffcce"/>
<project name="platform/system/vold" path="system/vold" revision="8ac5eef8ea3a456b96d52ce2091bf6d814782d8c"/>
<!-- hamachi specific things -->
<project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="6d90df25658d59dfcfd34f83e74e75c3af3901af"/>
<project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="901e2607afb2518d1666846bbcf572e65cd93bf4"/>
<project name="quic/lf/b2g/external/jsmin" path="external/jsmin" revision="cec896f0affaa0226c02605ad28d42df1bc0e393"/>
<project name="device/qcom/common" path="device/qcom/common" revision="d13aaf080177b7c48f243d51827db5c7a7873cd0"/>
<project name="platform/vendor/qcom/msm7627a" path="device/qcom/msm7627a" revision="f06bcacc6f13cec895dc5d4c2385c076396194ec"/>

View File

@ -15,7 +15,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -19,7 +19,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -17,7 +17,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -17,7 +17,7 @@
</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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b2f773d8320d30648b89767dfe5b25ef94bc7e62"/>

View File

@ -17,7 +17,7 @@
<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="a980b8f54956ed470667033630b02492efdf4a07"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -375,6 +375,8 @@
@BINPATH@/components/nsLoginInfo.js
@BINPATH@/components/nsLoginManager.js
@BINPATH@/components/nsLoginManagerPrompter.js
@BINPATH@/components/NetworkGeolocationProvider.manifest
@BINPATH@/components/NetworkGeolocationProvider.js
#ifdef MOZ_WEBRTC
@BINPATH@/components/PeerConnection.js
@BINPATH@/components/PeerConnection.manifest

View File

@ -2998,10 +2998,9 @@
gContextMenuContentData = { event: aMessage.objects.event,
browser: browser };
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
popup.openPopup(browser, "overlap",
gContextMenuContentData.event.clientX,
gContextMenuContentData.event.clientY,
true, false, null);
let event = gContextMenuContentData.event;
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
popup.openPopupAtScreen(pos.x, pos.y, true);
break;
}
case "DOMWebNotificationClicked": {
@ -3998,6 +3997,10 @@
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerDocument.defaultView))
return dt.effectAllowed = "none";
if (window.gMultiProcessBrowser !=
sourceNode.ownerDocument.defaultView.gMultiProcessBrowser)
return dt.effectAllowed = "none";
#ifdef XP_MACOSX
return dt.effectAllowed = event.altKey ? "copy" : "move";
#else

View File

@ -16,6 +16,7 @@ support-files =
browser_clearplugindata.html
browser_clearplugindata_noage.html
browser_registerProtocolHandler_notification.html
browser_star_hsts.sjs
browser_tab_dragdrop2_frame1.xul
bug564387.html
bug564387_video1.ogv
@ -321,6 +322,7 @@ skip-if = os == "linux" # bug 857427
[browser_save_video.js]
[browser_scope.js]
[browser_selectTabAtIndex.js]
[browser_star_hsts.js]
[browser_subframe_favicons_not_used.js]
[browser_tabDrop.js]
[browser_tabMatchesInAwesomebar_perwindowpb.js]

View File

@ -0,0 +1,114 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
let secureURL = "https://example.com/browser/browser/base/content/test/general/browser_star_hsts.sjs";
let unsecureURL = "http://example.com/browser/browser/base/content/test/general/browser_star_hsts.sjs";
add_task(function* test_star_redirect() {
registerCleanupFunction(function() {
// Ensure to remove example.com from the HSTS list.
let sss = Cc["@mozilla.org/ssservice;1"]
.getService(Ci.nsISiteSecurityService);
sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS,
NetUtil.newURI("http://example.com/"), 0);
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
gBrowser.removeCurrentTab();
});
let tab = gBrowser.selectedTab = gBrowser.addTab();
// This will add the page to the HSTS cache.
yield promiseTabLoadEvent(tab, secureURL, secureURL);
// This should transparently be redirected to the secure page.
yield promiseTabLoadEvent(tab, unsecureURL, secureURL);
yield promiseStarState(BookmarkingUI.STATUS_UNSTARRED);
let promiseBookmark = promiseOnItemAdded(gBrowser.currentURI);
BookmarkingUI.star.click();
// This resolves on the next tick, so the star should have already been
// updated at that point.
yield promiseBookmark;
is(BookmarkingUI.status, BookmarkingUI.STATUS_STARRED, "The star is starred");
});
/**
* Waits for the star to reflect the expected state.
*/
function promiseStarState(aValue) {
let deferred = Promise.defer();
let expectedStatus = aValue ? BookmarkingUI.STATUS_STARRED
: BookmarkingUI.STATUS_UNSTARRED;
(function checkState() {
if (BookmarkingUI.status == BookmarkingUI.STATUS_UPDATING ||
BookmarkingUI.status != expectedStatus) {
info("Waiting for star button change.");
setTimeout(checkState, 1000);
} else {
deferred.resolve();
}
})();
return deferred.promise;
}
/**
* Starts a load in an existing tab and waits for it to finish (via some event).
*
* @param aTab
* The tab to load into.
* @param aUrl
* The url to load.
* @param [optional] aFinalURL
* The url to wait for, same as aURL if not defined.
* @return {Promise} resolved when the event is handled.
*/
function promiseTabLoadEvent(aTab, aURL, aFinalURL)
{
if (!aFinalURL)
aFinalURL = aURL;
let deferred = Promise.defer();
info("Wait for load tab event");
aTab.linkedBrowser.addEventListener("load", function load(event) {
if (event.originalTarget != aTab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank" ||
event.target.location.href != aFinalURL) {
info("skipping spurious load event");
return;
}
aTab.linkedBrowser.removeEventListener("load", load, true);
info("Tab load event received");
deferred.resolve();
}, true, true);
aTab.linkedBrowser.loadURI(aURL);
return deferred.promise;
}
/**
* Waits for a bookmark to be added for the given uri.
*/
function promiseOnItemAdded(aExpectedURI) {
let defer = Promise.defer();
let bookmarksObserver = {
onItemAdded: function (aItemId, aFolderId, aIndex, aItemType, aURI) {
info("Added a bookmark to " + aURI.spec);
PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
if (aURI.equals(aExpectedURI))
defer.resolve();
else
defer.reject(new Error("Added an unexpected bookmark"));
},
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onItemRemoved: function () {},
onItemChanged: function () {},
onItemVisited: function () {},
onItemMoved: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavBookmarkObserver,
])
};
info("Waiting for a bookmark to be added");
PlacesUtils.bookmarks.addObserver(bookmarksObserver, false);
return defer.promise;
}

View File

@ -0,0 +1,13 @@
/* 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/. */
function handleRequest(request, response)
{
let page = "<!DOCTYPE html><html><body><p>HSTS page</p></body></html>";
response.setStatusLine(request.httpVersion, "200", "OK");
response.setHeader("Strict-Transport-Security", "max-age=60");
response.setHeader("Content-Type", "text/html", false);
response.setHeader("Content-Length", page.length + "", false);
response.write(page);
}

View File

@ -841,7 +841,7 @@ OBJ_SUFFIX := $(_OBJ_SUFFIX)
# PGO builds with GCC build objects with instrumentation in a first pass,
# then objects optimized, without instrumentation, in a second pass. If
# we overwrite the ojects from the first pass with those from the second,
# we overwrite the objects from the first pass with those from the second,
# we end up not getting instrumentation data for better optimization on
# incremental builds. As a consequence, we use a different object suffix
# for the first pass.

View File

@ -60,7 +60,7 @@ dnl ========================================================
GLIB_VERSION=1.2.0
PERL_VERSION=5.006
CAIRO_VERSION=1.10
PANGO_VERSION=1.14.0
PANGO_VERSION=1.22.0
GTK2_VERSION=2.10.0
GTK3_VERSION=3.0.0
WINDRES_VERSION=2.14.90
@ -251,10 +251,13 @@ if test -n "$gonkdir" ; then
19)
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
MOZ_B2G_CAMERA=1
MOZ_OMX_DECODER=1
MOZ_B2G_BT=1
MOZ_B2G_BT_BLUEDROID=1
MOZ_NFC=1
MOZ_RTSP=1
MOZ_OMX_DECODER=1
MOZ_OMX_ENCODER=1
AC_DEFINE(MOZ_OMX_ENCODER)
;;
*)
@ -4050,6 +4053,16 @@ fi
AC_DEFINE_UNQUOTED(MOZ_UPDATE_CHANNEL, $MOZ_UPDATE_CHANNEL)
AC_SUBST(MOZ_UPDATE_CHANNEL)
# Allow to specify a Mozilla API key file that contains the secret key to be
# used for various Mozilla API requests.
MOZ_ARG_WITH_STRING(mozilla-api-keyfile,
[ --with-mozilla-api-keyfile=file Use the secret key contained in the given keyfile for Mozilla API requests],
MOZ_MOZILLA_API_KEY=`cat $withval`)
if test -z "$MOZ_MOZILLA_API_KEY"; then
MOZ_MOZILLA_API_KEY=no-mozilla-api-key
fi
AC_SUBST(MOZ_MOZILLA_API_KEY)
# Allow to specify a Google API key file that contains the secret key to be
# used for various Google API requests.
MOZ_ARG_WITH_STRING(google-api-keyfile,

View File

@ -963,7 +963,7 @@ TransferZoomLevels(nsIDocument* aFromDoc,
return;
toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
toCtxt->SetMinFontSize(fromCtxt->MinFontSize(nullptr));
toCtxt->SetBaseMinFontSize(fromCtxt->BaseMinFontSize());
toCtxt->SetTextZoom(fromCtxt->TextZoom());
}

View File

@ -508,8 +508,16 @@ WebGLContext::CopyTexImage2D(GLenum target,
return;
}
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
return ErrorInvalidOperation("copyTexImage2D: Read source attachment doesn't have the"
" correct color/depth/stencil type.");
}
}
bool texFormatRequiresAlpha = internalformat == LOCAL_GL_RGBA ||
internalformat == LOCAL_GL_ALPHA ||
@ -613,10 +621,17 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
}
if (mBoundFramebuffer)
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
return ErrorInvalidOperation("copyTexSubImage2D: Read source attachment doesn't have the"
" correct color/depth/stencil type.");
}
}
bool texFormatRequiresAlpha = (internalFormat == LOCAL_GL_RGBA ||
internalFormat == LOCAL_GL_ALPHA ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA);
@ -2307,6 +2322,12 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
return ErrorInvalidFramebufferOperation("readPixels: incomplete framebuffer");
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
return ErrorInvalidOperation("readPixels: Read source attachment doesn't have the"
" correct color/depth/stencil type.");
}
}
// Now that the errors are out of the way, on to actually reading

View File

@ -630,6 +630,31 @@ WebGLFramebuffer::CheckFramebufferStatus() const
return mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
}
bool
WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
{
if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
return false;
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
bool hasPlanes = true;
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
hasPlanes &= ColorAttachmentCount() &&
ColorAttachment(0).IsDefined();
}
if (mask & LOCAL_GL_DEPTH_BUFFER_BIT) {
hasPlanes &= DepthAttachment().IsDefined() ||
DepthStencilAttachment().IsDefined();
}
if (mask & LOCAL_GL_STENCIL_BUFFER_BIT) {
hasPlanes &= StencilAttachment().IsDefined() ||
DepthStencilAttachment().IsDefined();
}
return hasPlanes;
}
bool
WebGLFramebuffer::CheckAndInitializeAttachments()

View File

@ -166,6 +166,9 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
// mask mirrors glClear.
bool HasCompletePlanes(GLbitfield mask);
bool CheckAndInitializeAttachments();
bool CheckColorAttachmentNumber(GLenum attachment, const char* functionName) const;

View File

@ -3,6 +3,7 @@ support-files =
driver-info.js
webgl-util.js
[test_depth_readpixels.html]
[test_highp_fs.html]
[test_no_arr_points.html]
[test_privileged_exts.html]

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL test: Check for error on ReadPixels from a depth-only FB.</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
<script src="driver-info.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
"use strict";
(function() {
var gl = WebGLUtil.getWebGL('c');
if (!gl) {
todo(gl, 'Get GL working here first.');
return;
}
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 4, 4);
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER, rb);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
todo(false, 'Depth-only FB incomplete. This is valid.');
return;
}
ok(!gl.getError(), 'Should have no errors after constructing FB.');
var pixels = new Uint8Array([1, 2, 3, 4]);
gl.readPixels(0, 0, // x,y
1, 1, // w,h
gl.RGBA, gl.UNSIGNED_BYTE, pixels);
ok(gl.getError() == gl.INVALID_OPERATION,
'1x1 color read from a depth FB should generated INVALID_OP.');
console.log('Data after 1x1 color-from-depth readpixels:');
console.log(pixels);
gl.readPixels(0, 0, // x,y
0, 0, // w,h
gl.RGBA, gl.UNSIGNED_BYTE, pixels);
ok(gl.getError() == gl.INVALID_OPERATION,
'0x0 color read from a depth FB should generated INVALID_OP.');
})();
ok(true, 'Test complete.');
</script>
</body>
</html>

View File

@ -37,8 +37,8 @@ NS_IMPL_STRING_ATTR(HTMLBRElement, Clear, clear)
static const nsAttrValue::EnumTable kClearTable[] = {
{ "left", NS_STYLE_CLEAR_LEFT },
{ "right", NS_STYLE_CLEAR_RIGHT },
{ "all", NS_STYLE_CLEAR_LEFT_AND_RIGHT },
{ "both", NS_STYLE_CLEAR_LEFT_AND_RIGHT },
{ "all", NS_STYLE_CLEAR_BOTH },
{ "both", NS_STYLE_CLEAR_BOTH },
{ 0 }
};

View File

@ -20,6 +20,7 @@
#include "nsIControllers.h"
#include "nsIStringBundle.h"
#include "nsFocusManager.h"
#include "nsColorControlFrame.h"
#include "nsNumberControlFrame.h"
#include "nsPIDOMWindow.h"
#include "nsRepeatService.h"
@ -2805,12 +2806,12 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue,
OnValueChanged(!mParserCreating);
}
// Call parent's SetAttr for color input so its control frame is notified
// and updated
if (mType == NS_FORM_INPUT_COLOR) {
return nsGenericHTMLFormElement::SetAttr(kNameSpaceID_None,
nsGkAtoms::value, aValue,
true);
// Update color frame, to reflect color changes
nsColorControlFrame* colorControlFrame = do_QueryFrame(GetPrimaryFrame());
if (colorControlFrame) {
colorControlFrame->UpdateColor();
}
}
return NS_OK;

View File

@ -20,6 +20,7 @@ support-files =
[test_input_color_picker_initial.html]
[test_input_color_picker_popup.html]
[test_input_color_picker_update.html]
[test_input_defaultValue.html]
[test_input_email.html]
[test_input_event.html]
[test_input_file_picker.html]

View File

@ -0,0 +1,81 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=977029
-->
<head>
<title>Test for Bug 977029</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<div id="content">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=977029">Bug 977029</a>
<p>
Goal of this test is to check that modifying defaultValue and value attribute
of input types is working as expected.
</p>
<form>
<input id='a' type="color" value="#00ff00">
<input id='b' type="text" value="foo">
<input id='c' type="email" value="foo">
<input id='d' type="date" value="2010-09-20">
<input id='e' type="search" value="foo">
<input id='f' type="tel" value="foo">
<input id='g' type="url" value="foo">
<input id='h' type="number" value="42">
<input id='i' type="range" value="42" min="0" max="100">
<input id='j' type="time" value="17:00:25.54">
</form>
</div>
<script type="application/javascript">
// [ element id | original defaultValue | another value | another default value]
// Preferably use only valid values: the goal of this test isn't to test the
// value sanitization algorithm (for input types which have one) as this is
// already part of another test)
var testData = [["a", "#00ff00", "#00aaaa", "#00ccaa"],
["b", "foo", "bar", "tulip"],
["c", "foo", "foo@bar.org", "tulip"],
["d", "2010-09-20", "2012-09-21", ""],
["e", "foo", "bar", "tulip"],
["f", "foo", "bar", "tulip"],
["g", "foo", "bar", "tulip"],
["h", "42", "1337", "3"],
["i", "42", "17", "3"],
["j", "17:00:25.54", "07:00:25", "03:00:03"],
];
for (var data of testData) {
id = data[0];
input = document.getElementById(id);
originalDefaultValue = data[1];
is(originalDefaultValue, input.defaultValue,
"Default value isn't the expected one");
is(originalDefaultValue, input.value,
"input.value original value is different from defaultValue");
input.defaultValue = data[2]
is(input.defaultValue, input.value,
"Changing default value before value was changed should change value too");
input.value = data[3];
input.defaultValue = originalDefaultValue;
is(input.value, data[3],
"Changing default value after value was changed should not change value");
input.value = data[2];
is(originalDefaultValue, input.defaultValue,
"defaultValue shouldn't change when changing value");
input.defaultValue = data[3];
is(input.defaultValue, data[3],
"defaultValue should have changed");
// Change the value...
input.value = data[2];
is(input.value, data[2],
"value should have changed");
// ...then reset the form
input.form.reset();
is(input.defaultValue, input.value,
"reset form should bring back the default value");
}
</script>
</body>
</html>

View File

@ -2449,6 +2449,15 @@ void MediaDecoderStateMachine::StartBuffering()
{
AssertCurrentThreadInMonitor();
if (mState != DECODER_STATE_DECODING) {
// We only move into BUFFERING state if we're actually decoding.
// If we're currently doing something else, we don't need to buffer,
// and more importantly, we shouldn't overwrite mState to interrupt
// the current operation, as that could leave us in an inconsistent
// state!
return;
}
if (IsPlaying()) {
StopPlayback();
}

View File

@ -1643,6 +1643,9 @@ public:
void BaseMediaResource::DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset)
{
if (aNumBytes <= 0) {
return;
}
RefPtr<nsIRunnable> event(new DispatchBytesConsumedEvent(mDecoder, aNumBytes, aOffset));
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}

View File

@ -84,6 +84,11 @@ ParseMP3Headers(MP3FrameParser *aParser, MediaResource *aResource)
MAX_READ_SIZE, &bytesRead);
NS_ENSURE_SUCCESS(rv, rv);
if (!bytesRead) {
// End of stream.
return NS_ERROR_FAILURE;
}
aParser->Parse(buffer, bytesRead, offset);
offset += bytesRead;
}

View File

@ -37,6 +37,7 @@ XPIDL_MODULE = 'docshell'
EXPORTS += [
'nsDocShellLoadTypes.h',
'nsILinkHandler.h',
'nsIScrollObserver.h',
'nsIWebShellServices.h',
'SerializedLoadContext.h',
]

View File

@ -67,6 +67,7 @@
#include "nsITimedChannel.h"
#include "nsIPrivacyTransitionObserver.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsIDocShellTreeItem.h"
#include "nsIChannel.h"
#include "IHistory.h"
@ -2857,6 +2858,39 @@ nsDocShell::GetCurrentDocChannel()
return nullptr;
}
NS_IMETHODIMP
nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver)
{
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
if (!weakObs) {
return NS_ERROR_FAILURE;
}
return mScrollObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver)
{
nsWeakPtr obs = do_GetWeakReference(aObserver);
return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocShell::NotifyScrollObservers()
{
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
while (iter.HasMore()) {
nsWeakPtr ref = iter.GetNext();
nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
if (obs) {
obs->ScrollPositionChanged();
} else {
mScrollObservers.RemoveElement(ref);
}
}
return NS_OK;
}
//*****************************************************************************
// nsDocShell::nsIDocShellTreeItem
//*****************************************************************************
@ -9280,19 +9314,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
sameExceptHashes && !newHash.IsEmpty());
if (doShortCircuitedLoad) {
// Cancel an outstanding new-document load if this is a history
// load.
//
// We can't cancel the oustanding load unconditionally, because if a
// page does
// - load a.html
// - start loading b.html
// - load a.html#h
// we break the web if we cancel the load of b.html.
if (aSHEntry && mDocumentRequest) {
mDocumentRequest->Cancel(NS_BINDING_ABORTED);
}
// Save the position of the scrollers.
nscoord cx = 0, cy = 0;
GetCurScrollPos(ScrollOrientation_X, &cx);
@ -9324,6 +9345,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
mURIResultedInDocument = true;
nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
/* we need to assign mLSHE to aSHEntry right here, so that on History loads,
* SetCurrentURI() called from OnNewURI() will send proper
* onLocationChange() notifications to the browser to update
@ -9401,10 +9424,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
SetCurScrollPosEx(bx, by);
}
/* Clear out mLSHE so that further anchor visits get
* recorded in SH and SH won't misbehave.
/* Restore the original LSHE if we were loading something
* while short-circuited load was initiated.
*/
SetHistoryEntry(&mLSHE, nullptr);
SetHistoryEntry(&mLSHE, oldLSHE);
/* Set the title for the SH entry for this target url. so that
* SH menus in go/back/forward buttons won't be empty for this.
*/

View File

@ -900,6 +900,7 @@ private:
nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
nsTObserverArray<nsWeakPtr> mReflowObservers;
nsTObserverArray<nsWeakPtr> mScrollObservers;
nsCString mOriginalUriString;
// Separate function to do the actual name (i.e. not _top, _self etc.)

View File

@ -41,10 +41,11 @@ interface nsIWebBrowserPrint;
interface nsIVariant;
interface nsIPrivacyTransitionObserver;
interface nsIReflowObserver;
interface nsIScrollObserver;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(d0eaef67-4234-47de-b05a-9c7b324eb4f4)]
[scriptable, builtinclass, uuid(e46d924d-c20f-4add-8cf5-1e1c817b2181)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -667,6 +668,24 @@ interface nsIDocShell : nsIDocShellTreeItem
in DOMHighResTimeStamp start,
in DOMHighResTimeStamp end);
/**
* Add an observer to the list of parties to be notified when scroll position
* of some elements is changed.
*/
[noscript] void addWeakScrollObserver(in nsIScrollObserver obs);
/**
* Add an observer to the list of parties to be notified when scroll position
* of some elements is changed.
*/
[noscript] void removeWeakScrollObserver(in nsIScrollObserver obs);
/**
* Notify all attached observers that the scroll position of some element
* has changed.
*/
[noscript] void notifyScrollObservers();
/**
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
* (<iframe mozapp mozbrowser> is not considered a browser.)

View File

@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIScrollObserver_h___
#define nsIScrollObserver_h___
#include "nsISupports.h"
#define NS_ISCROLLOBSERVER_IID \
{ 0x7c1a8b63, 0xe322, 0x4827, \
{ 0xa4, 0xb1, 0x3b, 0x6e, 0x59, 0x03, 0x47, 0x7e } }
class nsIScrollObserver : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLOBSERVER_IID)
/**
* Called when the scroll position of some element has changed.
*/
virtual void ScrollPositionChanged() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScrollObserver, NS_ISCROLLOBSERVER_IID)
#endif /* nsIScrollObserver_h___ */

View File

@ -0,0 +1,24 @@
<html>
<head>
<script>
var timerID = 0;
function testDone() {
clearTimeout(timerID);
var l = document.body.firstChild.contentWindow.location.href;
opener.is(l, "data:text/html,bar", "Should have loaded a new document");
opener.nextTest();
window.close();
}
function test() {
var ifr = document.getElementsByTagName("iframe")[0];
ifr.onload = testDone;
ifr.contentWindow.location.hash = "b";
ifr.contentWindow.location.href = "data:text/html,bar";
history.back();
timerID = setTimeout(testDone, 2000);
}
</script>
</head>
<body onload="setTimeout(test, 0)"><iframe src="data:text/html,foo#a"></iframe>
</body>
</html>

View File

@ -8,6 +8,7 @@ support-files =
file_bug508537_1.html
file_bug534178.html
file_document_write_1.html
file_fragment_handling_during_load.html
file_static_and_dynamic_1.html
frame0.html
frame1.html

View File

@ -26,7 +26,8 @@ var testFiles =
"file_bug508537_1.html", // Dynamic frames and forward-back
"file_document_write_1.html", // Session history + document.write
"file_static_and_dynamic_1.html",// Static and dynamic frames and forward-back
"file_bug534178.html" // Session history transaction clean-up.
"file_bug534178.html", // Session history transaction clean-up.
"file_fragment_handling_during_load.html"
];
var testCount = 0; // Used by the test files.

View File

@ -8,10 +8,10 @@ const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
// This module exposes a subset of the functionalities of the parent DOM
// Registry to content processes, to be used from the AppsService component.
// This module exposes a subset of the functionnalities of the parent DOM
// Registry to content processes, to be be used from the AppsService component.
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "WrappedManifestCache"];
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry"];
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -20,265 +20,54 @@ function debug(s) {
//dump("-*- AppsServiceChild.jsm: " + s + "\n");
}
const APPS_IPC_MSG_NAMES = [
"Webapps:AddApp",
"Webapps:RemoveApp",
"Webapps:CheckForUpdate:Return:KO",
"Webapps:FireEvent",
"Webapps:UpdateState"
];
// A simple cache for the wrapped manifests.
this.WrappedManifestCache = {
_cache: { },
// Gets an entry from the cache, and populates the cache if needed.
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
if (!(aManifestURL in this._cache)) {
this._cache[aManifestURL] = { };
}
let winObjs = this._cache[aManifestURL];
if (!(aInnerWindowID in winObjs)) {
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
}
return winObjs[aInnerWindowID];
},
// Invalidates an entry in the cache.
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
debug("Evicting manifest " + aManifestURL + " window ID " +
aInnerWindowID);
if (aManifestURL in this._cache) {
let winObjs = this._cache[aManifestURL];
if (aInnerWindowID in winObjs) {
delete winObjs[aInnerWindowID];
}
if (Object.keys(winObjs).length == 0) {
delete this._cache[aManifestURL];
}
}
},
observe: function(aSubject, aTopic, aData) {
// Clear the cache on memory pressure.
this._cache = { };
Cu.forceGC();
},
init: function() {
Services.obs.addObserver(this, "memory-pressure", false);
}
};
this.WrappedManifestCache.init();
// DOMApplicationRegistry keeps a cache containing a list of apps in the device.
// This information is updated with the data received from the main process and
// it is queried by the DOM objects to set their state.
// This module handle all the messages broadcasted from the parent process,
// including DOM events, which are dispatched to the corresponding DOM objects.
this.DOMApplicationRegistry = {
// DOMApps will hold a list of arrays of weak references to
// mozIDOMApplication objects indexed by manifest URL.
DOMApps: {},
init: function init() {
debug("init");
this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
APPS_IPC_MSG_NAMES.forEach((function(aMsgName) {
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
this.cpmm.addMessageListener(aMsgName, this);
}).bind(this));
this.cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
messages: APPS_IPC_MSG_NAMES
});
// We need to prime the cache with the list of apps.
// XXX should we do this async and block callers if it's not yet there?
let list = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
this.webapps = list.webapps;
// XXX shoud we do this async and block callers if it's not yet there?
this.webapps = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
// We need a fast mapping from localId -> app, so we add an index.
// And add the manifest to the app object.
this.localIdIndex = { };
for (let id in this.webapps) {
let app = this.webapps[id];
this.localIdIndex[app.localId] = app;
app.manifest = list.manifests[id];
}
Services.obs.addObserver(this, "xpcom-shutdown", false);
},
observe: function(aSubject, aTopic, aData) {
// cpmm.addMessageListener causes the DOMApplicationRegistry object to
// live forever if we don't clean up properly.
// cpmm.addMessageListener causes the DOMApplicationRegistry object to live
// forever if we don't clean up properly.
this.webapps = null;
this.DOMApps = null;
APPS_IPC_MSG_NAMES.forEach((aMsgName) => {
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
this.cpmm.removeMessageListener(aMsgName, this);
});
this.cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
APPS_IPC_MSG_NAMES)
}).bind(this));
},
receiveMessage: function receiveMessage(aMessage) {
debug("Received " + aMessage.name + " message.");
let msg = aMessage.data;
let msg = aMessage.json;
switch (aMessage.name) {
case "Webapps:AddApp":
this.webapps[msg.id] = msg.app;
this.localIdIndex[msg.app.localId] = msg.app;
break;
case "Webapps:RemoveApp":
delete this.DOMApps[this.webapps[msg.id].manifestURL];
delete this.localIdIndex[this.webapps[msg.id].localId];
delete this.webapps[msg.id];
break;
case "Webapps:FireEvent":
this._fireEvent(aMessage);
break;
case "Webapps:UpdateState":
this._updateState(msg);
break;
case "Webapps:CheckForUpdate:Return:KO":
let DOMApps = this.DOMApps[msg.manifestURL];
if (!DOMApps || !msg.requestID) {
return;
}
DOMApps.forEach((DOMApp) => {
let domApp = DOMApp.get();
if (msg.requestID) {
domApp._fireRequestResult(aMessage, true /* aIsError */);
}
});
break;
}
},
/**
* mozIDOMApplication management
*/
// Every time a DOM app is created, we save a weak reference to it that will
// be used to dispatch events and fire request results.
addDOMApp: function(aApp, aManifestURL, aId) {
let weakRef = Cu.getWeakReference(aApp);
if (!this.DOMApps[aManifestURL]) {
this.DOMApps[aManifestURL] = [];
}
let apps = this.DOMApps[aManifestURL];
// Get rid of dead weak references.
for (let i = 0; i < apps.length; i++) {
if (!apps[i].get()) {
apps.splice(i);
}
}
apps.push(weakRef);
// Each DOM app contains a proxy object used to build their state. We
// return the handler for this proxy object with traps to get and set
// app properties kept in the DOMApplicationRegistry app cache.
return {
get: function(target, prop) {
if (!DOMApplicationRegistry.webapps[aId]) {
return;
}
return DOMApplicationRegistry.webapps[aId][prop];
},
set: function(target, prop, val) {
if (!DOMApplicationRegistry.webapps[aId]) {
return;
}
DOMApplicationRegistry.webapps[aId][prop] = val;
return;
},
};
},
_fireEvent: function(aMessage) {
let msg = aMessage.data;
debug("_fireEvent " + JSON.stringify(msg));
if (!this.DOMApps || !msg.manifestURL || !msg.eventType) {
return;
}
let DOMApps = this.DOMApps[msg.manifestURL];
if (!DOMApps) {
return;
}
// The parent might ask childs to trigger more than one event in one
// shot, so in order to avoid needless IPC we allow an array for the
// 'eventType' IPC message field.
if (!Array.isArray(msg.eventType)) {
msg.eventType = [msg.eventType];
}
DOMApps.forEach((DOMApp) => {
let domApp = DOMApp.get();
msg.eventType.forEach((aEventType) => {
if ('on' + aEventType in domApp) {
domApp._fireEvent(aEventType);
}
});
if (msg.requestID) {
aMessage.data.result = msg.manifestURL;
domApp._fireRequestResult(aMessage);
}
});
},
_updateState: function(aMessage) {
if (!this.DOMApps || !aMessage.id) {
return;
}
let app = this.webapps[aMessage.id];
if (!app) {
return;
}
if (aMessage.app) {
for (let prop in aMessage.app) {
app[prop] = aMessage.app[prop];
}
}
if (aMessage.error) {
app.downloadError = aMessage.error;
}
if (aMessage.manifest) {
app.manifest = aMessage.manifest;
// Evict the wrapped manifest cache for all the affected DOM objects.
let DOMApps = this.DOMApps[app.manifestURL];
if (!DOMApps) {
return;
}
DOMApps.forEach((DOMApp) => {
let domApp = DOMApp.get();
WrappedManifestCache.evict(app.manifestURL, domApp.innerWindowID);
});
}
},
/**
* nsIAppsService API
*/
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
debug("getAppByManifestURL " + aManifestURL);
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);

View File

@ -12,7 +12,6 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
@ -265,9 +264,50 @@ WebappsRegistry.prototype = {
* mozIDOMApplication object
*/
// A simple cache for the wrapped manifests.
let manifestCache = {
_cache: { },
// Gets an entry from the cache, and populates the cache if needed.
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
if (!(aManifestURL in this._cache)) {
this._cache[aManifestURL] = { };
}
let winObjs = this._cache[aManifestURL];
if (!(aInnerWindowID in winObjs)) {
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
}
return winObjs[aInnerWindowID];
},
// Invalidates an entry in the cache.
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
if (aManifestURL in this._cache) {
let winObjs = this._cache[aManifestURL];
if (aInnerWindowID in winObjs) {
delete winObjs[aInnerWindowID];
}
if (Object.keys(winObjs).length == 0) {
delete this._cache[aManifestURL];
}
}
},
observe: function(aSubject, aTopic, aData) {
// Clear the cache on memory pressure.
this._cache = { };
},
init: function() {
Services.obs.addObserver(this, "memory-pressure", false);
}
};
function createApplicationObject(aWindow, aApp) {
let app = Cc["@mozilla.org/webapps/application;1"]
.createInstance(Ci.mozIDOMApplication);
let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication);
app.wrappedJSObject.init(aWindow, aApp);
return app;
}
@ -280,12 +320,27 @@ WebappsApplication.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
init: function(aWindow, aApp) {
let proxyHandler = DOMApplicationRegistry.addDOMApp(this,
aApp.manifestURL,
aApp.id);
this._proxy = new Proxy(this, proxyHandler);
this._window = aWindow;
let principal = this._window.document.nodePrincipal;
this._appStatus = principal.appStatus;
this.origin = aApp.origin;
this._manifest = aApp.manifest;
this._updateManifest = aApp.updateManifest;
this.manifestURL = aApp.manifestURL;
this.receipts = aApp.receipts;
this.installOrigin = aApp.installOrigin;
this.installTime = aApp.installTime;
this.installState = aApp.installState || "installed";
this.removable = aApp.removable;
this.lastUpdateCheck = aApp.lastUpdateCheck ? aApp.lastUpdateCheck
: Date.now();
this.updateTime = aApp.updateTime ? aApp.updateTime
: aApp.installTime;
this.progress = NaN;
this.downloadAvailable = aApp.downloadAvailable;
this.downloading = aApp.downloading;
this.readyToApplyDownload = aApp.readyToApplyDownload;
this.downloadSize = aApp.downloadSize || 0;
this._onprogress = null;
this._ondownloadsuccess = null;
@ -293,83 +348,40 @@ WebappsApplication.prototype = {
this._ondownloadavailable = null;
this._ondownloadapplied = null;
this.initDOMRequestHelper(aWindow);
},
this._downloadError = null;
get _appStatus() {
return this._proxy.appStatus;
},
this.initDOMRequestHelper(aWindow, [
{ name: "Webapps:CheckForUpdate:Return:KO", weakRef: true },
{ name: "Webapps:Connect:Return:OK", weakRef: true },
{ name: "Webapps:Connect:Return:KO", weakRef: true },
{ name: "Webapps:FireEvent", weakRef: true },
{ name: "Webapps:GetConnections:Return:OK", weakRef: true },
{ name: "Webapps:UpdateState", weakRef: true }
]);
get downloadAvailable() {
return this._proxy.downloadAvailable;
},
get downloading() {
return this._proxy.downloading;
},
get downloadSize() {
return this._proxy.downloadSize;
},
get installOrigin() {
return this._proxy.installOrigin;
},
get installState() {
return this._proxy.installState;
},
get installTime() {
return this._proxy.installTime;
},
get lastUpdateCheck() {
return this._proxy.lastUpdateCheck;
},
get manifestURL() {
return this._proxy.manifestURL;
},
get origin() {
return this._proxy.origin;
},
get progress() {
return this._proxy.progress;
},
get readyToApplyDownload() {
return this._proxy.readyToApplyDownload;
},
get receipts() {
return this._proxy.receipts;
},
set receipts(aReceipts) {
this._proxy.receipts = aReceipts;
},
get removable() {
return this._proxy.removable;
},
get updateTime() {
return this._proxy.updateTime;
cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
messages: ["Webapps:FireEvent",
"Webapps:UpdateState"],
app: {
id: this.id,
manifestURL: this.manifestURL,
installState: this.installState,
downloading: this.downloading
}
});
},
get manifest() {
return WrappedManifestCache.get(this.manifestURL,
this._proxy.manifest,
this._window,
this.innerWindowID);
return manifestCache.get(this.manifestURL,
this._manifest,
this._window,
this.innerWindowID);
},
get updateManifest() {
return this._proxy.updateManifest ?
Cu.cloneInto(this._proxy.updateManifest, this._window) : null;
return this.updateManifest =
this._updateManifest ? Cu.cloneInto(this._updateManifest, this._window)
: null;
},
set onprogress(aCallback) {
@ -413,7 +425,7 @@ WebappsApplication.prototype = {
},
get downloadError() {
return new this._window.DOMError(this._proxy.downloadError || '');
return new this._window.DOMError(this._downloadError || '');
},
download: function() {
@ -455,11 +467,12 @@ WebappsApplication.prototype = {
BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
if (browserChild) {
this.addMessageListeners("Webapps:ClearBrowserData:Return");
browserChild.messageManager.sendAsyncMessage("Webapps:ClearBrowserData", {
manifestURL: this.manifestURL,
oid: this._id,
requestID: this.getRequestId(request)
});
browserChild.messageManager.sendAsyncMessage(
"Webapps:ClearBrowserData",
{ manifestURL: this.manifestURL,
oid: this._id,
requestID: this.getRequestId(request) }
);
} else {
Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER");
}
@ -467,34 +480,29 @@ WebappsApplication.prototype = {
},
connect: function(aKeyword, aRules) {
this.addMessageListeners(["Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO"]);
return this.createPromise(function (aResolve, aReject) {
cpmm.sendAsyncMessage("Webapps:Connect", {
keyword: aKeyword,
rules: aRules,
manifestURL: this.manifestURL,
outerWindowID: this._id,
appStatus: this._appStatus,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
});
cpmm.sendAsyncMessage("Webapps:Connect",
{ keyword: aKeyword,
rules: aRules,
manifestURL: this.manifestURL,
outerWindowID: this._id,
appStatus: this._appStatus,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})});
}.bind(this));
},
getConnections: function() {
this.addMessageListeners("Webapps:getConnections:Return:OK");
return this.createPromise(function (aResolve, aReject) {
cpmm.sendAsyncMessage("Webapps:GetConnections", {
manifestURL: this.manifestURL,
outerWindowID: this._id,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
});
cpmm.sendAsyncMessage("Webapps:GetConnections",
{ manifestURL: this.manifestURL,
outerWindowID: this._id,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})});
}.bind(this));
},
@ -543,7 +551,12 @@ WebappsApplication.prototype = {
uninit: function() {
this._onprogress = null;
WrappedManifestCache.evict(this.manifestURL, this.innerWindowID);
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages", [
"Webapps:FireEvent",
"Webapps:UpdateState"
]);
manifestCache.evict(this.manifestURL, this.innerWindowID);
},
_fireEvent: function(aName) {
@ -560,15 +573,21 @@ WebappsApplication.prototype = {
}
},
_fireRequestResult: function(aMessage, aIsError) {
let req;
let msg = aMessage.data;
req = this.takeRequest(msg.requestID);
if (!req) {
return;
_updateState: function(aMsg) {
if (aMsg.app) {
for (let prop in aMsg.app) {
this[prop] = aMsg.app[prop];
}
}
if (aMsg.error) {
this._downloadError = aMsg.error;
}
if (aMsg.manifest) {
this._manifest = aMsg.manifest;
manifestCache.evict(this.manifestURL, this.innerWindowID);
}
aIsError ? Services.DOMRequest.fireError(req, msg.error)
: Services.DOMRequest.fireSuccess(req, msg.result);
},
receiveMessage: function(aMessage) {
@ -582,7 +601,10 @@ WebappsApplication.prototype = {
req = this.takeRequest(msg.requestID);
}
if (msg.oid != this._id || !req) {
// ondownload* callbacks should be triggered on all app instances
if ((msg.oid != this._id || !req) &&
aMessage.name !== "Webapps:FireEvent" &&
aMessage.name !== "Webapps:UpdateState") {
return;
}
@ -597,13 +619,45 @@ WebappsApplication.prototype = {
"Webapps:Launch:Return:KO"]);
Services.DOMRequest.fireSuccess(req, null);
break;
case "Webapps:CheckForUpdate:Return:KO":
Services.DOMRequest.fireError(req, msg.error);
break;
case "Webapps:FireEvent":
if (msg.manifestURL != this.manifestURL) {
return;
}
// The parent might ask childs to trigger more than one event in one
// shot, so in order to avoid needless IPC we allow an array for the
// 'eventType' IPC message field.
if (!Array.isArray(msg.eventType)) {
msg.eventType = [msg.eventType];
}
msg.eventType.forEach((aEventType) => {
if ("_on" + aEventType in this) {
this._fireEvent(aEventType);
} else {
dump("Unsupported event type " + aEventType + "\n");
}
});
if (req) {
Services.DOMRequest.fireSuccess(req, this.manifestURL);
}
break;
case "Webapps:UpdateState":
if (msg.manifestURL != this.manifestURL) {
return;
}
this._updateState(msg);
break;
case "Webapps:ClearBrowserData:Return":
this.removeMessageListeners(aMessage.name);
Services.DOMRequest.fireSuccess(req, null);
break;
case "Webapps:Connect:Return:OK":
this.removeMessageListeners(["Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO"]);
let messagePorts = [];
msg.messagePortIDs.forEach((aPortID) => {
let port = new this._window.MozInterAppMessagePort(aPortID);
@ -612,12 +666,9 @@ WebappsApplication.prototype = {
req.resolve(messagePorts);
break;
case "Webapps:Connect:Return:KO":
this.removeMessageListeners(["Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO"]);
req.reject("No connections registered");
break;
case "Webapps:GetConnections:Return:OK":
this.removeMessageListeners(aMessage.name);
let connections = [];
msg.connections.forEach((aConnection) => {
let connection =
@ -799,8 +850,12 @@ WebappsApplicationMgmt.prototype = {
break;
case "Webapps:Uninstall:Broadcast:Return:OK":
if (this._onuninstall) {
let detail = {
manifestURL: msg.manifestURL,
origin: msg.origin
};
let event = new this._window.MozApplicationEvent("applicationuninstall",
{ application : createApplicationObject(this._window, msg) });
{ application : createApplicationObject(this._window, detail) });
this._onuninstall.handleEvent(event);
}
break;
@ -829,5 +884,7 @@ WebappsApplicationMgmt.prototype = {
classDescription: "Webapps Application Mgmt"})
}
manifestCache.init();
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
WebappsApplication]);

View File

@ -1142,7 +1142,8 @@ this.DOMApplicationRegistry = {
this.removeMessageListener(["Webapps:Internal:AllMessages"], mm);
break;
case "Webapps:GetList":
return { webapps: this.webapps, manifests: this._manifestCache };
this.addMessageListener(["Webapps:AddApp", "Webapps:RemoveApp"], null, mm);
return this.webapps;
case "Webapps:Download":
this.startDownload(msg.manifestURL);
break;
@ -1287,7 +1288,7 @@ this.DOMApplicationRegistry = {
downloading: false
},
error: error,
id: app.id
manifestURL: app.manifestURL,
})
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
@ -1316,7 +1317,7 @@ this.DOMApplicationRegistry = {
if (!app.downloadAvailable) {
this.broadcastMessage("Webapps:UpdateState", {
error: "NO_DOWNLOAD_AVAILABLE",
id: app.id
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
@ -1361,7 +1362,7 @@ this.DOMApplicationRegistry = {
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: jsonManifest,
id: app.id
manifestURL: aManifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadsuccess",
@ -1404,7 +1405,7 @@ this.DOMApplicationRegistry = {
DOMApplicationRegistry._saveApps().then(() => {
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: aManifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadsuccess",
@ -1498,7 +1499,7 @@ this.DOMApplicationRegistry = {
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: aData,
id: app.id
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
@ -1538,7 +1539,7 @@ this.DOMApplicationRegistry = {
installState: aApp.installState,
progress: 0
},
id: aApp.id
manifestURL: aApp.manifestURL
});
let cacheUpdate = updateSvc.scheduleAppUpdate(
appcacheURI, docURI, aApp.localId, false, aProfileDir);
@ -1588,7 +1589,6 @@ this.DOMApplicationRegistry = {
debug("checkForUpdate for " + aData.manifestURL);
function sendError(aError) {
debug("checkForUpdate error " + aError);
aData.error = aError;
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
}
@ -1618,7 +1618,8 @@ this.DOMApplicationRegistry = {
// then we can't have an update.
if (app.origin.startsWith("app://") &&
app.manifestURL.startsWith("app://")) {
sendError("NOT_UPDATABLE");
aData.error = "NOT_UPDATABLE";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
return;
}
@ -1635,7 +1636,8 @@ this.DOMApplicationRegistry = {
if (onlyCheckAppCache) {
// Bail out for packaged apps.
if (app.origin.startsWith("app://")) {
sendError("NOT_UPDATABLE");
aData.error = "NOT_UPDATABLE";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
return;
}
@ -1643,7 +1645,8 @@ this.DOMApplicationRegistry = {
this._readManifests([{ id: id }]).then((aResult) => {
let manifest = aResult[0].manifest;
if (!manifest.appcache_path) {
sendError("NOT_UPDATABLE");
aData.error = "NOT_UPDATABLE";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
return;
}
@ -1659,7 +1662,7 @@ this.DOMApplicationRegistry = {
this._saveApps().then(() => {
this.broadcastMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadavailable",
@ -1668,7 +1671,8 @@ this.DOMApplicationRegistry = {
});
});
} else {
sendError("NOT_UPDATABLE");
aData.error = "NOT_UPDATABLE";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
}
}
};
@ -1728,7 +1732,7 @@ this.DOMApplicationRegistry = {
: "downloadapplied";
aMm.sendAsyncMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
aMm.sendAsyncMessage("Webapps:FireEvent", {
eventType: eventType,
@ -1755,7 +1759,7 @@ this.DOMApplicationRegistry = {
: "downloadapplied";
aMm.sendAsyncMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
aMm.sendAsyncMessage("Webapps:FireEvent", {
eventType: eventType,
@ -1863,7 +1867,7 @@ this.DOMApplicationRegistry = {
this._saveApps().then(() => {
this.broadcastMessage("Webapps:UpdateState", {
app: aApp,
id: aApp.id
manifestURL: aApp.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadavailable",
@ -1927,7 +1931,7 @@ this.DOMApplicationRegistry = {
reg.broadcastMessage("Webapps:UpdateState", {
app: aApp,
manifest: aApp.manifest,
id: aApp.id
manifestURL: aApp.manifestURL
});
reg.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
@ -1949,7 +1953,7 @@ this.DOMApplicationRegistry = {
reg.broadcastMessage("Webapps:UpdateState", {
app: aApp,
manifest: aApp.manifest,
id: aApp.id
manifestURL: aApp.manifestURL
});
reg.broadcastMessage("Webapps:FireEvent", {
eventType: eventType,
@ -2214,8 +2218,8 @@ this.DOMApplicationRegistry = {
queuedDownload: {},
queuedPackageDownload: {},
onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
aDontNeedNetwork) {
onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
aDontNeedNetwork) {
// If we are offline, register to run when we'll be online.
if ((Services.io.offline) && !aDontNeedNetwork) {
let onlineWrapper = {
@ -2345,6 +2349,7 @@ this.DOMApplicationRegistry = {
let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
this._writeManifestFile(id, aData.isPackage, jsonManifest);
debug("app.origin: " + app.origin);
let manifest = new ManifestHelper(jsonManifest, app.origin);
let appObject = this._cloneApp(aData, app, manifest, id, localId);
@ -2388,8 +2393,6 @@ this.DOMApplicationRegistry = {
// corresponging DOMRequest.onsuccess event as soon as the app is properly
// saved in the registry.
this._saveApps().then(() => {
aData.isPackage ? appObject.updateManifest = jsonManifest :
appObject.manifest = jsonManifest;
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
if (aData.isPackage && aData.autoInstall) {
// Skip directly to onInstallSuccessAck, since there isn't
@ -2506,7 +2509,7 @@ this.DOMApplicationRegistry = {
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: aManifest,
id: app.id
manifestURL: aNewApp.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: ["downloadsuccess", "downloadapplied"],
@ -2616,11 +2619,14 @@ this.DOMApplicationRegistry = {
oldApp,
aNewApp);
AppDownloadManager.add(aNewApp.manifestURL, {
channel: requestChannel,
appId: id,
previousState: aIsUpdate ? "installed" : "pending"
});
AppDownloadManager.add(
aNewApp.manifestURL,
{
channel: requestChannel,
appId: id,
previousState: aIsUpdate ? "installed" : "pending"
}
);
// We set the 'downloading' flag to true right before starting the fetch.
oldApp.downloading = true;
@ -2643,7 +2649,7 @@ this.DOMApplicationRegistry = {
debug("package's etag or hash unchanged; sending 'applied' event");
// The package's Etag or hash has not changed.
// We send a "applied" event right away.
this._sendAppliedEvent(oldApp);
this._sendAppliedEvent(aNewApp, oldApp, id);
return;
}
@ -2783,7 +2789,7 @@ this.DOMApplicationRegistry = {
app: {
progress: aProgress
},
id: aNewApp.id
manifestURL: aNewApp.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "progress",
@ -2911,21 +2917,21 @@ this.DOMApplicationRegistry = {
* @param aOldApp {Object} the currently stored app data
* @param aId {String} the unique id of the app
*/
_sendAppliedEvent: function(aApp) {
aApp.downloading = false;
aApp.downloadAvailable = false;
aApp.downloadSize = 0;
aApp.installState = "installed";
aApp.readyToApplyDownload = false;
if (aApp.staged && aApp.staged.manifestHash) {
_sendAppliedEvent: function(aNewApp, aOldApp, aId) {
aOldApp.downloading = false;
aOldApp.downloadAvailable = false;
aOldApp.downloadSize = 0;
aOldApp.installState = "installed";
aOldApp.readyToApplyDownload = false;
if (aOldApp.staged && aOldApp.staged.manifestHash) {
// If we're here then the manifest has changed but the package
// hasn't. Let's clear this, so we don't keep offering
// a bogus update to the user
aApp.manifestHash = aApp.staged.manifestHash;
aApp.etag = aApp.staged.etag || aApp.etag;
aApp.staged = {};
aOldApp.manifestHash = aOldApp.staged.manifestHash;
aOldApp.etag = aOldApp.staged.etag || aOldApp.etag;
aOldApp.staged = {};
// Move the staged update manifest to a non staged one.
let dirPath = this._getAppDir(aApp.id).path;
let dirPath = this._getAppDir(aId).path;
// We don't really mind much if this fails.
OS.File.move(OS.Path.join(dirPath, "staged-update.webapp"),
@ -2935,15 +2941,15 @@ this.DOMApplicationRegistry = {
// Save the updated registry, and cleanup the tmp directory.
this._saveApps().then(() => {
this.broadcastMessage("Webapps:UpdateState", {
app: aApp,
id: aApp.id
app: aOldApp,
manifestURL: aNewApp.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
manifestURL: aApp.manifestURL,
manifestURL: aNewApp.manifestURL,
eventType: ["downloadsuccess", "downloadapplied"]
});
});
let file = FileUtils.getFile("TmpD", ["webapps", aApp.id], false);
let file = FileUtils.getFile("TmpD", ["webapps", aId], false);
if (file && file.exists()) {
file.remove(true);
}
@ -3322,7 +3328,7 @@ this.DOMApplicationRegistry = {
this.broadcastMessage("Webapps:UpdateState", {
app: aOldApp,
error: aError,
id: aNewApp.id
manifestURL: aNewApp.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloaderror",
@ -3872,7 +3878,7 @@ AppcacheObserver.prototype = {
let app = this.app;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: "progress",
@ -3904,7 +3910,7 @@ AppcacheObserver.prototype = {
app.downloadAvailable = false;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
eventType: ["downloadsuccess", "downloadapplied"],
@ -3917,7 +3923,7 @@ AppcacheObserver.prototype = {
app.downloading = false;
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
app: app,
id: app.id
manifestURL: app.manifestURL
});
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
error: aError,

View File

@ -99,7 +99,6 @@ var PackagedTestHelper = (function PackagedTestHelper() {
var aApp = evt.application;
aApp.ondownloaderror = function(evt) {
var error = aApp.downloadError.name;
ok(true, "Got downloaderror " + error);
if (error == aExpectedError) {
ok(true, "Got expected " + aExpectedError);
var expected = {

View File

@ -79,15 +79,16 @@ function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) {
checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false,
aNextVersion, PackagedTestHelper.next);
var ondownloadsuccesshandler =
checkLastAppState.bind(undefined, miniManifestURL,
aExpectedReady, false, aPreviousVersion,
function() {
navigator.mozApps.mgmt.applyDownload(lApp);
});
var ondownloadsuccesshandler =
checkLastAppState.bind(undefined, miniManifestURL,
aExpectedReady, false, aPreviousVersion,
function() {
navigator.mozApps.mgmt.applyDownload(lApp);
});
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, null,
true);
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, null,
true);
}
@ -174,7 +175,7 @@ var steps = [
"&appName=arandomname" +
"&appToFail1";
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MANIFEST_MISMATCH", 1, false, true,
"MANIFEST_MISMATCH", 2, false, true,
"arandomname",
function () {
checkForUpdate(false, null, null, null, false,

View File

@ -247,4 +247,4 @@ addLoadEvent(go);
</script>
</pre>
</body>
</html>
</html>

View File

@ -132,7 +132,7 @@ JSStructuredCloneCallbacks gConsoleCallbacks = {
ConsoleStructuredCloneCallbacksError
};
class ConsoleCallData
class ConsoleCallData MOZ_FINAL : public LinkedListElement<ConsoleCallData>
{
public:
ConsoleCallData()
@ -141,6 +141,12 @@ public:
, mTimeStamp(JS_Now())
, mMonotonicTimer(0)
{
MOZ_COUNT_CTOR(ConsoleCallData);
}
~ConsoleCallData()
{
MOZ_COUNT_DTOR(ConsoleCallData);
}
void
@ -259,7 +265,7 @@ private:
class ConsoleCallDataRunnable MOZ_FINAL : public ConsoleRunnable
{
public:
ConsoleCallDataRunnable(const ConsoleCallData& aCallData)
ConsoleCallDataRunnable(ConsoleCallData* aCallData)
: mCallData(aCallData)
{
}
@ -269,16 +275,16 @@ private:
PreDispatch(JSContext* aCx) MOZ_OVERRIDE
{
ClearException ce(aCx);
JSAutoCompartment ac(aCx, mCallData.mGlobal);
JSAutoCompartment ac(aCx, mCallData->mGlobal);
JS::Rooted<JSObject*> arguments(aCx,
JS_NewArrayObject(aCx, mCallData.mArguments.Length()));
JS_NewArrayObject(aCx, mCallData->mArguments.Length()));
if (!arguments) {
return false;
}
for (uint32_t i = 0; i < mCallData.mArguments.Length(); ++i) {
if (!JS_DefineElement(aCx, arguments, i, mCallData.mArguments[i],
for (uint32_t i = 0; i < mCallData->mArguments.Length(); ++i) {
if (!JS_DefineElement(aCx, arguments, i, mCallData->mArguments[i],
nullptr, nullptr, JSPROP_ENUMERATE)) {
return false;
}
@ -290,8 +296,8 @@ private:
return false;
}
mCallData.mArguments.Clear();
mCallData.mGlobal = nullptr;
mCallData->mArguments.Clear();
mCallData->mGlobal = nullptr;
return true;
}
@ -341,17 +347,17 @@ private:
return;
}
mCallData.mArguments.AppendElement(value);
mCallData->mArguments.AppendElement(value);
}
MOZ_ASSERT(mCallData.mArguments.Length() == length);
MOZ_ASSERT(mCallData->mArguments.Length() == length);
mCallData.mGlobal = JS::CurrentGlobalOrNull(cx);
console->AppendCallData(mCallData);
mCallData->mGlobal = JS::CurrentGlobalOrNull(cx);
console->AppendCallData(mCallData.forget());
}
private:
ConsoleCallData mCallData;
nsAutoPtr<ConsoleCallData> mCallData;
JSAutoStructuredCloneBuffer mArguments;
nsTArray<nsString> mStrings;
@ -480,7 +486,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Console)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mQueuedCalls.Clear();
tmp->ClearConsoleData();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -494,11 +500,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Console)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
for (uint32_t i = 0; i < tmp->mQueuedCalls.Length(); ++i) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mQueuedCalls[i].mGlobal);
for (ConsoleCallData* data = tmp->mQueuedCalls.getFirst(); data != nullptr;
data = data->getNext()) {
if (data->mGlobal) {
aCallbacks.Trace(&data->mGlobal, "data->mGlobal", aClosure);
}
for (uint32_t j = 0; j < tmp->mQueuedCalls[i].mArguments.Length(); ++j) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mQueuedCalls[i].mArguments[j]);
for (uint32_t i = 0; i < data->mArguments.Length(); ++i) {
if (JSVAL_IS_TRACEABLE(data->mArguments[i])) {
aCallbacks.Trace(&data->mArguments[i], "data->mArguments[i]", aClosure);
}
}
}
@ -568,7 +579,7 @@ Console::Observe(nsISupports* aSubject, const char* aTopic,
obs->RemoveObserver(this, "inner-window-destroyed");
}
mQueuedCalls.Clear();
ClearConsoleData();
mTimerRegistry.Clear();
if (mTimer) {
@ -735,8 +746,8 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
// goes wrong.
class RAII {
public:
RAII(nsTArray<ConsoleCallData>& aArray)
: mArray(aArray)
RAII(LinkedList<ConsoleCallData>& aList)
: mList(aList)
, mUnfinished(true)
{
}
@ -744,7 +755,9 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
~RAII()
{
if (mUnfinished) {
mArray.RemoveElementAt(mArray.Length() - 1);
ConsoleCallData* data = mList.popLast();
MOZ_ASSERT(data);
delete data;
}
}
@ -755,12 +768,14 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
}
private:
nsTArray<ConsoleCallData>& mArray;
LinkedList<ConsoleCallData>& mList;
bool mUnfinished;
};
ConsoleCallData& callData = *mQueuedCalls.AppendElement();
callData.Initialize(aCx, aMethodName, aMethodString, aData);
ConsoleCallData* callData = new ConsoleCallData();
mQueuedCalls.insertBack(callData);
callData->Initialize(aCx, aMethodName, aMethodString, aData);
RAII raii(mQueuedCalls);
if (mWindow) {
@ -773,7 +788,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
MOZ_ASSERT(loadContext);
loadContext->GetUsePrivateBrowsing(&callData.mPrivate);
loadContext->GetUsePrivateBrowsing(&callData->mPrivate);
}
uint32_t maxDepth = aMethodName == MethodTrace ?
@ -797,7 +812,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
if (language == nsIProgrammingLanguage::JAVASCRIPT ||
language == nsIProgrammingLanguage::JAVASCRIPT2) {
ConsoleStackEntry& data = *callData.mStack.AppendElement();
ConsoleStackEntry& data = *callData->mStack.AppendElement();
nsCString string;
rv = stack->GetFilename(string);
@ -850,20 +865,24 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
return;
}
callData.mMonotonicTimer = performance->Now();
callData->mMonotonicTimer = performance->Now();
}
// The operation is completed. RAII class has to be disabled.
raii.Finished();
if (!NS_IsMainThread()) {
// Here we are in a worker thread.
// Here we are in a worker thread. The ConsoleCallData has to been removed
// from the list and it will be deleted by the ConsoleCallDataRunnable or
// by the Main-Thread Console object.
mQueuedCalls.popLast();
nsRefPtr<ConsoleCallDataRunnable> runnable =
new ConsoleCallDataRunnable(callData);
runnable->Dispatch();
return;
}
// The operation is completed. RAII class has to be disabled.
raii.Finished();
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->InitWithCallback(this, CALL_DELAY,
@ -872,9 +891,9 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
}
void
Console::AppendCallData(const ConsoleCallData& aCallData)
Console::AppendCallData(ConsoleCallData* aCallData)
{
mQueuedCalls.AppendElement(aCallData);
mQueuedCalls.insertBack(aCallData);
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1");
@ -887,17 +906,19 @@ Console::AppendCallData(const ConsoleCallData& aCallData)
NS_IMETHODIMP
Console::Notify(nsITimer *timer)
{
MOZ_ASSERT(!mQueuedCalls.IsEmpty());
MOZ_ASSERT(!mQueuedCalls.isEmpty());
uint32_t i = 0;
for (; i < MESSAGES_IN_INTERVAL && i < mQueuedCalls.Length();
++i) {
ProcessCallData(mQueuedCalls[i]);
for (uint32_t i = 0; i < MESSAGES_IN_INTERVAL; ++i) {
ConsoleCallData* data = mQueuedCalls.popFirst();
if (!data) {
break;
}
ProcessCallData(data);
delete data;
}
mQueuedCalls.RemoveElementsAt(0, i);
if (mQueuedCalls.IsEmpty()) {
if (mQueuedCalls.isEmpty()) {
mTimer->Cancel();
mTimer = nullptr;
}
@ -906,18 +927,20 @@ Console::Notify(nsITimer *timer)
}
void
Console::ProcessCallData(ConsoleCallData& aData)
Console::ProcessCallData(ConsoleCallData* aData)
{
MOZ_ASSERT(aData);
ConsoleStackEntry frame;
if (!aData.mStack.IsEmpty()) {
frame = aData.mStack[0];
if (!aData->mStack.IsEmpty()) {
frame = aData->mStack[0];
}
AutoSafeJSContext cx;
ClearException ce(cx);
RootedDictionary<ConsoleEvent> event(cx);
JSAutoCompartment ac(cx, aData.mGlobal);
JSAutoCompartment ac(cx, aData->mGlobal);
event.mID.Construct();
event.mInnerID.Construct();
@ -930,14 +953,14 @@ Console::ProcessCallData(ConsoleCallData& aData)
event.mInnerID.Value().SetAsString() = frame.mFilename;
}
event.mLevel = aData.mMethodString;
event.mLevel = aData->mMethodString;
event.mFilename = frame.mFilename;
event.mLineNumber = frame.mLineNumber;
event.mFunctionName = frame.mFunctionName;
event.mTimeStamp = aData.mTimeStamp;
event.mPrivate = aData.mPrivate;
event.mTimeStamp = aData->mTimeStamp;
event.mPrivate = aData->mPrivate;
switch (aData.mMethodName) {
switch (aData->mMethodName) {
case MethodLog:
case MethodInfo:
case MethodWarn:
@ -946,35 +969,35 @@ Console::ProcessCallData(ConsoleCallData& aData)
case MethodDebug:
case MethodAssert:
event.mArguments.Construct();
ProcessArguments(cx, aData.mArguments, event.mArguments.Value());
ProcessArguments(cx, aData->mArguments, event.mArguments.Value());
break;
default:
event.mArguments.Construct();
ArgumentsToValueList(aData.mArguments, event.mArguments.Value());
ArgumentsToValueList(aData->mArguments, event.mArguments.Value());
}
if (aData.mMethodName == MethodTrace) {
if (aData->mMethodName == MethodTrace) {
event.mStacktrace.Construct();
event.mStacktrace.Value().SwapElements(aData.mStack);
event.mStacktrace.Value().SwapElements(aData->mStack);
}
else if (aData.mMethodName == MethodGroup ||
aData.mMethodName == MethodGroupCollapsed ||
aData.mMethodName == MethodGroupEnd) {
ComposeGroupName(cx, aData.mArguments, event.mGroupName);
else if (aData->mMethodName == MethodGroup ||
aData->mMethodName == MethodGroupCollapsed ||
aData->mMethodName == MethodGroupEnd) {
ComposeGroupName(cx, aData->mArguments, event.mGroupName);
}
else if (aData.mMethodName == MethodTime && !aData.mArguments.IsEmpty()) {
event.mTimer = StartTimer(cx, aData.mArguments[0], aData.mMonotonicTimer);
else if (aData->mMethodName == MethodTime && !aData->mArguments.IsEmpty()) {
event.mTimer = StartTimer(cx, aData->mArguments[0], aData->mMonotonicTimer);
}
else if (aData.mMethodName == MethodTimeEnd && !aData.mArguments.IsEmpty()) {
event.mTimer = StopTimer(cx, aData.mArguments[0], aData.mMonotonicTimer);
else if (aData->mMethodName == MethodTimeEnd && !aData->mArguments.IsEmpty()) {
event.mTimer = StopTimer(cx, aData->mArguments[0], aData->mMonotonicTimer);
}
else if (aData.mMethodName == MethodCount) {
event.mCounter = IncreaseCounter(cx, frame, aData.mArguments);
else if (aData->mMethodName == MethodCount) {
event.mCounter = IncreaseCounter(cx, frame, aData->mArguments);
}
JS::Rooted<JS::Value> eventValue(cx);
@ -1395,5 +1418,13 @@ Console::IncreaseCounter(JSContext* aCx, const ConsoleStackEntry& aFrame,
return value;
}
void
Console::ClearConsoleData()
{
while (ConsoleCallData* data = mQueuedCalls.popFirst()) {
delete data;
}
}
} // namespace dom
} // namespace mozilla

View File

@ -128,10 +128,10 @@ private:
const Sequence<JS::Value>& aData);
void
AppendCallData(const ConsoleCallData& aData);
AppendCallData(ConsoleCallData* aData);
void
ProcessCallData(ConsoleCallData& aData);
ProcessCallData(ConsoleCallData* aData);
// If the first JS::Value of the array is a string, this method uses it to
// format a string. The supported sequences are:
@ -181,11 +181,14 @@ private:
IncreaseCounter(JSContext* aCx, const ConsoleStackEntry& aFrame,
const nsTArray<JS::Heap<JS::Value>>& aArguments);
void
ClearConsoleData();
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
nsTArray<ConsoleCallData> mQueuedCalls;
LinkedList<ConsoleCallData> mQueuedCalls;
nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;

View File

@ -9,6 +9,7 @@ support-files =
[test_Image_constructor.html]
[test_appname_override.html]
[test_bug913761.html]
[test_bug978522.html]
[test_clearTimeoutIntervalNoArg.html]
[test_consoleEmptyStack.html]
[test_constructor-assignment.html]
@ -16,6 +17,7 @@ support-files =
[test_document.all_unqualified.html]
[test_domcursor.html]
[test_domrequest.html]
[test_domwindowutils.html]
[test_e4x_for_each.html]
[test_error.html]
[test_gsp-qualified.html]
@ -52,4 +54,3 @@ support-files =
[test_window_extensible.html]
[test_window_indexing.html]
[test_writable-replaceable.html]
[test_domwindowutils.html]

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=978522
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 978522 - basic support</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=978522">Mozilla Bug 978522</a>
<script type="application/javascript">
console.log('%s', {
toString: function() {
console.log('%s', {
toString: function() {
ok(true, "Still alive \\o/");
SimpleTest.finish();
return "hello world";
}
});
}
});
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

View File

@ -147,15 +147,18 @@ GonkCameraParameters::Initialize()
rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
if (NS_FAILED(rv)) {
return rv;
NS_WARNING("Failed to initialize minimum exposure compensation");
mExposureCompensationMin = 0;
}
rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
if (NS_FAILED(rv)) {
return rv;
NS_WARNING("Failed to initialize exposure compensation step size");
mExposureCompensationStep = 0;
}
rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
if (NS_FAILED(rv)) {
return rv;
// zoom is not supported
mZoomRatios.Clear();
}
mInitialized = true;
@ -410,6 +413,11 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
switch (aKey) {
case CAMERA_PARAM_EXPOSURECOMPENSATION:
if (mExposureCompensationStep == 0) {
DOM_CAMERA_LOGE("Exposure compensation not supported, can't set %f\n", aValue);
return NS_ERROR_NOT_AVAILABLE;
}
/**
* Convert from real value to a Gonk index, round
* to the nearest step; index is 1-based.
@ -422,34 +430,46 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
case CAMERA_PARAM_ZOOM:
{
if (mZoomRatios.Length() == 0) {
DOM_CAMERA_LOGE("Zoom not supported, can't set %fx\n", aValue);
return NS_ERROR_NOT_AVAILABLE;
}
/**
* Convert from a real zoom multipler (e.g. 2.5x) to
* the index of the nearest supported value.
*/
value = aValue * 100.0;
// mZoomRatios is sorted, so we can binary search it
unsigned int bottom = 0;
unsigned int top = mZoomRatios.Length() - 1;
unsigned int middle;
if (value < mZoomRatios[0]) {
index = 0;
} else if (value > mZoomRatios.LastElement()) {
index = mZoomRatios.Length() - 1;
} else {
// mZoomRatios is sorted, so we can binary search it
int bottom = 0;
int top = mZoomRatios.Length() - 1;
int middle;
while (bottom != top) {
middle = (top + bottom) / 2;
if (value == mZoomRatios[middle]) {
// exact match
break;
}
if (value > mZoomRatios[middle] && value < mZoomRatios[middle + 1]) {
// the specified zoom value lies in this interval
break;
}
if (value > mZoomRatios[middle]) {
bottom = middle + 1;
} else {
top = middle - 1;
while (top >= bottom) {
middle = (top + bottom) / 2;
if (value == mZoomRatios[middle]) {
// exact match
break;
}
if (value > mZoomRatios[middle] && value < mZoomRatios[middle + 1]) {
// the specified zoom value lies in this interval
break;
}
if (value > mZoomRatios[middle]) {
bottom = middle + 1;
} else {
top = middle - 1;
}
}
index = middle;
}
index = middle;
DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
}
return SetImpl(CAMERA_PARAM_ZOOM, index);
}
@ -616,16 +636,19 @@ GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
if (NS_FAILED(rv)) {
return rv;
}
if (!p) {
DOM_CAMERA_LOGW("Camera parameter %d not available (value is null)\n", aKey);
return NS_ERROR_NOT_AVAILABLE;
}
if (*p == '\0') {
DOM_CAMERA_LOGW("Camera parameter %d not available (value is empty string)\n", aKey);
return NS_ERROR_NOT_AVAILABLE;
}
aArray.Clear();
// If there is no value available, just return the empty array.
if (!p) {
DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
return NS_OK;
}
if (*p == '\0') {
DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
return NS_OK;
}
const char* comma;
while (p) {

View File

@ -56,6 +56,33 @@ TestGonkCameraHardware::TestCase()
return test;
}
const nsCString
TestGonkCameraHardware::GetExtraParameters()
{
/**
* The contents of this pref are appended to the flattened string of
* parameters stuffed into GonkCameraParameters by the camera library.
* It consists of semicolon-delimited key=value pairs, e.g.
*
* focus-mode=auto;flash-mode=auto;preview-size=1024x768
*
* The unflattening process breaks this string up on semicolon boundaries
* and sets an entry in a hashtable of strings with the token before
* the equals sign as the key, and the token after as the value. Because
* the string is parsed in order, key=value pairs occuring later in the
* string will replace value pairs appearing earlier, making it easy to
* inject fake, testable values into the parameters table.
*
* One constraint of this approach is that neither the key nor the value
* may contain equals signs or semicolons. We don't enforce that here
* so that we can also test correct handling of improperly-formatted values.
*/
const nsCString parameters = Preferences::GetCString("camera.control.test.hardware.gonk.parameters");
DOM_CAMERA_LOGA("TestGonkCameraHardware : extra-parameters '%s'\n",
parameters.get());
return parameters;
}
bool
TestGonkCameraHardware::IsTestCaseInternal(const char* aTest, const char* aFile, int aLine)
{
@ -174,7 +201,14 @@ TestGonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
return static_cast<nsresult>(TestCaseError(UNKNOWN_ERROR));
}
return GonkCameraHardware::PullParameters(aParams);
String8 s = mCamera->getParameters();
nsCString extra = GetExtraParameters();
if (!extra.IsEmpty()) {
s += ";";
s += extra.get();
}
return aParams.Unflatten(s);
}
int

View File

@ -55,6 +55,7 @@ public:
protected:
const nsCString TestCase();
const nsCString GetExtraParameters();
bool IsTestCaseInternal(const char* aTest, const char* aFile, int aLine);
int TestCaseError(int aDefaultError);

View File

@ -18,13 +18,41 @@ var CameraTest = (function() {
* 'take-picture-process-failure' will simulate a failure of the
* asynchronous picture-taking process, even if the initial API call
* path seems to have succeeded.
*
* If 'camera.control.test.hardware.gonk.parameters' is set, it will cause
* the contents of that string to be appended to the string of parameters
* pulled from the Gonk camera library. This allows tests to inject fake
* settings/capabilities for features not supported by the emulator. These
* parameters are one or more semicolon-delimited key=value pairs, e.g. to
* pretend the emulator supports zoom:
*
* zoom-ratios=100,150,200,300,400;max-zoom=4
*
* This means (of course) that neither the key not the value tokens can
* contain either equals signs or semicolons. The test shim doesn't enforce
* this so that we can test getting junk from the camera library as well.
*/
const PREF_TEST_ENABLED = "camera.control.test.enabled";
const PREF_TEST_HARDWARE = "camera.control.test.hardware";
const PREF_TEST_EXTRA_PARAMETERS = "camera.control.test.hardware.gonk.parameters";
var oldTestEnabled;
var oldTestHw;
var testMode;
function testHardwareSetFakeParameters(parameters, callback) {
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_EXTRA_PARAMETERS, parameters]]}, function() {
var setParams = SpecialPowers.getCharPref(PREF_TEST_EXTRA_PARAMETERS);
ise(setParams, parameters, "Extra test parameters '" + setParams + "'");
if (callback) {
callback(setParams);
}
});
}
function testHardwareClearFakeParameters(callback) {
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_EXTRA_PARAMETERS]]}, callback);
}
function testHardwareSet(test, callback) {
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_HARDWARE, test]]}, function() {
var setTest = SpecialPowers.getCharPref(PREF_TEST_HARDWARE);
@ -58,6 +86,8 @@ var CameraTest = (function() {
} catch(e) { }
testMode = {
set: testHardwareSet,
setFakeParameters: testHardwareSetFakeParameters,
clearFakeParameters: testHardwareClearFakeParameters,
done: testHardwareDone
};
if (callback) {
@ -68,32 +98,40 @@ var CameraTest = (function() {
}
function testEnd(callback) {
function allDone(cb) {
function cb2() {
SimpleTest.finish();
if (cb) {
cb();
}
// A chain of clean-up functions....
function allCleanedUp() {
SimpleTest.finish();
if (callback) {
callback();
}
}
function cleanUpTestEnabled() {
var next = allCleanedUp;
if (oldTestEnabled) {
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_ENABLED, oldTestEnabled]]}, cb2);
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_ENABLED, oldTestEnabled]]}, next);
} else {
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_ENABLED]]}, cb2);
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_ENABLED]]}, next);
}
}
function cleanUpTest() {
var next = cleanUpTestEnabled;
if (testMode) {
testMode.done(next);
testMode = null;
} else {
next();
}
}
function cleanUpExtraParameters() {
var next = cleanUpTest;
if (testMode) {
testMode.clearFakeParameters(next);
} else {
next();
}
}
if (testMode) {
testMode.done(function() {
allDone(callback);
});
testMode = null;
} else {
allDone(function() {
if (callback) {
callback();
}
});
}
cleanUpExtraParameters();
}
ise(SpecialPowers.sanityCheck(), "foo", "SpecialPowers passed sanity check");

View File

@ -7,3 +7,4 @@ support-files = camera_common.js
[test_camera_hardware_init_failure.html]
[test_camera_hardware_failures.html]
[test_bug975472.html]
[test_camera_fake_parameters.html]

View File

@ -0,0 +1,135 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for CameraParameters we need to fake</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=976802">Mozilla Bug 976802</a>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var initialConfig = {
mode: 'picture',
recorderProfile: 'cif',
previewSize: {
width: 352,
height: 288
}
};
var cameraObj = null;
// Shorthand functions
function end() {
CameraTest.end();
}
function next() {
CameraTest.next();
}
function run() {
CameraTest.run();
}
function onError(e) {
ok(false, "Error" + JSON.stringify(e));
}
// The array of tests
var tests = [
{
key: "fake-zoom",
prep: function setupFakeZoom(test) {
test.setFakeParameters("zoom-ratios=100,150,200,300,400;max-zoom=4", function() {
run();
});
},
test: function testFakeZoom(cam, cap) {
ok(cap.zoomRatios.length == 5, "zoom ratios length = " + cap.zoomRatios.length);
// test individual zoom ratios
cap.zoomRatios.forEach(function(zoom, index) {
cam.zoom = zoom;
ok(cam.zoom === zoom,
"zoom[" + index + "] = " + zoom + "x, cam.zoom = " + cam.zoom + "x");
});
// test below-lower-bound zoom ratio
var zoom = cap.zoomRatios[0] - 0.1;
cam.zoom = zoom;
ok(cam.zoom === cap.zoomRatios[0],
zoom + "x zoom clamps to minimum: " +
cap.zoomRatios[0] + "x, cam.zoom = " + cam.zoom + "x");
// test above-upper-bound zoom ratio
zoom = cap.zoomRatios.slice(-1)[0] + 1.0;
cam.zoom = zoom;
ok(cam.zoom === cap.zoomRatios.slice(-1)[0],
zoom + "x zoom clamps to maximum: " + cap.zoomRatios.slice(-1)[0] +
"x, cam.zoom = " + cam.zoom + "x");
// test snapping to supported zoom ratio
if (cap.zoomRatios.length > 1) {
zoom = (cap.zoomRatios[0] + cap.zoomRatios[1]) / 2;
cam.zoom = zoom;
ok(cam.zoom === cap.zoomRatios[0],
zoom + "x zoom rounded down to: " + cap.zoomRatios[0] +
"x, cam.zoom = " + cam.zoom + "x");
}
next();
}
},
];
var testGenerator = function() {
for (var i = 0; i < tests.length; ++i ) {
yield tests[i];
}
}();
window.addEventListener('beforeunload', function() {
document.getElementById('viewfinder').mozSrcObject = null;
cameraObj.release();
cameraObj = null;
});
CameraTest.begin("hardware", function(test) {
function onError(error) {
ok(false, "getCamera() failed with: " + error);
end();
}
CameraTest.next = function() {
try {
var t = testGenerator.next();
info("test: " + t.key);
function onSuccess(camera, config) {
cameraObj = camera;
t.test(camera, camera.capabilities);
}
CameraTest.run = function() {
navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError);
};
t.prep(test);
} catch(e) {
if (e instanceof StopIteration) {
end();
} else {
throw e;
}
}
};
next();
});
</script>
</body>
</html>

View File

@ -18,6 +18,7 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Preferences.h"
#include "mozilla/Scoped.h"
#include "mozilla/Services.h"
#include "nsAutoPtr.h"
@ -74,6 +75,10 @@ using namespace mozilla::ipc;
#include "nsDirectoryServiceDefs.h"
namespace mozilla {
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, PR_Close);
}
StaticAutoPtr<DeviceStorageUsedSpaceCache>
DeviceStorageUsedSpaceCache::sDeviceStorageUsedSpaceCache;
@ -933,14 +938,16 @@ DeviceStorageFile::AppendRelativePath(const nsAString& aPath) {
nsresult
DeviceStorageFile::CreateFileDescriptor(FileDescriptor& aFileDescriptor)
{
PRFileDesc* fd;
ScopedPRFileDesc fd;
nsresult rv = mFile->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE,
0660, &fd);
0660, &fd.rwget());
NS_ENSURE_SUCCESS(rv, rv);
// NOTE: The FileDescriptor::PlatformHandleType constructor returns a dup of
// the file descriptor, so we don't need the original fd after this.
// Our scoped file descriptor will automatically close fd.
aFileDescriptor =
FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd));
return NS_OK;
}

View File

@ -56,6 +56,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransfer)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransfer)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransfer)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(mozilla::dom::DataTransfer)
NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDataTransfer)

View File

@ -35,6 +35,10 @@
#include "TextComposition.h"
#include "mozilla/Preferences.h"
#include "nsAsyncDOMEvent.h"
#include "nsIDocShell.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsWeakReference.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -46,7 +50,10 @@ using namespace mozilla::widget;
// sTextStateObserver is null if there is no focused editor
class nsTextStateManager MOZ_FINAL : public nsISelectionListener,
public nsStubMutationObserver
public nsStubMutationObserver,
public nsIReflowObserver,
public nsIScrollObserver,
public nsSupportsWeakReference
{
public:
nsTextStateManager()
@ -61,6 +68,10 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIREFLOWOBSERVER
// nsIScrollObserver
virtual void ScrollPositionChanged() MOZ_OVERRIDE;
void Init(nsIWidget* aWidget,
nsPresContext* aPresContext,
@ -82,6 +93,7 @@ private:
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
void ObserveEditableNode();
nsCOMPtr<nsIDocShell> mDocShell;
nsIMEUpdatePreference mUpdatePreference;
uint32_t mPreAttrChangeLength;
};
@ -752,6 +764,8 @@ nsTextStateManager::Init(nsIWidget* aWidget,
return;
}
mDocShell = aPresContext->GetDocShell();
ObserveEditableNode();
}
@ -774,6 +788,13 @@ nsTextStateManager::ObserveEditableNode()
// add text change observer
mRootContent->AddMutationObserver(this);
}
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
// Add scroll position listener and reflow observer to detect position and
// size changes
mDocShell->AddWeakScrollObserver(this);
mDocShell->AddWeakReflowObserver(this);
}
}
void
@ -800,8 +821,13 @@ nsTextStateManager::Destroy(void)
if (mUpdatePreference.WantTextChange() && mRootContent) {
mRootContent->RemoveMutationObserver(this);
}
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
mDocShell->RemoveWeakScrollObserver(this);
mDocShell->RemoveWeakReflowObserver(this);
}
mRootContent = nullptr;
mEditableNode = nullptr;
mDocShell = nullptr;
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
}
@ -833,9 +859,12 @@ nsTextStateManager::IsEditorHandlingEventForComposition() const
return composition->IsEditorHandlingEvent();
}
NS_IMPL_ISUPPORTS2(nsTextStateManager,
NS_IMPL_ISUPPORTS5(nsTextStateManager,
nsIMutationObserver,
nsISelectionListener)
nsISelectionListener,
nsIReflowObserver,
nsIScrollObserver,
nsISupportsWeakReference)
// Helper class, used for selection change notification
class SelectionChangeEvent : public nsRunnable {
@ -917,6 +946,54 @@ private:
bool mCausedByComposition;
};
class PositionChangeEvent MOZ_FINAL : public nsRunnable
{
public:
PositionChangeEvent(nsTextStateManager* aDispatcher)
: mDispatcher(aDispatcher) {
MOZ_ASSERT(mDispatcher);
}
NS_IMETHOD Run() {
if (mDispatcher->mWidget) {
mDispatcher->mWidget->NotifyIME(
IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
}
return NS_OK;
}
private:
nsRefPtr<nsTextStateManager> mDispatcher;
};
void
nsTextStateManager::ScrollPositionChanged()
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
}
NS_IMETHODIMP
nsTextStateManager::Reflow(DOMHighResTimeStamp aStart,
DOMHighResTimeStamp aEnd)
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
return NS_OK;
}
NS_IMETHODIMP
nsTextStateManager::ReflowInterruptible(DOMHighResTimeStamp aStart,
DOMHighResTimeStamp aEnd)
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
return NS_OK;
}
void
nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,

View File

@ -694,6 +694,10 @@ nsresult nsGeolocationService::Init()
}
#endif
if (Preferences::GetBool("geo.provider.use_mls", false)) {
mProvider = do_GetService("@mozilla.org/geolocation/mls-provider;1");
}
// Override platform-specific providers with the default (network)
// provider while testing. Our tests are currently not meant to exercise
// the provider, and some tests rely on the network provider being used.

View File

@ -1,2 +1,3 @@
component {77DA64D3-7458-4920-9491-86CC9914F904} NetworkGeolocationProvider.js
contract @mozilla.org/geolocation/provider;1 {77DA64D3-7458-4920-9491-86CC9914F904}
contract @mozilla.org/geolocation/mls-provider;1 {77DA64D3-7458-4920-9491-86CC9914F904}

View File

@ -2102,6 +2102,30 @@ add_test(function test_error_message_update_icc_contact() {
run_next_test();
});
add_test(function test_process_icc_io_error() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let ioHelper = context.ICCIOHelper;
function do_test(errorCode, expectedErrorMsg) {
let called = false;
function errorCb(errorMsg) {
called = true;
do_check_eq(errorMsg, expectedErrorMsg);
}
ioHelper.processICCIOError({rilRequestError: errorCode,
onerror: errorCb});
do_check_true(called);
}
for (let i = 0; i < ERROR_REJECTED_BY_REMOTE + 1; i++) {
do_test(i, RIL_ERROR_TO_GECKO_ERROR[i]);
}
run_next_test();
});
add_test(function test_personalization_state() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];

View File

@ -38,13 +38,10 @@ UNIFIED_SOURCES += [
'OSFileConstants.cpp',
]
# On Systems that have build in geolocation providers,
# we really do not need these.
if CONFIG['OS_TARGET'] != 'Android' or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
EXTRA_COMPONENTS += [
'NetworkGeolocationProvider.js',
'NetworkGeolocationProvider.manifest',
]
EXTRA_COMPONENTS += [
'NetworkGeolocationProvider.js',
'NetworkGeolocationProvider.manifest',
]
FAIL_ON_WARNINGS = True

View File

@ -7,6 +7,8 @@
<script type="text/javascript">
SimpleTest.requestCompleteLog();
function checkException(func, exc)
{
var exceptionThrew = false;
@ -17,7 +19,7 @@ function checkException(func, exc)
exceptionThrew = true;
is(ex.name, exc, "Expected "+exc+" exception");
if (ex.name != exc) {
ok(true, "The exception which was thrown is: " + ex);
info("The exception which was thrown is: " + ex);
}
}
ok(exceptionThrew, "Exception "+exc+" threw");

View File

@ -25,7 +25,7 @@ interface DataTransfer {
[Throws]
void clearData(optional DOMString format);
[Throws]
readonly attribute FileList files;
readonly attribute FileList? files;
};
// Mozilla specific stuff

View File

@ -9544,81 +9544,84 @@
< smoulders
---
> smoulder/GSMD
44062c49892
43766a49597,49598
> snarkily
> snarky/TR
44062c49894
< sonofabitch
---
> sonofabitch/!
44346a50177
44346a50179
> spelled
44348a50180
44348a50182
> spelt
44371a50204
44371a50206
> spick/S!
44383c50216
44383c50218
< spik/S
---
> spik/S!
46106a51940
46106a51942
> syllabi
46160c51994
46160c51996
< synch/GMD
---
> synch/GMDS
46167d52000
46167d52002
< synchs
46203,46204c52036,52037
46203,46204c52038,52039
< sysadmin/S
< sysop/S
---
> sysadmin/MS
> sysop/MS
46752a52586
46752a52588
> terabit/MS
46753a52588,52589
46753a52590,52591
> terahertz/M
> terapixel/MS
46817a52654
46817a52656
> testcase/MS
46831a52669
46831a52671
> testsuite/MS
46925a52764
46925a52766
> theremin/MS
47455c53294
47455c53296
< toolbar
---
> toolbar/MS
47755a53595
47755a53597
> transfect/DSMG
47774a53615,53616
47774a53617,53618
> transgenderism
> transgene/MS
47951c53793
47951c53795
< triage/M
---
> triage/MG
48869a54712
48869a54714
> unlikeable
49211c55054
49211c55056
< vagina/M
---
> vagina/MS
49368,49369c55211
49368,49369c55213
< velour's
< velours's
---
> velour/MS
49478a55321
49478a55323
> vertices
50148a55992
50148a55994
> weaponize/DSG
50260,50261d56103
50260,50261d56105
< werwolf/M
< werwolves
50728c56570
50728c56572
< women
---
> women/M
50794c56636
50794c56638
< wop/S!
---
> wop/MS!

View File

@ -1,4 +1,4 @@
57458
57460
0/nm
0th/pt
1/n1
@ -49938,6 +49938,8 @@ snapshot/SM
snare/DSMG
snarf/SDG
snark/S
snarkily
snarky/TR
snarl's
snarl/USDG
snarling/Y

View File

@ -11,6 +11,7 @@
#include "nsPrintfCString.h"
#include "prenv.h"
#include "GLContext.h"
#include "gfxPrefs.h"
namespace mozilla {
namespace gl {
@ -32,13 +33,9 @@ static const char *sEGLExtensionNames[] = {
#if defined(ANDROID)
static bool sUseApitraceInitialized = false;
static bool sUseApitrace = false;
static PRLibrary* LoadApitraceLibrary()
{
MOZ_ASSERT(sUseApitraceInitialized);
if (!sUseApitrace) {
if (!gfxPrefs::UseApitrace()) {
return nullptr;
}
@ -101,13 +98,6 @@ GLLibraryEGL::EnsureInitialized()
return true;
}
#if defined(ANDROID)
if (!sUseApitraceInitialized) {
sUseApitrace = Preferences::GetBool("gfx.apitrace.enabled", false);
sUseApitraceInitialized = true;
}
#endif // ANDROID
mozilla::ScopedGfxFeatureReporter reporter("EGL");
#ifdef XP_WIN

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,6 @@ CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImp
CanvasLayer(aLayerManager, aImplData)
{
MOZ_COUNT_CTOR(CopyableCanvasLayer);
mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false);
}
CopyableCanvasLayer::~CopyableCanvasLayer()

View File

@ -58,7 +58,6 @@ protected:
bool mIsGLAlphaPremult;
bool mNeedsYFlip;
bool mForceReadback;
RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
nsRefPtr<gfxImageSurface> mDeprecatedCachedTempSurface;

View File

@ -17,7 +17,7 @@
#include "gfxColor.h"
#include "gfxContext.h"
#include "gfxUtils.h"
#include "gfxPlatform.h"
#include "gfxPrefs.h"
#include "nsIWidget.h"
#include "GLContext.h"
@ -637,7 +637,7 @@ NS_IMPL_ISUPPORTS1(DebugDataSender, nsIRunnable);
void
LayerScope::CreateServerSocket()
{
if (!Preferences::GetBool("gfx.layerscope.enabled", false)) {
if (!gfxPrefs::LayerScopeEnabled()) {
return;
}
@ -814,7 +814,7 @@ LayerScopeWebSocketManager::LayerScopeWebSocketManager()
NS_NewThread(getter_AddRefs(mDebugSenderThread));
mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
int port = Preferences::GetInt("gfx.layerscope.port", 23456);
int port = gfxPrefs::LayerScopePort();
mServerSocket->Init(port, false, -1);
mServerSocket->AsyncListen(new DebugListener);
}

View File

@ -59,14 +59,12 @@ AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource, const gfx3D
while ((r = iter.Next())) {
aDest.Or(aDest, TransformRect(*r, aTransform));
}
aDest.SimplifyOutward(4);
}
static void
AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource)
{
aDest.Or(aDest, aSource);
aDest.SimplifyOutward(4);
}
static nsIntRegion

View File

@ -89,7 +89,7 @@ enum LayerRenderStateFlags {
struct LayerRenderState {
LayerRenderState()
#ifdef MOZ_WIDGET_GONK
: mSurface(nullptr), mFlags(0), mHasOwnOffset(false), mTexture(nullptr)
: mSurface(nullptr), mTexture(nullptr), mFlags(0), mHasOwnOffset(false)
#endif
{}
@ -100,9 +100,9 @@ struct LayerRenderState {
TextureHost* aTexture)
: mSurface(aSurface)
, mSize(aSize)
, mTexture(aTexture)
, mFlags(aFlags)
, mHasOwnOffset(false)
, mTexture(aTexture)
{}
bool YFlipped() const

View File

@ -125,17 +125,24 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget,
}
if (aMask) {
Matrix oldTransform = aTarget->GetTransform();
// Transform from user -> buffer space.
Matrix transform;
transform.Translate(quadrantTranslation.x, quadrantTranslation.y);
Matrix inverseMask = *aMaskTransform;
inverseMask.Invert();
transform *= oldTransform;
transform *= inverseMask;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
SurfacePattern source(snapshot, ExtendMode::CLAMP, transform, Filter::POINT);
#else
SurfacePattern source(snapshot, ExtendMode::CLAMP, transform);
#endif
Matrix oldTransform = aTarget->GetTransform();
aTarget->SetTransform(*aMaskTransform);
aTarget->MaskSurface(source, aMask, Point(0, 0), DrawOptions(aOpacity, aOperator));
aTarget->SetTransform(oldTransform);

View File

@ -53,7 +53,6 @@ public:
NS_ASSERTION(BasicManager()->InConstruction(),
"Can only set properties in construction phase");
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(10);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
}

View File

@ -20,7 +20,8 @@ using namespace mozilla::layers;
TextureClientX11::TextureClientX11(SurfaceFormat aFormat, TextureFlags aFlags)
: TextureClient(aFlags),
mFormat(aFormat)
mFormat(aFormat),
mLocked(false)
{
MOZ_COUNT_CTOR(TextureClientX11);
}

View File

@ -25,6 +25,7 @@
#ifdef XP_MACOSX
#include "SharedSurfaceIO.h"
#endif
#include "gfxPrefs.h" // for WebGLForceLayersReadback
using namespace mozilla::gfx;
using namespace mozilla::gl;
@ -45,7 +46,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
screen->PreserveBuffer());
SurfaceFactory_GL* factory = nullptr;
if (!mForceReadback) {
if (!gfxPrefs::WebGLForceLayersReadback()) {
if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
if (mGLContext->GetContextType() == GLContextType::EGL) {
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);

View File

@ -259,8 +259,8 @@ ClientLayerManager::GetRemoteRenderer()
void
ClientLayerManager::Composite()
{
if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
remoteRenderer->SendForceComposite();
if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) {
manager->SendForceComposite();
}
}

View File

@ -60,7 +60,6 @@ public:
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(10);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
}

View File

@ -13,6 +13,7 @@
#include "SharedSurfaceANGLE.h"
#include "gfxContext.h"
#include "GLContext.h"
#include "gfxPrefs.h"
using namespace mozilla::gl;
using namespace mozilla::gfx;
@ -28,7 +29,6 @@ CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager)
, mHasAlpha(true)
{
mImplData = static_cast<LayerD3D10*>(this);
mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false);
}
CanvasLayerD3D10::~CanvasLayerD3D10()
@ -52,7 +52,7 @@ CanvasLayerD3D10::Initialize(const Data& aData)
screen->PreserveBuffer());
SurfaceFactory_GL* factory = nullptr;
if (!mForceReadback) {
if (!gfxPrefs::WebGLForceLayersReadback()) {
if (mGLContext->IsANGLE()) {
factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext,
device(),

View File

@ -50,7 +50,6 @@ private:
bool mNeedsYFlip;
bool mIsD2DTexture;
bool mHasAlpha;
bool mForceReadback;
nsAutoArrayPtr<uint8_t> mCachedTempBlob;
uint32_t mCachedTempBlob_Size;

View File

@ -52,7 +52,6 @@ void
ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
{
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(10);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
}

View File

@ -337,13 +337,6 @@ CompositorParent::RecvFlushRendering()
return true;
}
bool
CompositorParent::RecvForceComposite()
{
ScheduleComposition();
return true;
}
bool
CompositorParent::RecvNotifyRegionInvalidated(const nsIntRegion& aRegion)
{
@ -758,6 +751,12 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
mLayerManager->NotifyShadowTreeTransaction();
}
void
CompositorParent::ForceComposite(LayerTransactionParent* aLayerTree)
{
ScheduleComposition();
}
void
CompositorParent::InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints)
{
@ -1017,7 +1016,6 @@ public:
SurfaceDescriptor* aOutSnapshot)
{ return true; }
virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
virtual bool RecvForceComposite() MOZ_OVERRIDE { return true; }
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) { return true; }
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE { return true; }
virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) MOZ_OVERRIDE { return true; }
@ -1036,6 +1034,7 @@ public:
const TargetConfig& aTargetConfig,
bool aIsFirstPaint,
bool aScheduleComposite) MOZ_OVERRIDE;
virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) MOZ_OVERRIDE;
@ -1188,6 +1187,14 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite);
}
void
CrossProcessCompositorParent::ForceComposite(LayerTransactionParent* aLayerTree)
{
uint64_t id = aLayerTree->GetId();
MOZ_ASSERT(id != 0);
sIndirectLayerTrees[id].mParent->ForceComposite(aLayerTree);
}
AsyncCompositionManager*
CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLayerTree)
{

View File

@ -88,7 +88,6 @@ public:
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
SurfaceDescriptor* aOutSnapshot) MOZ_OVERRIDE;
virtual bool RecvFlushRendering() MOZ_OVERRIDE;
virtual bool RecvForceComposite() MOZ_OVERRIDE;
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE;
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE;
@ -102,6 +101,7 @@ public:
const TargetConfig& aTargetConfig,
bool aIsFirstPaint,
bool aScheduleComposite) MOZ_OVERRIDE;
virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE { return mCompositionManager; }
/**
* This forces the is-first-paint flag to true. This is intended to

View File

@ -648,6 +648,14 @@ LayerTransactionParent::RecvClearCachedResources()
return true;
}
bool
LayerTransactionParent::RecvForceComposite()
{
mShadowLayersManager->ForceComposite(this);
return true;
}
PGrallocBufferParent*
LayerTransactionParent::AllocPGrallocBufferParent(const IntSize& aSize,
const uint32_t& aFormat,

View File

@ -90,6 +90,7 @@ protected:
const bool& scheduleComposite) MOZ_OVERRIDE;
virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
virtual bool RecvForceComposite() MOZ_OVERRIDE;
virtual bool RecvGetOpacity(PLayerParent* aParent,
float* aOpacity) MOZ_OVERRIDE;
virtual bool RecvGetTransform(PLayerParent* aParent,

View File

@ -69,9 +69,6 @@ parent:
// block until they are completed.
sync FlushRendering();
// Schedule a composite if one isn't already scheduled.
async ForceComposite();
sync StartFrameTimeRecording(int32_t bufferSize)
returns (uint32_t startIndex);

View File

@ -85,6 +85,9 @@ parent:
// Drop any front buffers that might be retained on the compositor
// side.
async ClearCachedResources();
// Schedule a composite if one isn't already scheduled.
async ForceComposite();
async __delete__();
};

View File

@ -23,6 +23,8 @@ public:
bool aScheduleComposite) = 0;
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) { return nullptr; }
virtual void ForceComposite(LayerTransactionParent* aLayerTree) { }
};
} // layers

View File

@ -307,7 +307,6 @@ private:
// Textures used for direct texturing of buffers like gralloc.
// The index of the texture in this array must correspond to the texture unit.
nsTArray<GLuint> mTextures;
static bool sDrawFPS;
/**
* Height of the OpenGL context's primary framebuffer in pixels. Used by

View File

@ -100,7 +100,7 @@ load 783041-2.html
load 783041-3.html
load 783041-4.html
asserts-if(gtk2Widget,1) load 798853.html # bug 868792
asserts-if(winWidget,0-1) skip-if(B2G) load 815489.html
asserts-if(winWidget,0-1) skip-if(B2G) skip-if(Android&&AndroidVersion==10) load 815489.html # bug 978277
load 836225-1.html
load 839745-1.html
load 856784-1.html

View File

@ -16,6 +16,7 @@
#include "base/task.h"
#include "Layers.h"
#include "TestLayers.h"
#include "gfxPrefs.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -29,6 +30,26 @@ using ::testing::InSequence;
class Task;
class AsyncPanZoomControllerTester : public ::testing::Test {
protected:
virtual void SetUp() {
gfxPrefs::One();
}
virtual void TearDown() {
gfxPrefs::Destroy();
}
};
class APZCTreeManagerTester : public ::testing::Test {
protected:
virtual void SetUp() {
gfxPrefs::One();
}
virtual void TearDown() {
gfxPrefs::Destroy();
}
};
class MockContentController : public GeckoContentController {
public:
MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
@ -544,7 +565,7 @@ TEST(AsyncPanZoomController, ComplexTransform) {
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
}
TEST(AsyncPanZoomController, Pan) {
TEST_F(AsyncPanZoomControllerTester, Pan) {
DoPanTest(true, false, mozilla::layers::AllowedTouchBehavior::NONE);
}
@ -553,24 +574,24 @@ TEST(AsyncPanZoomController, Pan) {
// According to the pointer-events/touch-action spec AUTO and PAN_Y touch-action values allow vertical
// scrolling while NONE and PAN_X forbid it. The first parameter of DoPanTest method specifies this
// behavior.
TEST(AsyncPanZoomController, PanWithTouchActionAuto) {
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionAuto) {
DoPanTest(true, true,
mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN | mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
}
TEST(AsyncPanZoomController, PanWithTouchActionNone) {
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionNone) {
DoPanTest(false, true, 0);
}
TEST(AsyncPanZoomController, PanWithTouchActionPanX) {
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionPanX) {
DoPanTest(false, true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN);
}
TEST(AsyncPanZoomController, PanWithTouchActionPanY) {
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionPanY) {
DoPanTest(true, true, mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
}
TEST(AsyncPanZoomController, PanWithPreventDefault) {
TEST_F(AsyncPanZoomControllerTester, PanWithPreventDefault) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
@ -608,7 +629,7 @@ TEST(AsyncPanZoomController, PanWithPreventDefault) {
apzc->Destroy();
}
TEST(AsyncPanZoomController, Fling) {
TEST_F(AsyncPanZoomControllerTester, Fling) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
@ -638,7 +659,7 @@ TEST(AsyncPanZoomController, Fling) {
}
}
TEST(AsyncPanZoomController, OverScrollPanning) {
TEST_F(AsyncPanZoomControllerTester, OverScrollPanning) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
@ -999,7 +1020,7 @@ TEST(APZCTreeManager, HitTesting1) {
}
// A more involved hit testing test that involves css and async transforms.
TEST(APZCTreeManager, HitTesting2) {
TEST_F(APZCTreeManagerTester, HitTesting2) {
nsTArray<nsRefPtr<Layer> > layers;
nsRefPtr<LayerManager> lm;
nsRefPtr<Layer> root = CreateTestLayerTree2(lm, layers);

View File

@ -5040,15 +5040,15 @@ gfxFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh,
// Don't switch fonts for control characters, regardless of
// whether they are present in the current font, as they won't
// actually be rendered (see bug 716229)
uint8_t category = GetGeneralCategory(aCh);
if (category == HB_UNICODE_GENERAL_CATEGORY_CONTROL) {
if (isJoinControl ||
GetGeneralCategory(aCh) == HB_UNICODE_GENERAL_CATEGORY_CONTROL) {
nsRefPtr<gfxFont> ret = aPrevMatchedFont;
return ret.forget();
}
// if this character is a join-control or the previous is a join-causer,
// if previous character was a join-causer (ZWJ),
// use the same font as the previous range if we can
if (isJoinControl || wasJoinCauser) {
if (wasJoinCauser) {
if (aPrevMatchedFont->HasCharacter(aCh)) {
nsRefPtr<gfxFont> ret = aPrevMatchedFont;
return ret.forget();
@ -5132,7 +5132,6 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
NS_ASSERTION(aLength > 0, "don't call ComputeRanges for zero-length text");
uint32_t prevCh = 0;
uint8_t matchType = 0;
int32_t lastRangeIndex = -1;
// initialize prevFont to the group's primary font, so that this will be
@ -5140,6 +5139,10 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
// fallback for these (bug 716229)
gfxFont *prevFont = GetFontAt(0);
// if we use the initial value of prevFont, we treat this as a match from
// the font group; fixes bug 978313
uint8_t matchType = gfxTextRange::kFontGroup;
for (uint32_t i = 0; i < aLength; i++) {
const uint32_t origI = i; // save off in case we increase for surrogate

View File

@ -1303,6 +1303,11 @@ private:
GlyphWidths mContainedGlyphWidths;
nsTHashtable<HashEntry> mTightGlyphExtents;
int32_t mAppUnitsPerDevUnit;
private:
// not implemented:
gfxGlyphExtents(const gfxGlyphExtents& aOther) MOZ_DELETE;
gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) MOZ_DELETE;
};
/**

View File

@ -1275,7 +1275,11 @@ gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
uint32_t aPlatformCode, uint32_t aScriptCode,
uint32_t aLangCode, nsAString& aName)
{
NS_ASSERTION(aByteLen > 0, "bad length for font name data");
if (aByteLen <= 0) {
NS_WARNING("empty font name");
aName.SetLength(0);
return true;
}
const char *csName = GetCharsetForFontName(aPlatformCode, aScriptCode, aLangCode);

View File

@ -534,14 +534,6 @@ gfxPlatform::~gfxPlatform()
cairo_debug_reset_static_data();
#endif
#endif
#if 0
// It would be nice to do this (although it might need to be after
// the cairo shutdown that happens in ~gfxPlatform). It even looks
// idempotent. But it has fatal assertions that fire if stuff is
// leaked, and we hit them.
FcFini();
#endif
}
bool

View File

@ -75,14 +75,6 @@ gfxPlatformGtk::~gfxPlatformGtk()
sFontconfigUtils = nullptr;
gfxPangoFontGroup::Shutdown();
#if 0
// It would be nice to do this (although it might need to be after
// the cairo shutdown that happens in ~gfxPlatform). It even looks
// idempotent. But it has fatal assertions that fire if stuff is
// leaked, and we hit them.
FcFini();
#endif
}
already_AddRefed<gfxASurface>

View File

@ -102,6 +102,9 @@ private:
// We will keep these in an alphabetical order to make it easier to see if
// a method accessing a pref already exists. Just add yours in the list.
#if defined(ANDROID)
DECL_GFX_PREF(Once, "gfx.apitrace.enabled", UseApitrace, bool, false);
#endif
DECL_GFX_PREF(Live, "gfx.canvas.azure.accelerated", CanvasAzureAccelerated, bool, false);
DECL_GFX_PREF(Once, "gfx.canvas.skiagl.dynamic-cache", CanvasSkiaGLDynamicCache, bool, false);
DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-size", CanvasSkiaGLCacheSize, int32_t, 96);
@ -109,6 +112,8 @@ private:
DECL_GFX_PREF(Once, "gfx.direct2d.disabled", Direct2DDisabled, bool, false);
DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled", Direct2DForceEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.layerscope.enabled", LayerScopeEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.layerscope.port", LayerScopePort, int32_t, 23456);
DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true);
DECL_GFX_PREF(Live, "gl.msaa-level", MSAALevel, uint32_t, 2);
@ -154,6 +159,8 @@ private:
DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false);
public:
// Manage the singleton:
static gfxPrefs& One()

View File

@ -241,8 +241,17 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrateg
return; /* I/O suspension */
}
int sampleSize = mImage.GetRequestedSampleSize();
if (sampleSize > 0) {
mInfo.scale_num = 1;
mInfo.scale_denom = sampleSize;
}
/* Used to set up image size so arrays can be allocated */
jpeg_calc_output_dimensions(&mInfo);
// Post our size to the superclass
PostSize(mInfo.image_width, mInfo.image_height, ReadOrientationFromEXIF());
PostSize(mInfo.output_width, mInfo.output_height, ReadOrientationFromEXIF());
if (HasError()) {
// Setting the size led to an error.
mState = JPEG_ERROR;
@ -375,9 +384,6 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrateg
*/
mInfo.buffered_image = mDecodeStyle == PROGRESSIVE && jpeg_has_multiple_scans(&mInfo);
/* Used to set up image size so arrays can be allocated */
jpeg_calc_output_dimensions(&mInfo);
if (!mImageData) {
mState = JPEG_ERROR;
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
@ -388,7 +394,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrateg
PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
(" JPEGDecoderAccounting: nsJPEGDecoder::Write -- created image frame with %ux%u pixels",
mInfo.image_width, mInfo.image_height));
mInfo.output_width, mInfo.output_height));
mState = JPEG_START_DECOMPRESS;
}

View File

@ -19,6 +19,8 @@
#include "VectorImage.h"
#include "Image.h"
#include "nsMediaFragmentURIParser.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "ImageFactory.h"
@ -29,6 +31,7 @@ namespace image {
static bool gInitializedPrefCaches = false;
static bool gDecodeOnDraw = false;
static bool gDiscardable = false;
static bool gEnableMozSampleSize = false;
/*static*/ void
ImageFactory::Initialize()
@ -37,6 +40,7 @@ ImageFactory::Initialize()
if (!gInitializedPrefCaches) {
Preferences::AddBoolVarCache(&gDiscardable, "image.mem.discardable");
Preferences::AddBoolVarCache(&gDecodeOnDraw, "image.mem.decodeondraw");
Preferences::AddBoolVarCache(&gEnableMozSampleSize, "image.mozsamplesize.enabled");
gInitializedPrefCaches = true;
}
}
@ -212,6 +216,22 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
newImage->SetRequestedResolution(parser.GetResolution());
}
if (parser.HasSampleSize()) {
/* Get our principal */
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
nsCOMPtr<nsIPrincipal> principal;
if (chan) {
nsContentUtils::GetSecurityManager()->GetChannelPrincipal(chan,
getter_AddRefs(principal));
}
if ((principal &&
principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED) ||
gEnableMozSampleSize) {
newImage->SetRequestedSampleSize(parser.GetSampleSize());
}
}
return newImage.forget();
}

Some files were not shown because too many files have changed in this diff Show More