mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Merge latest green fx-team changeset and mozilla-central
This commit is contained in:
commit
031fb4f43b
@ -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);
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"branch": "",
|
||||
"revision": ""
|
||||
},
|
||||
"revision": "d0ed050535c3a5337c09c0de720de78954a42f31",
|
||||
"revision": "3d294ffa51afd8a8daafcdaa97cda8e38de81cb8",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
114
browser/base/content/test/general/browser_star_hsts.js
Normal file
114
browser/base/content/test/general/browser_star_hsts.js
Normal 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;
|
||||
}
|
13
browser/base/content/test/general/browser_star_hsts.sjs
Normal file
13
browser/base/content/test/general/browser_star_hsts.sjs
Normal 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);
|
||||
}
|
@ -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.
|
||||
|
17
configure.in
17
configure.in
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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>
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
81
content/html/content/test/forms/test_input_defaultValue.html
Normal file
81
content/html/content/test/forms/test_input_defaultValue.html
Normal 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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ XPIDL_MODULE = 'docshell'
|
||||
EXPORTS += [
|
||||
'nsDocShellLoadTypes.h',
|
||||
'nsILinkHandler.h',
|
||||
'nsIScrollObserver.h',
|
||||
'nsIWebShellServices.h',
|
||||
'SerializedLoadContext.h',
|
||||
]
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.)
|
||||
|
@ -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.)
|
||||
|
28
docshell/base/nsIScrollObserver.h
Normal file
28
docshell/base/nsIScrollObserver.h
Normal 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___ */
|
@ -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>
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
@ -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,
|
||||
|
@ -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 = {
|
||||
|
@ -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,
|
||||
|
@ -247,4 +247,4 @@ addLoadEvent(go);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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]
|
||||
|
32
dom/base/test/test_bug978522.html
Normal file
32
dom/base/test/test_bug978522.html
Normal 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>
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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]
|
||||
|
135
dom/camera/test/test_camera_fake_parameters.html
Normal file
135
dom/camera/test/test_camera_fake_parameters.html
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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}
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -25,7 +25,7 @@ interface DataTransfer {
|
||||
[Throws]
|
||||
void clearData(optional DOMString format);
|
||||
[Throws]
|
||||
readonly attribute FileList files;
|
||||
readonly attribute FileList? files;
|
||||
};
|
||||
|
||||
// Mozilla specific stuff
|
||||
|
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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
@ -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()
|
||||
|
@ -58,7 +58,6 @@ protected:
|
||||
|
||||
bool mIsGLAlphaPremult;
|
||||
bool mNeedsYFlip;
|
||||
bool mForceReadback;
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
|
||||
nsRefPtr<gfxImageSurface> mDeprecatedCachedTempSurface;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -259,8 +259,8 @@ ClientLayerManager::GetRemoteRenderer()
|
||||
void
|
||||
ClientLayerManager::Composite()
|
||||
{
|
||||
if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
|
||||
remoteRenderer->SendForceComposite();
|
||||
if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) {
|
||||
manager->SendForceComposite();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -50,7 +50,6 @@ private:
|
||||
bool mNeedsYFlip;
|
||||
bool mIsD2DTexture;
|
||||
bool mHasAlpha;
|
||||
bool mForceReadback;
|
||||
|
||||
nsAutoArrayPtr<uint8_t> mCachedTempBlob;
|
||||
uint32_t mCachedTempBlob_Size;
|
||||
|
@ -52,7 +52,6 @@ void
|
||||
ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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__();
|
||||
};
|
||||
|
@ -23,6 +23,8 @@ public:
|
||||
bool aScheduleComposite) = 0;
|
||||
|
||||
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) { return nullptr; }
|
||||
|
||||
virtual void ForceComposite(LayerTransactionParent* aLayerTree) { }
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user