mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound. a=merge
This commit is contained in:
commit
a1155fd152
@ -254,7 +254,7 @@ endif # MOZ_CRASHREPORTER
|
||||
uploadsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
|
||||
$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
|
||||
$(PYTHON) -u $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
|
||||
else
|
||||
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
|
||||
endif
|
||||
|
@ -316,7 +316,7 @@ pref("browser.urlbar.autoFill", true);
|
||||
pref("browser.urlbar.autoFill.typed", true);
|
||||
|
||||
// Use the new unifiedComplete component
|
||||
pref("browser.urlbar.unifiedcomplete", false);
|
||||
pref("browser.urlbar.unifiedcomplete", true);
|
||||
|
||||
// 0: Match anywhere (e.g., middle of words)
|
||||
// 1: Match on word boundaries and then try matching anywhere
|
||||
|
@ -143,8 +143,12 @@ const gXPInstallObserver = {
|
||||
cancelButton.accessKey = gNavigatorBundle.getString("addonInstall.cancelButton.accesskey");
|
||||
|
||||
let acceptButton = document.getElementById("addon-progress-accept");
|
||||
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
|
||||
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
|
||||
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
|
||||
} else {
|
||||
acceptButton.hidden = true;
|
||||
}
|
||||
break; }
|
||||
case "addon-install-failed": {
|
||||
// TODO This isn't terribly ideal for the multiple failure case
|
||||
|
@ -15,6 +15,9 @@ var FullScreen = {
|
||||
init: function() {
|
||||
// called when we go into full screen, even if initiated by a web page script
|
||||
window.addEventListener("fullscreen", this, true);
|
||||
window.addEventListener("MozDOMFullscreen:Exited", this,
|
||||
/* useCapture */ true,
|
||||
/* wantsUntrusted */ false);
|
||||
for (let type of this._MESSAGES) {
|
||||
window.messageManager.addMessageListener(type, this);
|
||||
}
|
||||
@ -97,6 +100,9 @@ var FullScreen = {
|
||||
if (event.propertyName == "opacity")
|
||||
this.cancelWarning();
|
||||
break;
|
||||
case "MozDOMFullscreen:Exited":
|
||||
this.cleanupDomFullscreen();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -125,15 +131,7 @@ var FullScreen = {
|
||||
if (this._isRemoteBrowser(browser)) {
|
||||
this._windowUtils.remoteFrameFullscreenReverted();
|
||||
}
|
||||
document.documentElement.removeAttribute("inDOMFullscreen");
|
||||
this.cleanupDomFullscreen();
|
||||
this.showNavToolbox();
|
||||
// If we are still in fullscreen mode, re-hide
|
||||
// the toolbox with animation.
|
||||
if (window.fullScreen) {
|
||||
this._shouldAnimate = true;
|
||||
this.hideNavToolbox();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -189,8 +187,6 @@ var FullScreen = {
|
||||
document.removeEventListener("keypress", this._keyToggleCallback, false);
|
||||
document.removeEventListener("popupshown", this._setPopupOpen, false);
|
||||
document.removeEventListener("popuphidden", this._setPopupOpen, false);
|
||||
|
||||
this.cleanupDomFullscreen();
|
||||
}
|
||||
},
|
||||
|
||||
@ -202,6 +198,15 @@ var FullScreen = {
|
||||
if (!this.useLionFullScreen)
|
||||
window.removeEventListener("activate", this);
|
||||
|
||||
document.documentElement.removeAttribute("inDOMFullscreen");
|
||||
this.showNavToolbox();
|
||||
// If we are still in fullscreen mode, re-hide
|
||||
// the toolbox with animation.
|
||||
if (window.fullScreen) {
|
||||
this._shouldAnimate = true;
|
||||
this.hideNavToolbox();
|
||||
}
|
||||
|
||||
window.messageManager
|
||||
.broadcastAsyncMessage("DOMFullscreen:CleanUp");
|
||||
},
|
||||
|
@ -2367,7 +2367,9 @@ function BrowserViewSourceOfDocument(aArgsOrDocument) {
|
||||
// In the case of sidebars and chat windows, gBrowser is defined but null,
|
||||
// because no #content element exists. For these cases, we need to find
|
||||
// the most recent browser window.
|
||||
if (!tabBrowser) {
|
||||
// In the case of popups, we need to find a non-popup browser window.
|
||||
if (!tabBrowser || !window.toolbar.visible) {
|
||||
// This returns only non-popup browser windows by default.
|
||||
let browserWindow = RecentWindow.getMostRecentBrowserWindow();
|
||||
tabBrowser = browserWindow.gBrowser;
|
||||
}
|
||||
|
@ -1011,7 +1011,9 @@ nsContextMenu.prototype = {
|
||||
// In the case of sidebars and chat windows, gBrowser is defined but null,
|
||||
// because no #content element exists. For these cases, we need to find
|
||||
// the most recent browser window.
|
||||
if (!tabBrowser) {
|
||||
// In the case of popups, we need to find a non-popup browser window.
|
||||
if (!tabBrowser || !window.toolbar.visible) {
|
||||
// This returns only non-popup browser windows by default.
|
||||
let browserWindow = RecentWindow.getMostRecentBrowserWindow();
|
||||
tabBrowser = browserWindow.gBrowser;
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ skip-if = asan # Disabled because it takes a long time (see test for more inform
|
||||
[browser_popupUI.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_popup_blocker.js]
|
||||
skip-if = e10s && debug # Frequent bug 1125520 failures
|
||||
skip-if = (os == 'linux') || (e10s && debug) # Frequent bug 1081925 and bug 1125520 failures
|
||||
[browser_printpreview.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1101973 - breaks the next test in e10s, and may be responsible for later timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost"
|
||||
[browser_private_browsing_window.js]
|
||||
|
@ -2,4 +2,4 @@
|
||||
# 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/.
|
||||
|
||||
MOZ_APP_DISPLAYNAME=MozillaDeveloperPreview
|
||||
MOZ_APP_DISPLAYNAME=Nightly
|
||||
|
@ -2,8 +2,8 @@
|
||||
- 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/. -->
|
||||
|
||||
<!ENTITY brandShorterName "Mozilla Developer Preview">
|
||||
<!ENTITY brandShortName "Mozilla Developer Preview">
|
||||
<!ENTITY brandFullName "Mozilla Developer Preview">
|
||||
<!ENTITY vendorShortName "mozilla.org">
|
||||
<!ENTITY brandShorterName "Nightly">
|
||||
<!ENTITY brandShortName "Nightly">
|
||||
<!ENTITY brandFullName "Nightly">
|
||||
<!ENTITY vendorShortName "Mozilla">
|
||||
<!ENTITY trademarkInfo.part1 " ">
|
||||
|
@ -2,9 +2,9 @@
|
||||
# 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/.
|
||||
|
||||
brandShorterName=Mozilla Developer Preview
|
||||
brandShortName=Mozilla Developer Preview
|
||||
brandFullName=Mozilla Developer Preview
|
||||
vendorShortName=mozilla.org
|
||||
brandShorterName=Nightly
|
||||
brandShortName=Nightly
|
||||
brandFullName=Nightly
|
||||
vendorShortName=Mozilla
|
||||
|
||||
syncBrandShortName=Sync
|
||||
|
@ -163,7 +163,7 @@ loop.conversation = (function(mozL10n) {
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop}), document.querySelector("#main"));
|
||||
|
||||
document.body.setAttribute("dir", "rtl");//mozL10n.getDirection());
|
||||
document.body.setAttribute("dir", mozL10n.getDirection());
|
||||
document.body.setAttribute("platform", loop.shared.utils.getPlatform());
|
||||
|
||||
dispatcher.dispatch(new sharedActions.GetWindowData({
|
||||
|
@ -163,7 +163,7 @@ loop.conversation = (function(mozL10n) {
|
||||
dispatcher={dispatcher}
|
||||
mozLoop={navigator.mozLoop} />, document.querySelector("#main"));
|
||||
|
||||
document.body.setAttribute("dir", "rtl");//mozL10n.getDirection());
|
||||
document.body.setAttribute("dir", mozL10n.getDirection());
|
||||
document.body.setAttribute("platform", loop.shared.utils.getPlatform());
|
||||
|
||||
dispatcher.dispatch(new sharedActions.GetWindowData({
|
||||
|
@ -17,23 +17,41 @@
|
||||
<link rel="localization" href="l10n/{locale}/loop.properties">
|
||||
|
||||
<script>
|
||||
// window.navigator.doNotTrack "yes" is for old versions of FF
|
||||
// window.navigator.doNotTrack "1" is for current versions of FF + Chrome + Opera
|
||||
// window.doNotTrack is safari
|
||||
// window.navigator.msDoNotTrack
|
||||
if (window.navigator.doNotTrack !== "yes" &&
|
||||
window.navigator.doNotTrack !== "1" &&
|
||||
window.doNotTrack !== "1" &&
|
||||
window.navigator.msDoNotTrack !== "1") {
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
(function() {
|
||||
function insertScript(url) {
|
||||
var node = document.createElement("script");
|
||||
var sibling = document.getElementsByTagName("script")[0];
|
||||
node.async = 1;
|
||||
node.src = url;
|
||||
sibling.parentNode.insertBefore(node, sibling);
|
||||
}
|
||||
|
||||
ga('create', 'UA-36116321-15', 'auto');
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
// window.navigator.doNotTrack "yes" is for old versions of FF
|
||||
// window.navigator.doNotTrack "1" is for current versions of FF + Chrome + Opera
|
||||
// window.doNotTrack is safari
|
||||
// window.navigator.msDoNotTrack
|
||||
if (window.navigator.doNotTrack !== "yes" &&
|
||||
window.navigator.doNotTrack !== "1" &&
|
||||
window.doNotTrack !== "1" &&
|
||||
window.navigator.msDoNotTrack !== "1") {
|
||||
|
||||
insertScript("//cdn.optimizely.com/js/2768540301.js");
|
||||
|
||||
// This is an unfolded, readable version of the official GA inclusion
|
||||
// script.
|
||||
window.GoogleAnalyticsObject = "ga";
|
||||
window.ga = window.ga || function() {
|
||||
(window.ga.q = window.ga.q || []).push(arguments);
|
||||
};
|
||||
window.ga.l = 1 * new Date();
|
||||
|
||||
insertScript("//www.google-analytics.com/analytics.js");
|
||||
|
||||
window.ga("create", "UA-36116321-15", "auto");
|
||||
window.ga("set", "anonymizeIp", true);
|
||||
window.ga("send", "pageview");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
</head>
|
||||
@ -60,14 +78,14 @@
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
||||
return evt;
|
||||
};
|
||||
}
|
||||
|
||||
myCustomEvent.prototype = window.Event.prototype;
|
||||
window.CustomEvent = myCustomEvent;
|
||||
}
|
||||
|
||||
// To support IE for the l10n-gaia library on IE <= 10.
|
||||
if (!"language" in navigator) {
|
||||
if (!("language" in navigator)) {
|
||||
navigator.language = navigator.browserLanguage;
|
||||
}
|
||||
|
||||
@ -76,21 +94,21 @@
|
||||
// Define a dummy MutationObserver object if one doesn't exist
|
||||
// This could later be extended to use Mutation events but for
|
||||
// now this will simply result in no-ops.
|
||||
function myMutationObserver() {};
|
||||
function myMutationObserver() {}
|
||||
myMutationObserver.prototype = {
|
||||
disconnect: function() {},
|
||||
observe: function () {},
|
||||
takeRecords: function() {},
|
||||
takeRecords: function() {}
|
||||
};
|
||||
window.MutationObserver = myMutationObserver;
|
||||
}
|
||||
|
||||
window.OTProperties = {
|
||||
cdnURL: 'shared/libs/',
|
||||
cdnURL: "shared/libs/"
|
||||
};
|
||||
window.OTProperties.assetURL = window.OTProperties.cdnURL + 'sdk-content/';
|
||||
window.OTProperties.configURL = window.OTProperties.assetURL + 'js/dynamic_config.min.js';
|
||||
window.OTProperties.cssURL = window.OTProperties.assetURL + 'css/ot.css';
|
||||
window.OTProperties.assetURL = window.OTProperties.cdnURL + "sdk-content/";
|
||||
window.OTProperties.configURL = window.OTProperties.assetURL + "js/dynamic_config.min.js";
|
||||
window.OTProperties.cssURL = window.OTProperties.assetURL + "css/ot.css";
|
||||
</script>
|
||||
<script type="text/javascript" src="js/multiplexGum.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/sdk.js"></script>
|
||||
@ -99,7 +117,7 @@
|
||||
// defined until after sdk.js has been evaluated. This updates the
|
||||
// navigator object to reference TBPlugin if it was defined by sdk.js.
|
||||
if (!navigator.originalGum) {
|
||||
navigator.originalGum = (window["TBPlugin"] && TBPlugin.getUserMedia);
|
||||
navigator.originalGum = (window.TBPlugin && window.TBPlugin.getUserMedia);
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="libs/l10n-gaia-02ca67948fe8.js"></script>
|
||||
@ -139,7 +157,7 @@
|
||||
|
||||
<script>
|
||||
// Wait for all the localization notes to load
|
||||
window.addEventListener('localized', function() {
|
||||
window.addEventListener("localized", function() {
|
||||
loop.webapp.init();
|
||||
}, false);
|
||||
</script>
|
||||
|
@ -36,56 +36,14 @@ var formHistoryStartup = Cc["@mozilla.org/satchel/form-history-startup;1"].
|
||||
getService(Ci.nsIObserver);
|
||||
formHistoryStartup.observe(null, "profile-after-change", null);
|
||||
|
||||
let notificationIndex = 0;
|
||||
|
||||
let notificationsObserver = {
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
print("Received notification: " + aTopic);
|
||||
|
||||
// Note that some of these notifications could arrive multiple times, for
|
||||
// example in case of sync, we allow that.
|
||||
if (EXPECTED_NOTIFICATIONS[notificationIndex] != aTopic)
|
||||
notificationIndex++;
|
||||
do_check_eq(EXPECTED_NOTIFICATIONS[notificationIndex], aTopic);
|
||||
|
||||
if (aTopic != TOPIC_CONNECTION_CLOSED)
|
||||
return;
|
||||
|
||||
getDistinctNotifications().forEach(
|
||||
function (topic) Services.obs.removeObserver(notificationsObserver, topic)
|
||||
);
|
||||
|
||||
print("Looking for uncleared stuff.");
|
||||
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
);
|
||||
|
||||
try {
|
||||
URIS.forEach(function(aUrl) {
|
||||
stmt.params.page_url = aUrl;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.reset();
|
||||
});
|
||||
} finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Check cache.
|
||||
checkCache(FTP_URL);
|
||||
}
|
||||
}
|
||||
|
||||
let timeInMicroseconds = Date.now() * 1000;
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_execute() {
|
||||
do_test_pending();
|
||||
|
||||
print("Initialize browserglue before Places");
|
||||
add_task(function* test_execute() {
|
||||
do_print("Initialize browserglue before Places");
|
||||
|
||||
// Avoid default bookmarks import.
|
||||
let glue = Cc["@mozilla.org/browser/browserglue;1"].
|
||||
@ -105,66 +63,78 @@ add_task(function test_execute() {
|
||||
|
||||
Services.prefs.setBoolPref("privacy.sanitize.sanitizeOnShutdown", true);
|
||||
|
||||
print("Add visits.");
|
||||
do_print("Add visits.");
|
||||
for (let aUrl of URIS) {
|
||||
yield PlacesTestUtils.addVisits({
|
||||
uri: uri(aUrl), visitDate: timeInMicroseconds++,
|
||||
transition: PlacesUtils.history.TRANSITION_TYPED
|
||||
});
|
||||
}
|
||||
print("Add cache.");
|
||||
storeCache(FTP_URL, "testData");
|
||||
do_print("Add cache.");
|
||||
yield storeCache(FTP_URL, "testData");
|
||||
});
|
||||
|
||||
function run_test_continue()
|
||||
{
|
||||
print("Simulate and wait shutdown.");
|
||||
getDistinctNotifications().forEach(
|
||||
function (topic)
|
||||
Services.obs.addObserver(notificationsObserver, topic, false)
|
||||
add_task(function* run_test_continue() {
|
||||
do_print("Simulate and wait shutdown.");
|
||||
yield shutdownPlaces();
|
||||
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
);
|
||||
|
||||
shutdownPlaces();
|
||||
try {
|
||||
URIS.forEach(function(aUrl) {
|
||||
stmt.params.page_url = aUrl;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.reset();
|
||||
});
|
||||
} finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
do_print("Check cache");
|
||||
// Check cache.
|
||||
let promiseCacheChecked = checkCache(FTP_URL);
|
||||
|
||||
do_print("Shutdown the download manager");
|
||||
// Shutdown the download manager.
|
||||
Services.obs.notifyObservers(null, "quit-application", null);
|
||||
}
|
||||
|
||||
function getDistinctNotifications() {
|
||||
let ar = EXPECTED_NOTIFICATIONS.concat(UNEXPECTED_NOTIFICATIONS);
|
||||
return [ar[i] for (i in ar) if (ar.slice(0, i).indexOf(ar[i]) == -1)];
|
||||
}
|
||||
yield promiseCacheChecked;
|
||||
});
|
||||
|
||||
function storeCache(aURL, aContent) {
|
||||
let cache = Services.cache2;
|
||||
let storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
|
||||
var storeCacheListener = {
|
||||
onCacheEntryCheck: function (entry, appcache) {
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
},
|
||||
return new Promise(resolve => {
|
||||
let storeCacheListener = {
|
||||
onCacheEntryCheck: function (entry, appcache) {
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
},
|
||||
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
|
||||
entry.setMetaDataElement("servertype", "0");
|
||||
var os = entry.openOutputStream(0);
|
||||
entry.setMetaDataElement("servertype", "0");
|
||||
var os = entry.openOutputStream(0);
|
||||
|
||||
var written = os.write(aContent, aContent.length);
|
||||
if (written != aContent.length) {
|
||||
do_throw("os.write has not written all data!\n" +
|
||||
" Expected: " + written + "\n" +
|
||||
" Actual: " + aContent.length + "\n");
|
||||
var written = os.write(aContent, aContent.length);
|
||||
if (written != aContent.length) {
|
||||
do_throw("os.write has not written all data!\n" +
|
||||
" Expected: " + written + "\n" +
|
||||
" Actual: " + aContent.length + "\n");
|
||||
}
|
||||
os.close();
|
||||
entry.close();
|
||||
resolve();
|
||||
}
|
||||
os.close();
|
||||
entry.close();
|
||||
do_execute_soon(run_test_continue);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_NORMALLY,
|
||||
storeCacheListener);
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_NORMALLY,
|
||||
storeCacheListener);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -172,14 +142,16 @@ function checkCache(aURL) {
|
||||
let cache = Services.cache2;
|
||||
let storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
|
||||
var checkCacheListener = {
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
return new Promise(resolve => {
|
||||
let checkCacheListener = {
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_READONLY,
|
||||
checkCacheListener);
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_READONLY,
|
||||
checkCacheListener);
|
||||
});
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ var gMainPane = {
|
||||
|
||||
let tmp = {};
|
||||
Components.utils.import("resource://gre/modules/UpdateChannel.jsm", tmp);
|
||||
if (!e10sCheckbox.checked && tmp.UpdateChannel.get() == "nightly") {
|
||||
if (!e10sCheckbox.checked && tmp.UpdateChannel.get() != "default") {
|
||||
Services.prefs.setBoolPref("browser.requestE10sFeedback", true);
|
||||
Services.prompt.alert(window, brandName, "After restart, a tab will open to input.mozilla.org where you can provide us feedback about your e10s experience.");
|
||||
}
|
||||
|
@ -19,4 +19,6 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -11,6 +11,8 @@ ac_add_options --enable-js-diagnostics
|
||||
# by 2 MBs.
|
||||
STRIP_FLAGS="--strip-debug"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
# Use ccache
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
|
@ -19,4 +19,6 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -11,6 +11,8 @@ ac_add_options --enable-js-diagnostics
|
||||
# by 2 MBs.
|
||||
STRIP_FLAGS="--strip-debug"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
# Use ccache
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
|
@ -13,4 +13,6 @@ if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then
|
||||
ac_add_options --with-macbundlename-prefix=Firefox
|
||||
fi
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -18,4 +18,6 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -16,4 +16,6 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -10,6 +10,7 @@ all_platforms = ['win64', 'win32', 'linux32', 'linux64', 'macosx-universal']
|
||||
for platform in all_platforms:
|
||||
whitelist['nightly'][platform] = [
|
||||
'ac_add_options --enable-update-channel=nightly',
|
||||
'ac_add_options --with-branding=browser/branding/nightly',
|
||||
'ac_add_options --enable-profiling',
|
||||
'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --tinderbox-print"'
|
||||
]
|
||||
|
@ -26,6 +26,8 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -7,6 +7,8 @@ ac_add_options --enable-profiling
|
||||
# Nightlies only since this has a cost in performance
|
||||
ac_add_options --enable-js-diagnostics
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -26,6 +26,8 @@ ac_add_options --enable-warnings-as-errors
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. $topsrcdir/build/win64/mozconfig.vs2013
|
||||
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
@ -8,6 +8,8 @@ ac_add_options --enable-profiling
|
||||
# Nightlies only since this has a cost in performance
|
||||
ac_add_options --enable-js-diagnostics
|
||||
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -40,14 +40,12 @@ MOZ_SERVICES_CLOUDSYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
MOZ_EXTENSIONS_DEFAULT=" gio"
|
||||
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
|
||||
# Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results,
|
||||
# because branding dependencies are broken.
|
||||
# MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
|
||||
# specified. It should never point to the "official" branding directory.
|
||||
# For mozilla-beta, mozilla-release, or mozilla-central repositories, use
|
||||
# "nightly" branding (until bug 659568 is fixed).
|
||||
# "unofficial" branding.
|
||||
# For the mozilla-aurora repository, use "aurora".
|
||||
MOZ_BRANDING_DIRECTORY=browser/branding/nightly
|
||||
MOZ_BRANDING_DIRECTORY=browser/branding/unofficial
|
||||
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
|
||||
MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
# This should usually be the same as the value MAR_CHANNEL_ID.
|
||||
|
@ -202,6 +202,8 @@ skip-if = e10s && debug
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_conditional-breakpoints-05.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_console-eval.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-02.js]
|
||||
|
42
browser/devtools/debugger/test/browser_dbg_console-eval.js
Normal file
42
browser/devtools/debugger/test/browser_dbg_console-eval.js
Normal file
@ -0,0 +1,42 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Breaking in the middle of a script evaluated by the console should
|
||||
* work
|
||||
*/
|
||||
|
||||
function test() {
|
||||
Task.spawn(runTests);
|
||||
}
|
||||
|
||||
function* runTests() {
|
||||
let TAB_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
|
||||
let [,, panel] = yield initDebugger(TAB_URL);
|
||||
let dbgWin = panel.panelWin;
|
||||
let sources = dbgWin.DebuggerView.Sources;
|
||||
let frames = dbgWin.DebuggerView.StackFrames;
|
||||
let editor = dbgWin.DebuggerView.editor;
|
||||
let toolbox = gDevTools.getToolbox(panel.target);
|
||||
|
||||
let paused = promise.all([
|
||||
waitForEditorEvents(panel, "cursorActivity"),
|
||||
waitForDebuggerEvents(panel, dbgWin.EVENTS.SOURCE_SHOWN)
|
||||
]);
|
||||
|
||||
toolbox.once("webconsole-ready", () => {
|
||||
ok(toolbox.splitConsole, "Split console is shown.");
|
||||
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
|
||||
jsterm.execute('debugger');
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, dbgWin);
|
||||
|
||||
yield paused;
|
||||
is(sources.selectedItem.attachment.label, 'SCRIPT0',
|
||||
'Anonymous source is selected in sources');
|
||||
dump('text ::' + editor.getText() + '::\n');
|
||||
ok(editor.getText() === 'debugger', 'Editor has correct text');
|
||||
|
||||
yield toolbox.closeSplitConsole();
|
||||
yield resumeDebuggerThenCloseAndFinish(panel);
|
||||
}
|
@ -20,7 +20,6 @@ browser.jar:
|
||||
content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
* content/browser/devtools/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
content/browser/devtools/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/devtools/scratchpad-commands.js (scratchpad/scratchpad-commands.js)
|
||||
content/browser/devtools/splitview.css (shared/splitview.css)
|
||||
content/browser/devtools/theme-switching.js (shared/theme-switching.js)
|
||||
content/browser/devtools/frame-script-utils.js (shared/frame-script-utils.js)
|
||||
@ -114,7 +113,6 @@ browser.jar:
|
||||
content/browser/devtools/performance/views/details-memory-flamegraph.js (performance/views/details-memory-flamegraph.js)
|
||||
content/browser/devtools/performance/views/recordings.js (performance/views/recordings.js)
|
||||
content/browser/devtools/performance/views/jit-optimizations.js (performance/views/jit-optimizations.js)
|
||||
content/browser/devtools/responsivedesign/resize-commands.js (responsivedesign/resize-commands.js)
|
||||
content/browser/devtools/commandline.css (commandline/commandline.css)
|
||||
content/browser/devtools/commandlineoutput.xhtml (commandline/commandlineoutput.xhtml)
|
||||
content/browser/devtools/commandlinetooltip.xhtml (commandline/commandlinetooltip.xhtml)
|
||||
|
@ -175,6 +175,7 @@ ThreadNode.prototype = {
|
||||
let prevCalls = this.calls;
|
||||
let prevFrameKey;
|
||||
let isLeaf = mutableFrameKeyOptions.isLeaf = true;
|
||||
let skipRoot = options.invertTree;
|
||||
|
||||
// Inflate the stack and build the FrameNode call tree directly.
|
||||
//
|
||||
@ -213,6 +214,13 @@ ThreadNode.prototype = {
|
||||
// Fetch the stack prefix (i.e. older frames) index.
|
||||
stackIndex = stackEntry[STACK_PREFIX_SLOT];
|
||||
|
||||
// Do not include the (root) node in this sample, as the costs of each frame
|
||||
// will make it clear to differentiate (root)->B vs (root)->A->B
|
||||
// when a tree is inverted, a revert of bug 1147604
|
||||
if (stackIndex === null && skipRoot) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Inflate the frame.
|
||||
let inflatedFrame = getOrAddInflatedFrame(inflatedFrameCache, frameIndex, frameTable,
|
||||
stringTable, allocationsTable);
|
||||
@ -496,7 +504,7 @@ FrameNode.prototype = {
|
||||
return null;
|
||||
}
|
||||
return new JITOptimizations(this._optimizations, this._stringTable);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
exports.ThreadNode = ThreadNode;
|
||||
|
@ -21,9 +21,14 @@ const CALL_TREE_INDENTATION = 16; // px
|
||||
const DEFAULT_SORTING_PREDICATE = (frameA, frameB) => {
|
||||
let dataA = frameA.getDisplayedData();
|
||||
let dataB = frameB.getDisplayedData();
|
||||
return this.inverted
|
||||
? (dataA.selfPercentage < dataB.selfPercentage ? 1 : -1)
|
||||
: (dataA.samples < dataB.samples ? 1 : -1);
|
||||
if (this.inverted) {
|
||||
// Invert trees, sort by selfPercentage, and then totalPercentage
|
||||
if (dataA.selfPercentage === dataB.selfPercentage) {
|
||||
return dataA.totalPercentage < dataB.totalPercentage ? 1 : -1;
|
||||
}
|
||||
return dataA.selfPercentage < dataB.selfPercentage ? 1 : - 1;
|
||||
}
|
||||
return dataA.samples < dataB.samples ? 1 : -1;
|
||||
};
|
||||
|
||||
const DEFAULT_AUTO_EXPAND_DEPTH = 3; // depth
|
||||
@ -241,7 +246,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
cell.className = "plain call-tree-cell";
|
||||
cell.setAttribute("type", "samples");
|
||||
cell.setAttribute("crop", "end");
|
||||
cell.setAttribute("value", count || "");
|
||||
cell.setAttribute("value", count || 0);
|
||||
return cell;
|
||||
},
|
||||
_createFunctionCell: function(doc, arrowNode, frameName, frameInfo, frameLevel) {
|
||||
@ -335,20 +340,72 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
let data = this._cachedDisplayedData = Object.create(null);
|
||||
let frameInfo = this.frame.getInfo();
|
||||
|
||||
// Self/total duration.
|
||||
if (this.visibleCells.duration) {
|
||||
data.totalDuration = this.frame.duration;
|
||||
}
|
||||
if (this.visibleCells.selfDuration) {
|
||||
data.selfDuration = this.root.frame.selfDuration[this.frame.key];
|
||||
}
|
||||
/**
|
||||
* When inverting call tree, the costs and times are dependent on position
|
||||
* in the tree. We must only count leaf nodes with self cost, and total costs
|
||||
* dependent on how many times the leaf node was found with a full stack path.
|
||||
*
|
||||
* Total | Self | Calls | Function
|
||||
* ============================================================================
|
||||
* 100% | 100% | 100 | ▼ C
|
||||
* 50% | 0% | 50 | ▼ B
|
||||
* 50% | 0% | 50 | ▼ A
|
||||
* 50% | 0% | 50 | ▼ B
|
||||
*
|
||||
* Every instance of a `CallView` represents a row in the call tree. The same
|
||||
* container node is used for all rows.
|
||||
*/
|
||||
|
||||
// Self/total samples percentage.
|
||||
if (this.visibleCells.percentage) {
|
||||
data.totalPercentage = this.frame.samples / this.root.frame.samples * 100;
|
||||
}
|
||||
if (this.visibleCells.selfPercentage) {
|
||||
data.selfPercentage = this.root.frame.selfCount[this.frame.key] / this.root.frame.samples * 100;
|
||||
// Leaf nodes in an inverted tree don't have to do anything special.
|
||||
let isLeaf = this._level === 0;
|
||||
|
||||
if (this.inverted && !isLeaf && this.parent != null) {
|
||||
let calleeData = this.parent.getDisplayedData();
|
||||
// Percentage of time that this frame called the callee
|
||||
// in this branch
|
||||
let callerPercentage = this.frame.samples / calleeData.samples;
|
||||
|
||||
// Self/total duration.
|
||||
if (this.visibleCells.duration) {
|
||||
data.totalDuration = calleeData.totalDuration * callerPercentage;
|
||||
}
|
||||
if (this.visibleCells.selfDuration) {
|
||||
data.selfDuration = 0;
|
||||
}
|
||||
|
||||
// Self/total samples percentage.
|
||||
if (this.visibleCells.percentage) {
|
||||
data.totalPercentage = calleeData.totalPercentage * callerPercentage;
|
||||
}
|
||||
if (this.visibleCells.selfPercentage) {
|
||||
data.selfPercentage = 0;
|
||||
}
|
||||
|
||||
// Raw samples.
|
||||
if (this.visibleCells.samples) {
|
||||
data.samples = this.frame.samples;
|
||||
}
|
||||
} else {
|
||||
// Self/total duration.
|
||||
if (this.visibleCells.duration) {
|
||||
data.totalDuration = this.frame.duration;
|
||||
}
|
||||
if (this.visibleCells.selfDuration) {
|
||||
data.selfDuration = this.root.frame.selfDuration[this.frame.key];
|
||||
}
|
||||
|
||||
// Self/total samples percentage.
|
||||
if (this.visibleCells.percentage) {
|
||||
data.totalPercentage = this.frame.samples / this.root.frame.samples * 100;
|
||||
}
|
||||
if (this.visibleCells.selfPercentage) {
|
||||
data.selfPercentage = this.root.frame.selfCount[this.frame.key] / this.root.frame.samples * 100;
|
||||
}
|
||||
|
||||
// Raw samples.
|
||||
if (this.visibleCells.samples) {
|
||||
data.samples = this.frame.samples;
|
||||
}
|
||||
}
|
||||
|
||||
// Self/total allocations count.
|
||||
@ -360,11 +417,6 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
data.selfAllocations = this.frame.allocations;
|
||||
}
|
||||
|
||||
// Raw samples.
|
||||
if (this.visibleCells.samples) {
|
||||
data.samples = this.frame.samples;
|
||||
}
|
||||
|
||||
// Frame name (function location or some meta information).
|
||||
data.name = frameInfo.isMetaCategory
|
||||
? frameInfo.categoryData.label
|
||||
@ -396,7 +448,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.root.emit("link", this);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
exports.CallView = CallView;
|
||||
|
@ -140,6 +140,7 @@ skip-if = e10s # GC events seem unreliable in multiprocess
|
||||
[browser_profiler_tree-view-07.js]
|
||||
[browser_profiler_tree-view-08.js]
|
||||
[browser_profiler_tree-view-09.js]
|
||||
[browser_profiler_tree-view-10.js]
|
||||
[browser_profiler-frame-utils-01.js]
|
||||
[browser_timeline-blueprint.js]
|
||||
[browser_timeline-filters.js]
|
||||
@ -147,4 +148,5 @@ skip-if = e10s # GC events seem unreliable in multiprocess
|
||||
[browser_timeline-waterfall-generic.js]
|
||||
[browser_timeline-waterfall-rerender.js]
|
||||
[browser_timeline-waterfall-sidebar.js]
|
||||
skip-if = os == 'linux' # Bug 1161817
|
||||
[browser_waterfall-collapse.js]
|
||||
|
@ -6,6 +6,9 @@
|
||||
* and that they're cleared upon rerecording.
|
||||
*/
|
||||
function* spawnTest() {
|
||||
// This test seems to take a long time to cleanup on Ubuntu VMs.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
|
@ -0,0 +1,151 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the profiler's tree view, when inverted, displays the self and
|
||||
* total costs correctly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
let { ThreadNode } = devtools.require("devtools/performance/tree-model");
|
||||
let { CallView } = devtools.require("devtools/performance/tree-view");
|
||||
|
||||
let threadNode = new ThreadNode(gThread, { invertTree: true });
|
||||
let treeRoot = new CallView({ frame: threadNode, inverted: true, hidden: true });
|
||||
|
||||
let container = document.createElement("vbox");
|
||||
treeRoot.attachTo(container);
|
||||
|
||||
// Add 1 to each index to skip the hidden root node
|
||||
let $$fun = i => container.querySelectorAll(".call-tree-cell[type=function]")[i+1];
|
||||
let $$name = i => container.querySelectorAll(".call-tree-cell[type=function] > .call-tree-name")[i+1];
|
||||
let $$percentage = i => container.querySelectorAll(".call-tree-cell[type=percentage]")[i+1];
|
||||
let $$selfpercentage = i => container.querySelectorAll(".call-tree-cell[type='self-percentage']")[i+1];
|
||||
|
||||
/**
|
||||
* Samples
|
||||
*
|
||||
* A->C
|
||||
* A->B
|
||||
* A->B->C x4
|
||||
* A->B->D x4
|
||||
*
|
||||
* Expected Tree
|
||||
* +--total--+--self--+--tree-------------+
|
||||
* | 50% | 50% | C
|
||||
* | 40% | 0 | -> B
|
||||
* | 30% | 0 | -> A
|
||||
* | 10% | 0 | -> A
|
||||
*
|
||||
* | 40% | 40% | D
|
||||
* | 40% | 0 | -> B
|
||||
* | 40% | 0 | -> A
|
||||
*
|
||||
* | 10% | 10% | B
|
||||
* | 10% | 0 | -> A
|
||||
*/
|
||||
|
||||
is(container.childNodes.length, 10,
|
||||
"The container node should have all children available.");
|
||||
|
||||
[ // total, self, indent + name
|
||||
[ 50, 50, "C"],
|
||||
[ 40, 0, " B"],
|
||||
[ 30, 0, " A"],
|
||||
[ 10, 0, " A"],
|
||||
[ 40, 40, "D"],
|
||||
[ 40, 0, " B"],
|
||||
[ 40, 0, " A"],
|
||||
[ 10, 10, "B"],
|
||||
[ 10, 0, " A"],
|
||||
].forEach(function (def, i) {
|
||||
info(`Checking ${i}th tree item`);
|
||||
let [total, self, name] = def;
|
||||
name = name.trim();
|
||||
|
||||
is($$name(i).getAttribute("value"), name, `${name} has correct name.`);
|
||||
is($$percentage(i).getAttribute("value"), `${total}%`, `${name} has correct total percent.`);
|
||||
is($$selfpercentage(i).getAttribute("value"), `${self}%`, `${name} has correct self percent.`);
|
||||
});
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
let gThread = synthesizeProfileForTest([{
|
||||
time: 5,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "C" }
|
||||
]
|
||||
}, {
|
||||
time: 10,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "D" }
|
||||
]
|
||||
}, {
|
||||
time: 15,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "C" },
|
||||
]
|
||||
}, {
|
||||
time: 20,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
]
|
||||
}, {
|
||||
time: 25,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "C" }
|
||||
]
|
||||
}, {
|
||||
time: 30,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "C" }
|
||||
]
|
||||
}, {
|
||||
time: 35,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "D" }
|
||||
]
|
||||
}, {
|
||||
time: 40,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "D" }
|
||||
]
|
||||
}, {
|
||||
time: 45,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "B" },
|
||||
{ location: "C" }
|
||||
]
|
||||
}, {
|
||||
time: 50,
|
||||
frames: [
|
||||
{ location: "(root)" },
|
||||
{ location: "A" },
|
||||
{ location: "B" },
|
||||
{ location: "D" }
|
||||
]
|
||||
}]);
|
@ -49,8 +49,11 @@ function* spawnTest() {
|
||||
is(afterResizeBarsCount, beforeResizeBarsCount,
|
||||
"The same subset of the total markers remained visible.");
|
||||
|
||||
is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
|
||||
"The correct item is still focused in the tree.");
|
||||
// Temporarily disable the following assertion; intermittent failures.
|
||||
// Bug 1169352.
|
||||
|
||||
// is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
|
||||
// "The correct item is still focused in the tree.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
|
@ -33,11 +33,16 @@ ul {
|
||||
max-width: 512px;
|
||||
}
|
||||
|
||||
#errorTitleText {
|
||||
#errorTitle {
|
||||
background: url("aboutNetError_info.svg") left 0 no-repeat;
|
||||
background-size: 1.2em;
|
||||
-moz-margin-start: -2em;
|
||||
-moz-padding-start: 2em;
|
||||
background-size: 3em;
|
||||
-moz-margin-start: -5em;
|
||||
-moz-padding-start: 5em;
|
||||
}
|
||||
|
||||
#errorTitleText {
|
||||
border-bottom: 1px solid #C1C1C1;
|
||||
padding-bottom: 0.4em;
|
||||
}
|
||||
|
||||
#errorTitleText:-moz-dir(rtl) {
|
||||
@ -58,7 +63,7 @@ ul {
|
||||
}
|
||||
|
||||
@media (max-width: 675px) {
|
||||
#errorTitleText {
|
||||
#errorTitle {
|
||||
padding-top: 0;
|
||||
background-image: none;
|
||||
-moz-padding-start: 0;
|
||||
|
@ -264,8 +264,7 @@ public class SUTAgentAndroid extends Activity
|
||||
{
|
||||
if (ba != null)
|
||||
{
|
||||
sUniqueID = ba.getAddress();
|
||||
sUniqueID.toLowerCase();
|
||||
sUniqueID = ba.getAddress().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ packages.txt:testing/mozbase/packages.txt
|
||||
objdir:build
|
||||
gyp.pth:media/webrtc/trunk/tools/gyp/pylib
|
||||
pyasn1.pth:python/pyasn1
|
||||
pyasn1_modules.pth:python/pyasn1-modules
|
||||
bitstring.pth:python/bitstring
|
||||
redo.pth:python/redo
|
||||
requests.pth:python/requests
|
||||
rsa.pth:python/rsa
|
||||
|
@ -3034,6 +3034,7 @@ then
|
||||
esac
|
||||
LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}"
|
||||
AC_SUBST(MOZ_USE_PTHREADS)
|
||||
MOZ_CHECK_HEADERS(pthread.h)
|
||||
fi
|
||||
|
||||
|
||||
@ -3603,7 +3604,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
|
||||
_USE_SYSTEM_NSS=1 )
|
||||
|
||||
if test -n "$_USE_SYSTEM_NSS"; then
|
||||
AM_PATH_NSS(3.19, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
AM_PATH_NSS(3.19.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_NATIVE_NSS"; then
|
||||
|
@ -17,11 +17,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
||||
// designMode document is in a frame inside the window, as this means
|
||||
// the editable region is not in the root docshell (a less complicated case).
|
||||
|
||||
var pageShowChecker = '<scr' + 'ipt>' +
|
||||
'window.addEventListener("pageshow", function(event) {' +
|
||||
'window.opener.postMessage({persisted:event.persisted}, "*");' +
|
||||
'});</scr' + 'ipt>';
|
||||
|
||||
var gTests = [
|
||||
{
|
||||
// <html><body><p>designModeDocument</p></body></html>
|
||||
url: "data:text/html;charset=utf-8,<html><body><p>designModeDocument</p></body></html>",
|
||||
url: "data:text/html;charset=utf-8,<html><head>" + pageShowChecker + "</head><body><p>designModeDocument</p></body></html>",
|
||||
name: 'designModeNavigate',
|
||||
onload(doc) { doc.designMode = "on"; },
|
||||
expectedBodyBeforeEdit: '<p>designModeDocument</p>',
|
||||
@ -30,7 +34,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
||||
},
|
||||
{
|
||||
// <html><body contentEditable="true"><p>contentEditable</p></body></html>
|
||||
url: 'data:text/html;charset=utf-8,<html><body contentEditable="true"><p>contentEditable</p></body></html>',
|
||||
url: "data:text/html;charset=utf-8,<html><head>" + pageShowChecker + "</head><body contentEditable=\"true\"><p>contentEditable</p></body></html>",
|
||||
name: 'contentEditableNavigate',
|
||||
expectedBodyBeforeEdit: '<p>contentEditable</p>',
|
||||
expectedBodyAfterEdit: 'EDITED <br><p>contentEditable</p>',
|
||||
@ -51,12 +55,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
||||
}
|
||||
gTest = gTests[gTestNum];
|
||||
gTest.window = window.open(gTest.url, gTest.name, "width=500,height=500");
|
||||
gTest.window.addEventListener("load", function() {
|
||||
window.onmessage = function(e) {
|
||||
is(e.data.persisted, false, "Initial load cannot be persisted");
|
||||
window.onmessage = null;
|
||||
if ("onload" in gTest) {
|
||||
gTest.onload(gTest.window.document);
|
||||
}
|
||||
SimpleTest.waitForFocus(beginTest, gTest.window);
|
||||
}, false);
|
||||
};
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
@ -73,10 +79,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
window.onmessage = function(e) {
|
||||
window.onmessage = null;
|
||||
// Skip the test if the page is not loaded from the bf-cache when going back.
|
||||
if (e.data.persisted) {
|
||||
checkStillEditable();
|
||||
} else {
|
||||
gTest.window.close();
|
||||
goNext();
|
||||
}
|
||||
};
|
||||
gTest.window.history.back();
|
||||
setTimeout(function() {
|
||||
SimpleTest.waitForFocus(checkStillEditable, gTest.window);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function checkStillEditable() {
|
||||
|
@ -43,6 +43,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=669671
|
||||
* *should* load from the cache.
|
||||
*
|
||||
**/
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function onChildLoad()
|
||||
|
@ -668,7 +668,7 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arguments.AppendElement(value)) {
|
||||
if (!arguments.AppendElement(value, fallible)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -830,7 +830,7 @@ Console::Time(JSContext* aCx, const JS::Handle<JS::Value> aTime)
|
||||
Sequence<JS::Value> data;
|
||||
SequenceRooter<JS::Value> rooter(aCx, &data);
|
||||
|
||||
if (!aTime.isUndefined() && !data.AppendElement(aTime)) {
|
||||
if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -843,7 +843,7 @@ Console::TimeEnd(JSContext* aCx, const JS::Handle<JS::Value> aTime)
|
||||
Sequence<JS::Value> data;
|
||||
SequenceRooter<JS::Value> rooter(aCx, &data);
|
||||
|
||||
if (!aTime.isUndefined() && !data.AppendElement(aTime)) {
|
||||
if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -856,7 +856,7 @@ Console::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
|
||||
Sequence<JS::Value> data;
|
||||
SequenceRooter<JS::Value> rooter(aCx, &data);
|
||||
|
||||
if (aData.isString() && !data.AppendElement(aData)) {
|
||||
if (aData.isString() && !data.AppendElement(aData, fallible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -896,7 +896,7 @@ Console::ProfileMethod(JSContext* aCx, const nsAString& aAction,
|
||||
Sequence<JS::Value>& sequence = event.mArguments.Value();
|
||||
|
||||
for (uint32_t i = 0; i < aData.Length(); ++i) {
|
||||
if (!sequence.AppendElement(aData[i])) {
|
||||
if (!sequence.AppendElement(aData[i], fallible)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1440,7 +1440,7 @@ FlushOutput(JSContext* aCx, Sequence<JS::Value>& aSequence, nsString &aOutput)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aSequence.AppendElement(JS::StringValue(str))) {
|
||||
if (!aSequence.AppendElement(JS::StringValue(str), fallible)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1571,7 +1571,7 @@ Console::ProcessArguments(JSContext* aCx,
|
||||
v = aData[index++];
|
||||
}
|
||||
|
||||
if (!aSequence.AppendElement(v)) {
|
||||
if (!aSequence.AppendElement(v, fallible)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1594,13 +1594,13 @@ Console::ProcessArguments(JSContext* aCx,
|
||||
int32_t diff = aSequence.Length() - aStyles.Length();
|
||||
if (diff > 0) {
|
||||
for (int32_t i = 0; i < diff; i++) {
|
||||
if (!aStyles.AppendElement(JS::NullValue())) {
|
||||
if (!aStyles.AppendElement(JS::NullValue(), fallible)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!aStyles.AppendElement(JS::StringValue(jsString))) {
|
||||
if (!aStyles.AppendElement(JS::StringValue(jsString), fallible)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1672,7 +1672,7 @@ Console::ProcessArguments(JSContext* aCx,
|
||||
|
||||
// The rest of the array, if unused by the format string.
|
||||
for (; index < aData.Length(); ++index) {
|
||||
if (!aSequence.AppendElement(aData[index])) {
|
||||
if (!aSequence.AppendElement(aData[index], fallible)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1808,7 +1808,7 @@ Console::ArgumentsToValueList(const nsTArray<JS::Heap<JS::Value>>& aData,
|
||||
Sequence<JS::Value>& aSequence)
|
||||
{
|
||||
for (uint32_t i = 0; i < aData.Length(); ++i) {
|
||||
if (!aSequence.AppendElement(aData[i])) {
|
||||
if (!aSequence.AppendElement(aData[i], fallible)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -960,7 +960,7 @@ WebSocket::Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Sequence<nsString> protocols;
|
||||
if (!protocols.AppendElement(aProtocol)) {
|
||||
if (!protocols.AppendElement(aProtocol, fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -620,8 +620,13 @@ IsSelectionInsideRuby(nsISelection* aSelection)
|
||||
}
|
||||
|
||||
bool
|
||||
nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell, nsISelection* aSelection)
|
||||
nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell,
|
||||
nsISelection* aSelection, bool* aActionTaken)
|
||||
{
|
||||
if (aActionTaken) {
|
||||
*aActionTaken = false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
|
||||
"Invalid clipboard event type");
|
||||
|
||||
@ -646,14 +651,6 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
// retrieve the event target node from the start of the selection
|
||||
nsresult rv;
|
||||
if (sel) {
|
||||
// Only cut or copy when there is an uncollapsed selection
|
||||
if (aType == NS_CUT || aType == NS_COPY) {
|
||||
bool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
rv = sel->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_SUCCEEDED(rv) && range) {
|
||||
@ -708,6 +705,9 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
clipboardData->SetReadOnly();
|
||||
}
|
||||
|
||||
if (aActionTaken) {
|
||||
*aActionTaken = true;
|
||||
}
|
||||
return doDefault;
|
||||
}
|
||||
|
||||
@ -721,20 +721,43 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
// use the data added to the data transfer and copy that instead.
|
||||
uint32_t count = 0;
|
||||
if (doDefault) {
|
||||
// get the data from the selection if any
|
||||
bool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed) {
|
||||
return false;
|
||||
// find the focused node
|
||||
nsCOMPtr<nsIContent> srcNode = content;
|
||||
if (content->IsInNativeAnonymousSubtree()) {
|
||||
srcNode = content->FindFirstNonChromeOnlyAccessContent();
|
||||
}
|
||||
// XXX Code which decides whether we should copy text with ruby
|
||||
// annotation is currenct depending on whether each range of the
|
||||
// selection is inside a same ruby container. But we really should
|
||||
// expose the full functionality in browser. See bug 1130891.
|
||||
bool withRubyAnnotation = IsSelectionInsideRuby(sel);
|
||||
// call the copy code
|
||||
rv = HTMLCopy(sel, doc, aClipboardType, withRubyAnnotation);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
||||
// check if we are looking at a password input
|
||||
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(srcNode);
|
||||
if (formControl) {
|
||||
if (formControl->GetType() == NS_FORM_INPUT_PASSWORD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// when cutting non-editable content, do nothing
|
||||
// XXX this is probably the wrong editable flag to check
|
||||
if (aType != NS_CUT || content->IsEditable()) {
|
||||
// get the data from the selection if any
|
||||
bool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed) {
|
||||
if (aActionTaken) {
|
||||
*aActionTaken = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// XXX Code which decides whether we should copy text with ruby
|
||||
// annotation is currenct depending on whether each range of the
|
||||
// selection is inside a same ruby container. But we really should
|
||||
// expose the full functionality in browser. See bug 1130891.
|
||||
bool withRubyAnnotation = IsSelectionInsideRuby(sel);
|
||||
// call the copy code
|
||||
rv = HTMLCopy(sel, doc, aClipboardType, withRubyAnnotation);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (clipboardData) {
|
||||
@ -763,5 +786,8 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"), nullptr, 0);
|
||||
}
|
||||
|
||||
if (aActionTaken) {
|
||||
*aActionTaken = true;
|
||||
}
|
||||
return doDefault;
|
||||
}
|
||||
|
@ -83,12 +83,16 @@ class nsCopySupport
|
||||
*
|
||||
* aClipboardType specifies which clipboard to use, from nsIClipboard.
|
||||
*
|
||||
* If aActionTaken is non-NULL, it will be set to true if an action was
|
||||
* taken, whether it be the default action or the default being prevented.
|
||||
*
|
||||
* If the event is cancelled or an error occurs, false will be returned.
|
||||
*/
|
||||
static bool FireClipboardEvent(int32_t aType,
|
||||
int32_t aClipboardType,
|
||||
nsIPresShell* aPresShell,
|
||||
nsISelection* aSelection);
|
||||
nsISelection* aSelection,
|
||||
bool* aActionTaken = nullptr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -714,7 +714,8 @@ nsDOMMutationObserver::GetObservingInfo(
|
||||
mozilla::dom::Sequence<nsString>& filtersAsStrings =
|
||||
info.mAttributeFilter.Value();
|
||||
for (int32_t j = 0; j < filters.Count(); ++j) {
|
||||
if (!filtersAsStrings.AppendElement(nsDependentAtomString(filters[j]))) {
|
||||
if (!filtersAsStrings.AppendElement(nsDependentAtomString(filters[j]),
|
||||
mozilla::fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
@ -773,7 +774,7 @@ nsDOMMutationObserver::HandleMutation()
|
||||
for (uint32_t i = 0; i < mPendingMutationCount; ++i) {
|
||||
nsRefPtr<nsDOMMutationRecord> next;
|
||||
current->mNext.swap(next);
|
||||
*mutations.AppendElement() = current;
|
||||
*mutations.AppendElement(mozilla::fallible) = current;
|
||||
current.swap(next);
|
||||
}
|
||||
}
|
||||
|
@ -2976,19 +2976,10 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
||||
rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (hasReferrerPolicy) {
|
||||
// Referrer policy spec (section 6.1) says that once the referrer policy
|
||||
// is set, any future attempts to change it result in No-Referrer.
|
||||
if (!mReferrerPolicySet) {
|
||||
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
|
||||
mReferrerPolicySet = true;
|
||||
} else if (mReferrerPolicy != referrerPolicy) {
|
||||
mReferrerPolicy = mozilla::net::RP_No_Referrer;
|
||||
{
|
||||
MOZ_LOG(gCspPRLog, PR_LOG_DEBUG, ("%s %s",
|
||||
"CSP wants to set referrer, but nsDocument"
|
||||
"already has it set. No referrers will be sent"));
|
||||
}
|
||||
}
|
||||
// Referrer policy spec (section 6.1) says that we always use the newest
|
||||
// referrer policy we find
|
||||
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
|
||||
mReferrerPolicySet = true;
|
||||
|
||||
// Referrer Policy is set separately for the speculative parser in
|
||||
// nsHTMLDocument::StartDocumentLoad() so there's nothing to do here for
|
||||
@ -3776,14 +3767,10 @@ nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData)
|
||||
if (aHeaderField == nsGkAtoms::referrer && !aData.IsEmpty()) {
|
||||
ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData);
|
||||
|
||||
// Referrer policy spec (section 6.1) says that once the referrer policy
|
||||
// is set, any future attempts to change it result in No-Referrer.
|
||||
if (!mReferrerPolicySet) {
|
||||
mReferrerPolicy = policy;
|
||||
mReferrerPolicySet = true;
|
||||
} else if (mReferrerPolicy != policy) {
|
||||
mReferrerPolicy = mozilla::net::RP_No_Referrer;
|
||||
}
|
||||
// Referrer policy spec (section 6.1) says that we always use the newest
|
||||
// referrer policy we find
|
||||
mReferrerPolicy = policy;
|
||||
mReferrerPolicySet = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,7 +500,8 @@ nsClipboardCommand::IsCommandEnabled(const char* aCommandName, nsISupports *aCon
|
||||
nsresult
|
||||
nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
|
||||
{
|
||||
if (strcmp(aCommandName, "cmd_copy") &&
|
||||
if (strcmp(aCommandName, "cmd_cut") &&
|
||||
strcmp(aCommandName, "cmd_copy") &&
|
||||
strcmp(aCommandName, "cmd_copyAndCollapseToEnd"))
|
||||
return NS_OK;
|
||||
|
||||
@ -513,7 +514,13 @@ nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
|
||||
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCopySupport::FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, presShell, nullptr);
|
||||
int32_t eventType = NS_COPY;
|
||||
if (strcmp(aCommandName, "cmd_cut") == 0) {
|
||||
eventType = NS_CUT;
|
||||
}
|
||||
|
||||
bool actionTaken = false;
|
||||
nsCopySupport::FireClipboardEvent(eventType, nsIClipboard::kGlobalClipboard, presShell, nullptr, &actionTaken);
|
||||
|
||||
if (!strcmp(aCommandName, "cmd_copyAndCollapseToEnd")) {
|
||||
dom::Selection *sel =
|
||||
@ -522,7 +529,10 @@ nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
|
||||
sel->CollapseToEnd();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
if (actionTaken) {
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -368,7 +368,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
for (uint32_t idx = 0; idx < argCount; ++idx) {
|
||||
*args.AppendElement() = argv[idx + 2];
|
||||
*args.AppendElement(fallible) = argv[idx + 2];
|
||||
}
|
||||
args.SwapElements(mArgs);
|
||||
} else {
|
||||
@ -409,7 +409,7 @@ NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, Function& aFunction,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
FallibleTArray<JS::Heap<JS::Value> > args;
|
||||
if (!args.AppendElements(aArguments)) {
|
||||
if (!args.AppendElements(aArguments, fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIDOMHTMLAppletElement.h"
|
||||
#include "nsIExternalProtocolHandler.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsPluginHost.h"
|
||||
@ -2509,6 +2510,13 @@ nsObjectLoadingContent::OpenChannel()
|
||||
scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(httpChan);
|
||||
if (internalChannel) {
|
||||
// Bug 1168676. object/embed tags are not allowed to be intercepted by
|
||||
// ServiceWorkers.
|
||||
internalChannel->ForceNoIntercept();
|
||||
}
|
||||
|
||||
// AsyncOpen can fail if a file does not exist.
|
||||
rv = chan->AsyncOpen(shim, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -228,7 +228,7 @@ nsScreen::MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv)
|
||||
{
|
||||
nsString orientation(aOrientation);
|
||||
Sequence<nsString> orientations;
|
||||
if (!orientations.AppendElement(orientation)) {
|
||||
if (!orientations.AppendElement(orientation, fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return false;
|
||||
}
|
||||
|
@ -44,17 +44,23 @@ function create2ndLevelIframeUrl(schemeFrom, schemeTo, policy, type) {
|
||||
// loaded. The click triggers a redirection to file_bug704320_redirect.html,
|
||||
// which in turn notifies the main window that it's time to check the test
|
||||
// results.
|
||||
function createTest(schemeFrom, schemeTo, policy) {
|
||||
function createTest(schemeFrom, schemeTo, policy, optionalEarlierPolicy) {
|
||||
var _createTestUrl = createTestUrl.bind(
|
||||
null, schemeFrom, schemeTo, policy, 'test');
|
||||
|
||||
var _create2ndLevelIframeUrl = create2ndLevelIframeUrl.bind(
|
||||
null, schemeFrom, schemeTo, policy);
|
||||
|
||||
var metaReferrerPolicyString = '';
|
||||
if (optionalEarlierPolicy && optionalEarlierPolicy != '') {
|
||||
metaReferrerPolicyString += '<meta name="referrer" content="' + optionalEarlierPolicy + '">\n';
|
||||
}
|
||||
metaReferrerPolicyString += '<meta name="referrer" content="' + policy + '">';
|
||||
|
||||
return '<!DOCTYPE HTML>\n\
|
||||
<html>\n\
|
||||
<head>\n\
|
||||
<meta name="referrer" content="' + policy + '">\n\
|
||||
'+metaReferrerPolicyString+'\n\
|
||||
<link rel="stylesheet" type="text/css" href="' + _createTestUrl('stylesheet') + '">\n\
|
||||
<style type="text/css">\n\
|
||||
@import "' + _createTestUrl('import-css') + '";\n\
|
||||
@ -165,11 +171,17 @@ function createIframedWindowLocationTest(schemeFrom, schemeTo, policy) {
|
||||
</html>';
|
||||
}
|
||||
|
||||
function createPolicyTest(refpol) {
|
||||
function createPolicyTest(policy, optionalEarlierPolicy) {
|
||||
var metaReferrerPolicyString = '';
|
||||
if (optionalEarlierPolicy && optionalEarlierPolicy != '') {
|
||||
metaReferrerPolicyString += '<meta name="referrer" content="' + optionalEarlierPolicy + '">\n';
|
||||
}
|
||||
metaReferrerPolicyString += '<meta name="referrer" content="' + policy + '">';
|
||||
|
||||
return '<!DOCTYPE HTML>\n\
|
||||
<html>\n\
|
||||
<head>\n\
|
||||
<meta name="referrer" content="' + refpol + '">\n\
|
||||
'+metaReferrerPolicyString+'\n\
|
||||
<script type="text/javascript" src="/tests/dom/base/test/file_bug704320_preload_common.js"></script>\n\
|
||||
</head>\n\
|
||||
<body>\n\
|
||||
@ -191,10 +203,14 @@ function handleRequest(request, response) {
|
||||
var schemeFrom = params[1].split('=')[1];
|
||||
var schemeTo = params[2].split('=')[1];
|
||||
var policy = params[3].split('=')[1];
|
||||
var optionalEarlierPolicy = '';
|
||||
if (params[4]) {
|
||||
optionalEarlierPolicy = params[4].split('=')[1];
|
||||
}
|
||||
|
||||
response.setHeader('Content-Type', 'text/html; charset=utf-8', false);
|
||||
response.setHeader('Cache-Control', 'no-cache', false);
|
||||
response.write(createTest(schemeFrom, schemeTo, policy));
|
||||
response.write(createTest(schemeFrom, schemeTo, policy, optionalEarlierPolicy));
|
||||
}
|
||||
else if (action === 'create-2nd-level-iframe') {
|
||||
// ?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=origin&type=form"
|
||||
@ -266,7 +282,12 @@ function handleRequest(request, response) {
|
||||
// ?action=generate-policy-test&policy=b64-encoded-string
|
||||
response.setHeader('Cache-Control', 'no-cache', false);
|
||||
response.setHeader('Content-Type', 'text/html', false);
|
||||
var refpol = unescape(params[1].split('=')[1]);
|
||||
response.write(createPolicyTest(refpol));
|
||||
var policy = unescape(params[1].split('=')[1]);
|
||||
var optionalEarlierPolicy = '';
|
||||
if (params[2]) {
|
||||
optionalEarlierPolicy = params[2].split('=')[1];
|
||||
}
|
||||
|
||||
response.write(createPolicyTest(policy, optionalEarlierPolicy));
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
<out><div id="top" xmlns="http://www.w3.org/1999/xhtml"><link href="chrome://global/content/xml/XMLPrettyPrint.css" type="text/css" rel="stylesheet"/><div id="header"><p>
|
||||
<out><div id="top" class="highlight" xmlns="http://www.w3.org/1999/xhtml"><link href="chrome://global/content/xml/XMLPrettyPrint.css" type="text/css" rel="stylesheet"/><div id="header"><p>
|
||||
This XML file does not appear to have any style information associated with it. The document tree is shown below.
|
||||
</p></div><div><<span class="start-tag">out</span>><span class="text">Here be sea hags</span></<span class="end-tag">out</span>></div></div></out>
|
||||
|
@ -678,6 +678,8 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
||||
[test_bug1163743.html]
|
||||
support-files = referrerHelper.js
|
||||
[test_bug1165501.html]
|
||||
support-files = referrerHelper.js
|
||||
[test_caretPositionFromPoint.html]
|
||||
[test_classList.html]
|
||||
# This test fails on the Mac for some reason
|
||||
|
51
dom/base/test/test_bug1165501.html
Normal file
51
dom/base/test/test_bug1165501.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Spot test to see if newer meta-referrer policy is used
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1165501
|
||||
-->
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test policies for Bug 1165501</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="referrerHelper.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var advance = function() { tests.next(); };
|
||||
|
||||
/**
|
||||
* testing if policy is overwritten if there are two meta statements (1165501)
|
||||
* XXX: would be nice to test this with CSP and meta as well
|
||||
*/
|
||||
var tests = (function() {
|
||||
var iframe = document.getElementById("testframe");
|
||||
const sjs = "/tests/dom/base/test/bug704320.sjs?action=generate-policy-test";
|
||||
|
||||
// setting first unsafe-url and then origin - origin shall prevail
|
||||
yield resetCounter();
|
||||
yield iframe.src = sjs + "&policy=" + escape('origin')+ "&wrongPolicy=" + escape('unsafe-url');
|
||||
yield checkIndividualResults("unsafe-url then origin", ["origin"]);
|
||||
|
||||
// setting first no-referrer and then default - default shall prevail
|
||||
yield resetCounter();
|
||||
yield iframe.src = sjs + "&policy=" + escape('default')+ "&wrongPolicy=" + escape('no-referrer');
|
||||
yield checkIndividualResults("no-referrer then default", ["full"]);
|
||||
|
||||
|
||||
// complete. Be sure to yield so we don't call this twice.
|
||||
yield SimpleTest.finish();
|
||||
})();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="tests.next();">
|
||||
<iframe id="testframe"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -25,8 +25,9 @@
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
performance.clearResourceTimings();
|
||||
arr = performance.getEntries();
|
||||
is(arr.length, 0, "clearing performance entries");
|
||||
is(performance.getEntriesByType("resource").length, 0, "clearing performance resource entries");
|
||||
is(performance.getEntriesByType("mark").length, 0, "clearing performance mark entries");
|
||||
is(performance.getEntriesByType("measure").length, 0, "clearing performance measure entries");
|
||||
steps[i]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
|
@ -266,6 +266,14 @@ DOMInterfaces = {
|
||||
'concrete': False
|
||||
},
|
||||
|
||||
'ChromeUtils': {
|
||||
# The codegen is dumb, and doesn't understand that this interface is only a
|
||||
# collection of static methods, so we have this `concrete: False` hack.
|
||||
'concrete': False,
|
||||
'nativeType': 'mozilla::devtools::ChromeUtils',
|
||||
'implicitJSContext': ['readHeapSnapshot', 'saveHeapSnapshot']
|
||||
},
|
||||
|
||||
'ChromeWindow': {
|
||||
'concrete': False,
|
||||
},
|
||||
@ -501,6 +509,10 @@ DOMInterfaces = {
|
||||
'headerFile': 'nsGeolocation.h'
|
||||
},
|
||||
|
||||
'HeapSnapshot': {
|
||||
'nativeType': 'mozilla::devtools::HeapSnapshot'
|
||||
},
|
||||
|
||||
'History': {
|
||||
'headerFile': 'nsHistory.h',
|
||||
'nativeType': 'nsHistory'
|
||||
|
@ -4315,7 +4315,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
if (done${nestingLevel}) {
|
||||
break;
|
||||
}
|
||||
${elementType}* slotPtr${nestingLevel} = arr${nestingLevel}.AppendElement();
|
||||
${elementType}* slotPtr${nestingLevel} = arr${nestingLevel}.AppendElement(mozilla::fallible);
|
||||
if (!slotPtr${nestingLevel}) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
$*{exceptionCode}
|
||||
@ -5610,7 +5610,7 @@ class CGArgumentConverter(CGThing):
|
||||
return false;
|
||||
}
|
||||
for (uint32_t variadicArg = ${index}; variadicArg < ${argc}; ++variadicArg) {
|
||||
${elemType}& slot = *${declName}.AppendElement();
|
||||
${elemType}& slot = *${declName}.AppendElement(mozilla::fallible);
|
||||
""")
|
||||
).substitute(replacer)
|
||||
|
||||
|
277
dom/cache/Connection.cpp
vendored
Normal file
277
dom/cache/Connection.cpp
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/cache/Connection.h"
|
||||
|
||||
#include "mozilla/dom/cache/DBSchema.h"
|
||||
#include "mozStorageHelper.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
NS_IMPL_ISUPPORTS(cache::Connection, mozIStorageAsyncConnection,
|
||||
mozIStorageConnection);
|
||||
|
||||
Connection::Connection(mozIStorageConnection* aBase)
|
||||
: mBase(aBase)
|
||||
, mClosed(false)
|
||||
{
|
||||
MOZ_ASSERT(mBase);
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Connection);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(Close()));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::Close()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Connection);
|
||||
|
||||
if (mClosed) {
|
||||
return NS_OK;
|
||||
}
|
||||
mClosed = true;
|
||||
|
||||
// If we are closing here, then Cache must not have a transaction
|
||||
// open anywhere else. This should be guaranteed to succeed.
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(db::IncrementalVacuum(this)));
|
||||
|
||||
return mBase->Close();
|
||||
}
|
||||
|
||||
// The following methods are all boilerplate that either forward to the
|
||||
// base connection or block the method. All the async execution methods
|
||||
// are blocked because Cache does not use them and they would require more
|
||||
// work to wrap properly.
|
||||
|
||||
// mozIStorageAsyncConnection methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::AsyncClose(mozIStorageCompletionCallback*)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::AsyncClone(bool, mozIStorageCompletionCallback*)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetDatabaseFile(nsIFile** aFileOut)
|
||||
{
|
||||
return mBase->GetDatabaseFile(aFileOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CreateAsyncStatement(const nsACString&, mozIStorageAsyncStatement**)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::ExecuteAsync(mozIStorageBaseStatement**, uint32_t,
|
||||
mozIStorageStatementCallback*,
|
||||
mozIStoragePendingStatement**)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::ExecuteSimpleSQLAsync(const nsACString&,
|
||||
mozIStorageStatementCallback*,
|
||||
mozIStoragePendingStatement**)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CreateFunction(const nsACString& aFunctionName,
|
||||
int32_t aNumArguments,
|
||||
mozIStorageFunction* aFunction)
|
||||
{
|
||||
// async methods are not supported
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CreateAggregateFunction(const nsACString& aFunctionName,
|
||||
int32_t aNumArguments,
|
||||
mozIStorageAggregateFunction* aFunction)
|
||||
{
|
||||
return mBase->CreateAggregateFunction(aFunctionName, aNumArguments,
|
||||
aFunction);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::RemoveFunction(const nsACString& aFunctionName)
|
||||
{
|
||||
return mBase->RemoveFunction(aFunctionName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::SetProgressHandler(int32_t aGranularity,
|
||||
mozIStorageProgressHandler* aHandler,
|
||||
mozIStorageProgressHandler** aHandlerOut)
|
||||
{
|
||||
return mBase->SetProgressHandler(aGranularity, aHandler, aHandlerOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::RemoveProgressHandler(mozIStorageProgressHandler** aHandlerOut)
|
||||
{
|
||||
return mBase->RemoveProgressHandler(aHandlerOut);
|
||||
}
|
||||
|
||||
// mozIStorageConnection methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::Clone(bool aReadOnly, mozIStorageConnection** aConnectionOut)
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> conn;
|
||||
nsresult rv = mBase->Clone(aReadOnly, getter_AddRefs(conn));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> wrapped = new Connection(conn);
|
||||
wrapped.forget(aConnectionOut);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetDefaultPageSize(int32_t* aSizeOut)
|
||||
{
|
||||
return mBase->GetDefaultPageSize(aSizeOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetConnectionReady(bool* aReadyOut)
|
||||
{
|
||||
return mBase->GetConnectionReady(aReadyOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetLastInsertRowID(int64_t* aRowIdOut)
|
||||
{
|
||||
return mBase->GetLastInsertRowID(aRowIdOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetAffectedRows(int32_t* aCountOut)
|
||||
{
|
||||
return mBase->GetAffectedRows(aCountOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetLastError(int32_t* aErrorOut)
|
||||
{
|
||||
return mBase->GetLastError(aErrorOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetLastErrorString(nsACString& aErrorOut)
|
||||
{
|
||||
return mBase->GetLastErrorString(aErrorOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetSchemaVersion(int32_t* aVersionOut)
|
||||
{
|
||||
return mBase->GetSchemaVersion(aVersionOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::SetSchemaVersion(int32_t aVersion)
|
||||
{
|
||||
return mBase->SetSchemaVersion(aVersion);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CreateStatement(const nsACString& aQuery,
|
||||
mozIStorageStatement** aStatementOut)
|
||||
{
|
||||
return mBase->CreateStatement(aQuery, aStatementOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::ExecuteSimpleSQL(const nsACString& aQuery)
|
||||
{
|
||||
return mBase->ExecuteSimpleSQL(aQuery);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::TableExists(const nsACString& aTableName, bool* aExistsOut)
|
||||
{
|
||||
return mBase->TableExists(aTableName, aExistsOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::IndexExists(const nsACString& aIndexName, bool* aExistsOut)
|
||||
{
|
||||
return mBase->IndexExists(aIndexName, aExistsOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetTransactionInProgress(bool* aResultOut)
|
||||
{
|
||||
return mBase->GetTransactionInProgress(aResultOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::BeginTransaction()
|
||||
{
|
||||
return mBase->BeginTransaction();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::BeginTransactionAs(int32_t aType)
|
||||
{
|
||||
return mBase->BeginTransactionAs(aType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CommitTransaction()
|
||||
{
|
||||
return mBase->CommitTransaction();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::RollbackTransaction()
|
||||
{
|
||||
return mBase->RollbackTransaction();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::CreateTable(const char* aTable, const char* aSchema)
|
||||
{
|
||||
return mBase->CreateTable(aTable, aSchema);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::SetGrowthIncrement(int32_t aIncrement, const nsACString& aDatabase)
|
||||
{
|
||||
return mBase->SetGrowthIncrement(aIncrement, aDatabase);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::EnableModule(const nsACString& aModule)
|
||||
{
|
||||
return mBase->EnableModule(aModule);
|
||||
}
|
||||
|
||||
} // namespace cache
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
36
dom/cache/Connection.h
vendored
Normal file
36
dom/cache/Connection.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_cache_Connection_h
|
||||
#define mozilla_dom_cache_Connection_h
|
||||
|
||||
#include "mozIStorageConnection.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
class Connection final : public mozIStorageConnection
|
||||
{
|
||||
public:
|
||||
explicit Connection(mozIStorageConnection* aBase);
|
||||
|
||||
private:
|
||||
~Connection();
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> mBase;
|
||||
bool mClosed;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGEASYNCCONNECTION
|
||||
NS_DECL_MOZISTORAGECONNECTION
|
||||
};
|
||||
|
||||
} // namespace cache
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_cache_Connection_h
|
84
dom/cache/Context.cpp
vendored
84
dom/cache/Context.cpp
vendored
@ -131,11 +131,15 @@ class Context::QuotaInitRunnable final : public nsIRunnable
|
||||
public:
|
||||
QuotaInitRunnable(Context* aContext,
|
||||
Manager* aManager,
|
||||
Action* aQuotaIOThreadAction)
|
||||
Data* aData,
|
||||
nsIThread* aTarget,
|
||||
Action* aInitAction)
|
||||
: mContext(aContext)
|
||||
, mThreadsafeHandle(aContext->CreateThreadsafeHandle())
|
||||
, mManager(aManager)
|
||||
, mQuotaIOThreadAction(aQuotaIOThreadAction)
|
||||
, mData(aData)
|
||||
, mTarget(aTarget)
|
||||
, mInitAction(aInitAction)
|
||||
, mInitiatingThread(NS_GetCurrentThread())
|
||||
, mResult(NS_OK)
|
||||
, mState(STATE_INIT)
|
||||
@ -144,6 +148,8 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
MOZ_ASSERT(mManager);
|
||||
MOZ_ASSERT(mData);
|
||||
MOZ_ASSERT(mTarget);
|
||||
MOZ_ASSERT(mInitiatingThread);
|
||||
}
|
||||
|
||||
@ -166,7 +172,7 @@ public:
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_ASSERT(!mCanceled);
|
||||
mCanceled = true;
|
||||
mQuotaIOThreadAction->CancelOnInitiatingThread();
|
||||
mInitAction->CancelOnInitiatingThread();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -202,7 +208,7 @@ private:
|
||||
{
|
||||
MOZ_ASSERT(mState == STATE_COMPLETE);
|
||||
MOZ_ASSERT(!mContext);
|
||||
MOZ_ASSERT(!mQuotaIOThreadAction);
|
||||
MOZ_ASSERT(!mInitAction);
|
||||
}
|
||||
|
||||
enum State
|
||||
@ -211,6 +217,7 @@ private:
|
||||
STATE_CALL_WAIT_FOR_OPEN_ALLOWED,
|
||||
STATE_WAIT_FOR_OPEN_ALLOWED,
|
||||
STATE_ENSURE_ORIGIN_INITIALIZED,
|
||||
STATE_RUN_ON_TARGET,
|
||||
STATE_RUNNING,
|
||||
STATE_COMPLETING,
|
||||
STATE_COMPLETE
|
||||
@ -222,13 +229,15 @@ private:
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext = nullptr;
|
||||
mManager = nullptr;
|
||||
mQuotaIOThreadAction = nullptr;
|
||||
mInitAction = nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Context> mContext;
|
||||
nsRefPtr<ThreadsafeHandle> mThreadsafeHandle;
|
||||
nsRefPtr<Manager> mManager;
|
||||
nsRefPtr<Action> mQuotaIOThreadAction;
|
||||
nsRefPtr<Data> mData;
|
||||
nsCOMPtr<nsIThread> mTarget;
|
||||
nsRefPtr<Action> mInitAction;
|
||||
nsCOMPtr<nsIThread> mInitiatingThread;
|
||||
nsresult mResult;
|
||||
QuotaInfo mQuotaInfo;
|
||||
@ -266,9 +275,14 @@ NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
|
||||
// | (Quota IO Thread) +----------------+
|
||||
// +----------+------------+ |
|
||||
// | |
|
||||
// +----------v------------+ |
|
||||
// | RunOnTarget | Resolve(error) |
|
||||
// | (Target Thread) +----------------+
|
||||
// +----------+------------+ |
|
||||
// | |
|
||||
// +---------v---------+ +------v------+
|
||||
// | Running | | Completing |
|
||||
// | (Quota IO Thread) +------------>(Orig Thread)|
|
||||
// | (Target Thread) +------------>(Orig Thread)|
|
||||
// +-------------------+ +------+------+
|
||||
// |
|
||||
// +-----v----+
|
||||
@ -384,16 +398,27 @@ Context::QuotaInitRunnable::Run()
|
||||
break;
|
||||
}
|
||||
|
||||
mState = STATE_RUNNING;
|
||||
|
||||
if (!mQuotaIOThreadAction) {
|
||||
if (!mInitAction) {
|
||||
resolver->Resolve(NS_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
mState = STATE_RUN_ON_TARGET;
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
mTarget->Dispatch(this, nsIThread::DISPATCH_NORMAL)));
|
||||
break;
|
||||
}
|
||||
// -------------------
|
||||
case STATE_RUN_ON_TARGET:
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mTarget);
|
||||
|
||||
mState = STATE_RUNNING;
|
||||
|
||||
// Execute the provided initialization Action. The Action must Resolve()
|
||||
// before returning.
|
||||
mQuotaIOThreadAction->RunOnTarget(resolver, mQuotaInfo, nullptr);
|
||||
mInitAction->RunOnTarget(resolver, mQuotaInfo, mData);
|
||||
MOZ_ASSERT(resolver->Resolved());
|
||||
|
||||
break;
|
||||
@ -402,8 +427,8 @@ Context::QuotaInitRunnable::Run()
|
||||
case STATE_COMPLETING:
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
if (mQuotaIOThreadAction) {
|
||||
mQuotaIOThreadAction->CompleteOnInitiatingThread(mResult);
|
||||
if (mInitAction) {
|
||||
mInitAction->CompleteOnInitiatingThread(mResult);
|
||||
}
|
||||
mContext->OnQuotaInit(mResult, mQuotaInfo, mOfflineStorage);
|
||||
mState = STATE_COMPLETE;
|
||||
@ -776,21 +801,10 @@ Context::ThreadsafeHandle::ContextDestroyed(Context* aContext)
|
||||
// static
|
||||
already_AddRefed<Context>
|
||||
Context::Create(Manager* aManager, nsIThread* aTarget,
|
||||
Action* aQuotaIOThreadAction, Context* aOldContext)
|
||||
Action* aInitAction, Context* aOldContext)
|
||||
{
|
||||
nsRefPtr<Context> context = new Context(aManager, aTarget);
|
||||
|
||||
// Do this here to avoid doing an AddRef() in the constructor
|
||||
// TODO: pass context->mData to allow connetion sharing with init
|
||||
context->mInitRunnable = new QuotaInitRunnable(context, aManager,
|
||||
aQuotaIOThreadAction);
|
||||
|
||||
if (aOldContext) {
|
||||
aOldContext->SetNextContext(context);
|
||||
} else {
|
||||
context->Start();
|
||||
}
|
||||
|
||||
context->Init(aInitAction, aOldContext);
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
@ -913,6 +927,24 @@ Context::~Context()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Context::Init(Action* aInitAction, Context* aOldContext)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Context);
|
||||
MOZ_ASSERT(!mInitRunnable);
|
||||
|
||||
// Do this here to avoid doing an AddRef() in the constructor
|
||||
mInitRunnable = new QuotaInitRunnable(this, mManager, mData, mTarget,
|
||||
aInitAction);
|
||||
|
||||
if (aOldContext) {
|
||||
aOldContext->SetNextContext(this);
|
||||
return;
|
||||
}
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
void
|
||||
Context::Start()
|
||||
{
|
||||
|
3
dom/cache/Context.h
vendored
3
dom/cache/Context.h
vendored
@ -112,7 +112,7 @@ public:
|
||||
// be execute synchronously.
|
||||
static already_AddRefed<Context>
|
||||
Create(Manager* aManager, nsIThread* aTarget,
|
||||
Action* aQuotaIOThreadAction, Context* aOldContext);
|
||||
Action* aInitAction, Context* aOldContext);
|
||||
|
||||
// Execute given action on the target once the quota manager has been
|
||||
// initialized.
|
||||
@ -173,6 +173,7 @@ private:
|
||||
|
||||
Context(Manager* aManager, nsIThread* aTarget);
|
||||
~Context();
|
||||
void Init(Action* aInitAction, Context* aOldContext);
|
||||
void Start();
|
||||
void DispatchAction(Action* aAction, bool aDoomData = false);
|
||||
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
|
||||
|
12
dom/cache/DBAction.cpp
vendored
12
dom/cache/DBAction.cpp
vendored
@ -6,6 +6,9 @@
|
||||
|
||||
#include "mozilla/dom/cache/DBAction.h"
|
||||
|
||||
#include "mozilla/dom/cache/Connection.h"
|
||||
#include "mozilla/dom/cache/DBSchema.h"
|
||||
#include "mozilla/dom/cache/FileUtils.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "mozilla/net/nsFileProtocolHandler.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
@ -15,8 +18,6 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "DBSchema.h"
|
||||
#include "FileUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -79,7 +80,12 @@ DBAction::RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||
// Save this connection in the shared Data object so later Actions can
|
||||
// use it. This avoids opening a new connection for every Action.
|
||||
if (aOptionalData) {
|
||||
aOptionalData->SetConnection(conn);
|
||||
// Since we know this connection will be around for as long as the
|
||||
// Cache is open, use our special wrapped connection class. This
|
||||
// will let us perform certain operations once the Cache origin
|
||||
// is closed.
|
||||
nsCOMPtr<mozIStorageConnection> wrapped = new Connection(conn);
|
||||
aOptionalData->SetConnection(wrapped);
|
||||
}
|
||||
}
|
||||
|
||||
|
176
dom/cache/DBSchema.cpp
vendored
176
dom/cache/DBSchema.cpp
vendored
@ -29,13 +29,30 @@ namespace dom {
|
||||
namespace cache {
|
||||
namespace db {
|
||||
|
||||
const int32_t kMaxWipeSchemaVersion = 9;
|
||||
const int32_t kMaxWipeSchemaVersion = 10;
|
||||
|
||||
namespace {
|
||||
|
||||
const int32_t kLatestSchemaVersion = 9;
|
||||
const int32_t kLatestSchemaVersion = 10;
|
||||
const int32_t kMaxEntriesPerStatement = 255;
|
||||
|
||||
const uint32_t kPageSize = 4 * 1024;
|
||||
|
||||
// Grow the database in chunks to reduce fragmentation
|
||||
const uint32_t kGrowthSize = 32 * 1024;
|
||||
const uint32_t kGrowthPages = kGrowthSize / kPageSize;
|
||||
static_assert(kGrowthSize % kPageSize == 0,
|
||||
"Growth size must be multiple of page size");
|
||||
|
||||
// Only release free pages when we have more than this limit
|
||||
const int32_t kMaxFreePages = kGrowthPages;
|
||||
|
||||
// Limit WAL journal to a reasonable size
|
||||
const uint32_t kWalAutoCheckpointSize = 512 * 1024;
|
||||
const uint32_t kWalAutoCheckpointPages = kWalAutoCheckpointSize / kPageSize;
|
||||
static_assert(kWalAutoCheckpointSize % kPageSize == 0,
|
||||
"WAL checkpoint size must be multiple of page size");
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// If any of the static_asserts below fail, it means that you have changed
|
||||
@ -213,28 +230,12 @@ CreateSchema(mozIStorageConnection* aConn)
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(aConn);
|
||||
|
||||
nsAutoCString pragmas(
|
||||
// Enable auto-vaccum but in incremental mode in order to avoid doing a lot
|
||||
// of work at the end of each transaction.
|
||||
// NOTE: This must be done here instead of InitializeConnection() because it
|
||||
// only works when the database is empty.
|
||||
"PRAGMA auto_vacuum = INCREMENTAL; "
|
||||
);
|
||||
|
||||
nsresult rv = aConn->ExecuteSimpleSQL(pragmas);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
int32_t schemaVersion;
|
||||
rv = aConn->GetSchemaVersion(&schemaVersion);
|
||||
nsresult rv = aConn->GetSchemaVersion(&schemaVersion);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
if (schemaVersion == kLatestSchemaVersion) {
|
||||
// We already have the correct schema, so just do an incremental vaccum and
|
||||
// get started.
|
||||
rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"PRAGMA incremental_vacuum;"));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// We already have the correct schema, so just get started.
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -380,24 +381,69 @@ InitializeConnection(mozIStorageConnection* aConn)
|
||||
// This function needs to perform per-connection initialization tasks that
|
||||
// need to happen regardless of the schema.
|
||||
|
||||
nsAutoCString pragmas(
|
||||
"PRAGMA journal_mode = WAL; "
|
||||
// Use default mozStorage 32kb page size for now
|
||||
// WAL journal can grow to 512kb before being flushed to disk
|
||||
"PRAGMA wal_autocheckpoint = 16; "
|
||||
// Always truncate the journal back to 512kb after large transactions
|
||||
"PRAGMA journal_size_limit = 524288; "
|
||||
"PRAGMA foreign_keys = ON; "
|
||||
|
||||
// Note, the default encoding of UTF-8 is preferred. mozStorage does all
|
||||
// the work necessary to convert UTF-16 nsString values for us. We don't
|
||||
// need ordering and the binary equality operations are correct. So, do
|
||||
// NOT set PRAGMA encoding to UTF-16.
|
||||
nsPrintfCString pragmas(
|
||||
// Use a smaller page size to improve perf/footprint; default is too large
|
||||
"PRAGMA page_size = %u; "
|
||||
// Enable auto_vacuum; this must happen after page_size and before WAL
|
||||
"PRAGMA auto_vacuum = INCREMENTAL; "
|
||||
"PRAGMA foreign_keys = ON; ",
|
||||
kPageSize
|
||||
);
|
||||
|
||||
// Note, the default encoding of UTF-8 is preferred. mozStorage does all
|
||||
// the work necessary to convert UTF-16 nsString values for us. We don't
|
||||
// need ordering and the binary equality operations are correct. So, do
|
||||
// NOT set PRAGMA encoding to UTF-16.
|
||||
|
||||
nsresult rv = aConn->ExecuteSimpleSQL(pragmas);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// Limit fragmentation by growing the database by many pages at once.
|
||||
rv = aConn->SetGrowthIncrement(kGrowthSize, EmptyCString());
|
||||
if (rv == NS_ERROR_FILE_TOO_BIG) {
|
||||
NS_WARNING("Not enough disk space to set sqlite growth increment.");
|
||||
rv = NS_OK;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// Enable WAL journaling. This must be performed in a separate transaction
|
||||
// after changing the page_size and enabling auto_vacuum.
|
||||
nsPrintfCString wal(
|
||||
// WAL journal can grow to given number of *pages*
|
||||
"PRAGMA wal_autocheckpoint = %u; "
|
||||
// Always truncate the journal back to given number of *bytes*
|
||||
"PRAGMA journal_size_limit = %u; "
|
||||
// WAL must be enabled at the end to allow page size to be changed, etc.
|
||||
"PRAGMA journal_mode = WAL; ",
|
||||
kWalAutoCheckpointPages,
|
||||
kWalAutoCheckpointSize
|
||||
);
|
||||
|
||||
rv = aConn->ExecuteSimpleSQL(wal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// Verify that we successfully set the vacuum mode to incremental. It
|
||||
// is very easy to put the database in a state where the auto_vacuum
|
||||
// pragma above fails silently.
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<mozIStorageStatement> state;
|
||||
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA auto_vacuum;"
|
||||
), getter_AddRefs(state));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
bool hasMoreData = false;
|
||||
rv = state->ExecuteStep(&hasMoreData);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
int32_t mode;
|
||||
rv = state->GetInt32(0, &mode);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// integer value 2 is incremental mode
|
||||
if (NS_WARN_IF(mode != 2)) { return NS_ERROR_UNEXPECTED; }
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1916,6 +1962,70 @@ CreateAndBindKeyStatement(mozIStorageConnection* aConn,
|
||||
|
||||
} // anonymouns namespace
|
||||
|
||||
nsresult
|
||||
IncrementalVacuum(mozIStorageConnection* aConn)
|
||||
{
|
||||
// Determine how much free space is in the database.
|
||||
nsCOMPtr<mozIStorageStatement> state;
|
||||
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA freelist_count;"
|
||||
), getter_AddRefs(state));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
bool hasMoreData = false;
|
||||
rv = state->ExecuteStep(&hasMoreData);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
int32_t freePages = 0;
|
||||
rv = state->GetInt32(0, &freePages);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// We have a relatively small page size, so we want to be careful to avoid
|
||||
// fragmentation. We already use a growth incremental which will cause
|
||||
// sqlite to allocate and release multiple pages at the same time. We can
|
||||
// further reduce fragmentation by making our allocated chunks a bit
|
||||
// "sticky". This is done by creating some hysteresis where we allocate
|
||||
// pages/chunks as soon as we need them, but we only release pages/chunks
|
||||
// when we have a large amount of free space. This helps with the case
|
||||
// where a page is adding and remove resources causing it to dip back and
|
||||
// forth across a chunk boundary.
|
||||
//
|
||||
// So only proceed with releasing pages if we have more than our constant
|
||||
// threshold.
|
||||
if (freePages <= kMaxFreePages) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Release the excess pages back to the sqlite VFS. This may also release
|
||||
// chunks of multiple pages back to the OS.
|
||||
int32_t pagesToRelease = freePages - kMaxFreePages;
|
||||
|
||||
rv = aConn->ExecuteSimpleSQL(nsPrintfCString(
|
||||
"PRAGMA incremental_vacuum(%d);", pagesToRelease
|
||||
));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// Verify that our incremental vacuum actually did something
|
||||
#ifdef DEBUG
|
||||
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA freelist_count;"
|
||||
), getter_AddRefs(state));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
hasMoreData = false;
|
||||
rv = state->ExecuteStep(&hasMoreData);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
freePages = 0;
|
||||
rv = state->GetInt32(0, &freePages);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
MOZ_ASSERT(freePages <= kMaxFreePages);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace db
|
||||
} // namespace cache
|
||||
} // namespace dom
|
||||
|
5
dom/cache/DBSchema.h
vendored
5
dom/cache/DBSchema.h
vendored
@ -32,6 +32,7 @@ namespace db {
|
||||
nsresult
|
||||
CreateSchema(mozIStorageConnection* aConn);
|
||||
|
||||
// Note, this cannot be executed within a transaction.
|
||||
nsresult
|
||||
InitializeConnection(mozIStorageConnection* aConn);
|
||||
|
||||
@ -104,6 +105,10 @@ nsresult
|
||||
StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
|
||||
nsTArray<nsString>& aKeysOut);
|
||||
|
||||
// Note, this works best when its NOT executed within a transaction.
|
||||
nsresult
|
||||
IncrementalVacuum(mozIStorageConnection* aConn);
|
||||
|
||||
// We will wipe out databases with a schema versions less than this.
|
||||
extern const int32_t kMaxWipeSchemaVersion;
|
||||
|
||||
|
2
dom/cache/moz.build
vendored
2
dom/cache/moz.build
vendored
@ -21,6 +21,7 @@ EXPORTS.mozilla.dom.cache += [
|
||||
'CacheStorageParent.h',
|
||||
'CacheStreamControlChild.h',
|
||||
'CacheStreamControlParent.h',
|
||||
'Connection.h',
|
||||
'Context.h',
|
||||
'DBAction.h',
|
||||
'DBSchema.h',
|
||||
@ -56,6 +57,7 @@ UNIFIED_SOURCES += [
|
||||
'CacheStorageParent.cpp',
|
||||
'CacheStreamControlChild.cpp',
|
||||
'CacheStreamControlParent.cpp',
|
||||
'Connection.cpp',
|
||||
'Context.cpp',
|
||||
'DBAction.cpp',
|
||||
'DBSchema.cpp',
|
||||
|
1002
dom/cache/test/mochitest/large_url_list.js
vendored
Normal file
1002
dom/cache/test/mochitest/large_url_list.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
dom/cache/test/mochitest/mochitest.ini
vendored
2
dom/cache/test/mochitest/mochitest.ini
vendored
@ -21,6 +21,7 @@ support-files =
|
||||
test_cache_delete.js
|
||||
test_cache_put_reorder.js
|
||||
test_cache_https.js
|
||||
large_url_list.js
|
||||
|
||||
[test_cache.html]
|
||||
[test_cache_add.html]
|
||||
@ -37,3 +38,4 @@ support-files =
|
||||
[test_cache_https.html]
|
||||
skip-if = buildapp == 'b2g' # bug 1162353
|
||||
[test_cache_restart.html]
|
||||
[test_cache_shrink.html]
|
||||
|
131
dom/cache/test/mochitest/test_cache_shrink.html
vendored
Normal file
131
dom/cache/test/mochitest/test_cache_shrink.html
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Cache with QuotaManager Restart</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="large_url_list.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var appId, inBrowser;
|
||||
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
|
||||
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
|
||||
principal.appId != nsIPrincipal.NO_APP_ID) {
|
||||
appId = principal.appId;
|
||||
inBrowser = principal.isInBrowserElement;
|
||||
}
|
||||
SpecialPowers.clearStorageForURI(document.documentURI, resolve, appId,
|
||||
inBrowser);
|
||||
});
|
||||
}
|
||||
|
||||
function storageUsage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var appId, inBrowser;
|
||||
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
|
||||
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
|
||||
principal.appId != nsIPrincipal.NO_APP_ID) {
|
||||
appId = principal.appId;
|
||||
inBrowser = principal.isInBrowserElement;
|
||||
}
|
||||
SpecialPowers.getStorageUsageForURI(document.documentURI, resolve, appId,
|
||||
inBrowser);
|
||||
});
|
||||
}
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var appId, inBrowser;
|
||||
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
|
||||
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
|
||||
principal.appId != nsIPrincipal.NO_APP_ID) {
|
||||
appId = principal.appId;
|
||||
inBrowser = principal.isInBrowserElement;
|
||||
}
|
||||
SpecialPowers.resetStorageForURI(document.documentURI, resolve, appId,
|
||||
inBrowser);
|
||||
});
|
||||
}
|
||||
|
||||
function gc() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.exactGC(window, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["dom.caches.enabled", true],
|
||||
["dom.quotaManager.testing", true]],
|
||||
}, function() {
|
||||
var name = 'foo';
|
||||
var cache = null;
|
||||
var initialUsage = 0;
|
||||
var fullUsage = 0;
|
||||
var endUsage = 0;
|
||||
// start from a fresh origin directory so other tests do not influence our
|
||||
// results
|
||||
clearStorage().then(function() {
|
||||
return storageUsage();
|
||||
}).then(function(usage) {
|
||||
is(0, usage, 'disk usage should be zero to start');
|
||||
return caches.open(name);
|
||||
}).then(function(c) {
|
||||
cache = c;
|
||||
return storageUsage();
|
||||
}).then(function(usage) {
|
||||
initialUsage = usage;
|
||||
return Promise.all(largeUrlList.map(function(url) {
|
||||
return cache.put(new Request(url), new Response());
|
||||
}));
|
||||
}).then(function() {
|
||||
return cache.keys();
|
||||
}).then(function(keyList) {
|
||||
is(keyList.length, largeUrlList.length, 'Large URL list is stored in cache');
|
||||
cache = null;
|
||||
// Ensure the Cache DOM object is gone before proceeding. If its alive
|
||||
// it will keep the related entries on-disk as well.
|
||||
return gc();
|
||||
}).then(function() {
|
||||
// reset the quota manager storage to ensure the DB connection is flushed
|
||||
return resetStorage();
|
||||
}).then(function() {
|
||||
return storageUsage();
|
||||
}).then(function(usage) {
|
||||
fullUsage = usage;
|
||||
ok(fullUsage > initialUsage, 'disk usage should have grown');
|
||||
return caches.delete(name);
|
||||
}).then(function(result) {
|
||||
ok(result, 'cache should be deleted');
|
||||
// This is a bit superfluous, but its necessary to make sure the Cache is
|
||||
// fully deleted before we proceed. The deletion actually takes place in
|
||||
// two async steps. We don't want to resetStorage() until the second step
|
||||
// has taken place. This extra Cache operation ensure that all the
|
||||
// runnables have been flushed through the threads, etc.
|
||||
return caches.has(name);
|
||||
}).then(function(result) {
|
||||
ok(!result, 'cache should not exist in storage');
|
||||
// reset the quota manager storage to ensure the DB connection is flushed
|
||||
return resetStorage();
|
||||
}).then(function() {
|
||||
return storageUsage();
|
||||
}).then(function(usage) {
|
||||
endUsage = usage;
|
||||
dump("### ### initial:" + initialUsage + ", full:" + fullUsage +
|
||||
", end:" + endUsage + "\n");
|
||||
ok(endUsage < (fullUsage / 2), 'disk usage should have shrank significantly');
|
||||
ok(endUsage > initialUsage, 'disk usage should not shrink back to orig size');
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1381,7 +1381,7 @@ nsDOMCameraControl::OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces
|
||||
|
||||
if (faces.SetCapacity(len, fallible)) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
*faces.AppendElement() =
|
||||
*faces.AppendElement(fallible) =
|
||||
new DOMCameraDetectedFace(static_cast<DOMMediaStream*>(this), aFaces[i]);
|
||||
}
|
||||
}
|
||||
|
@ -2676,7 +2676,7 @@ void CanvasRenderingContext2D::DrawFocusIfNeeded(mozilla::dom::Element& aElement
|
||||
// set dashing for foreground
|
||||
FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
if (!dash.AppendElement(1)) {
|
||||
if (!dash.AppendElement(1, fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
@ -3964,14 +3964,14 @@ CanvasRenderingContext2D::SetLineDash(const Sequence<double>& aSegments,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dash.AppendElement(aSegments[x])) {
|
||||
if (!dash.AppendElement(aSegments[x], fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aSegments.Length() % 2) { // If the number of elements is odd, concatenate again
|
||||
for (uint32_t x = 0; x < aSegments.Length(); x++) {
|
||||
if (!dash.AppendElement(aSegments[x])) {
|
||||
if (!dash.AppendElement(aSegments[x], fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ JSValToDashArray(JSContext* cx, const JS::Value& patternArray,
|
||||
} else if (d > 0.0) {
|
||||
haveNonzeroElement = true;
|
||||
}
|
||||
if (!dashes.AppendElement(d)) {
|
||||
if (!dashes.AppendElement(d, mozilla::fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -349,19 +349,19 @@ TranslateDefaultAttachments(const dom::Sequence<GLenum>& in, dom::Sequence<GLenu
|
||||
for (size_t i = 0; i < in.Length(); i++) {
|
||||
switch (in[i]) {
|
||||
case LOCAL_GL_COLOR:
|
||||
if (!out->AppendElement(LOCAL_GL_COLOR_ATTACHMENT0)) {
|
||||
if (!out->AppendElement(LOCAL_GL_COLOR_ATTACHMENT0, fallible)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH:
|
||||
if (!out->AppendElement(LOCAL_GL_DEPTH_ATTACHMENT)) {
|
||||
if (!out->AppendElement(LOCAL_GL_DEPTH_ATTACHMENT, fallible)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_STENCIL:
|
||||
if (!out->AppendElement(LOCAL_GL_STENCIL_ATTACHMENT)) {
|
||||
if (!out->AppendElement(LOCAL_GL_STENCIL_ATTACHMENT, fallible)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -377,7 +377,7 @@ WebGLElementArrayCacheTree<T>::Update(size_t firstByte, size_t lastByte)
|
||||
if (requiredNumLeaves != NumLeaves()) {
|
||||
// See class comment for why we the tree storage size is 2 * numLeaves.
|
||||
if (!mTreeData.SetLength(2 * requiredNumLeaves, fallible)) {
|
||||
mTreeData.SetLength(0);
|
||||
mTreeData.Clear();
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(NumLeaves() == requiredNumLeaves);
|
||||
@ -471,7 +471,7 @@ WebGLElementArrayCache::BufferData(const void* ptr, size_t byteLength)
|
||||
{
|
||||
if (mBytes.Length() != byteLength) {
|
||||
if (!mBytes.SetLength(byteLength, fallible)) {
|
||||
mBytes.SetLength(0);
|
||||
mBytes.Clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ CryptoBuffer::Assign(const ArrayBufferViewOrArrayBuffer& aData)
|
||||
|
||||
// If your union is uninitialized, something's wrong
|
||||
MOZ_ASSERT(false);
|
||||
SetLength(0);
|
||||
Clear();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ CryptoBuffer::Assign(const OwningArrayBufferViewOrArrayBuffer& aData)
|
||||
|
||||
// If your union is uninitialized, something's wrong
|
||||
MOZ_ASSERT(false);
|
||||
SetLength(0);
|
||||
Clear();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -951,6 +951,41 @@ CryptoKey::PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey,
|
||||
}
|
||||
}
|
||||
|
||||
SECKEYPublicKey*
|
||||
CreateECPublicKey(const SECItem* aKeyData, const nsString& aNamedCurve)
|
||||
{
|
||||
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
|
||||
if (!arena) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
|
||||
if (!key) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
key->keyType = ecKey;
|
||||
key->pkcs11Slot = nullptr;
|
||||
key->pkcs11ID = CK_INVALID_HANDLE;
|
||||
|
||||
// Create curve parameters.
|
||||
SECItem* params = CreateECParamsForCurve(aNamedCurve, arena);
|
||||
if (!params) {
|
||||
return nullptr;
|
||||
}
|
||||
key->u.ec.DEREncodedParams = *params;
|
||||
|
||||
// Set public point.
|
||||
key->u.ec.publicValue = *aKeyData;
|
||||
|
||||
// Ensure the given point is on the curve.
|
||||
if (!CryptoKey::PublicKeyValid(key)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SECKEY_CopyPublicKey(key);
|
||||
}
|
||||
|
||||
SECKEYPublicKey*
|
||||
CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
@ -1002,39 +1037,18 @@ CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
|
||||
if (!key) {
|
||||
// Create point.
|
||||
SECItem* point = CreateECPointForCoordinates(x, y, arena.get());
|
||||
if (!point) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
key->keyType = ecKey;
|
||||
key->pkcs11Slot = nullptr;
|
||||
key->pkcs11ID = CK_INVALID_HANDLE;
|
||||
|
||||
nsString namedCurve;
|
||||
if (!NormalizeToken(aJwk.mCrv.Value(), namedCurve)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create parameters.
|
||||
SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
|
||||
if (!params) {
|
||||
return nullptr;
|
||||
}
|
||||
key->u.ec.DEREncodedParams = *params;
|
||||
|
||||
// Create point.
|
||||
SECItem* point = CreateECPointForCoordinates(x, y, arena.get());
|
||||
if (!point) {
|
||||
return nullptr;
|
||||
}
|
||||
key->u.ec.publicValue = *point;
|
||||
|
||||
if (!PublicKeyValid(key)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SECKEY_CopyPublicKey(key);
|
||||
return CreateECPublicKey(point, namedCurve);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -1115,6 +1129,57 @@ CryptoKey::PublicDhKeyToRaw(SECKEYPublicKey* aPubKey,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SECKEYPublicKey*
|
||||
CryptoKey::PublicECKeyFromRaw(CryptoBuffer& aKeyData,
|
||||
const nsString& aNamedCurve,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
|
||||
if (!arena) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SECItem rawItem = { siBuffer, nullptr, 0 };
|
||||
if (!aKeyData.ToSECItem(arena, &rawItem)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t flen;
|
||||
if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
|
||||
flen = 32; // bytes
|
||||
} else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
|
||||
flen = 48; // bytes
|
||||
} else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
|
||||
flen = 66; // bytes
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check length of uncompressed point coordinates. There are 2 field elements
|
||||
// and a leading point form octet (which must EC_POINT_FORM_UNCOMPRESSED).
|
||||
if (rawItem.len != (2 * flen + 1)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// No support for compressed points.
|
||||
if (rawItem.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateECPublicKey(&rawItem, aNamedCurve);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CryptoKey::PublicECKeyToRaw(SECKEYPublicKey* aPubKey,
|
||||
CryptoBuffer& aRetVal,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
if (!aRetVal.Assign(&aPubKey->u.ec.publicValue)) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey)
|
||||
{
|
||||
|
@ -180,6 +180,13 @@ public:
|
||||
CryptoBuffer& aRetVal,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/);
|
||||
|
||||
static SECKEYPublicKey* PublicECKeyFromRaw(CryptoBuffer& aKeyData,
|
||||
const nsString& aNamedCurve,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/);
|
||||
static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey,
|
||||
CryptoBuffer& aRetVal,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/);
|
||||
|
||||
static bool PublicKeyValid(SECKEYPublicKey* aPubKey);
|
||||
|
||||
// Structured clone methods use these to clone keys
|
||||
|
@ -563,16 +563,18 @@ private:
|
||||
// Perform the encryption/decryption
|
||||
if (mEncrypt) {
|
||||
rv = MapSECStatus(PK11_Encrypt(symKey.get(), mMechanism, ¶m,
|
||||
mResult.Elements(), &outLen, maxLen,
|
||||
mData.Elements(), mData.Length()));
|
||||
mResult.Elements(), &outLen,
|
||||
mResult.Length(), mData.Elements(),
|
||||
mData.Length()));
|
||||
} else {
|
||||
rv = MapSECStatus(PK11_Decrypt(symKey.get(), mMechanism, ¶m,
|
||||
mResult.Elements(), &outLen, maxLen,
|
||||
mData.Elements(), mData.Length()));
|
||||
mResult.Elements(), &outLen,
|
||||
mResult.Length(), mData.Elements(),
|
||||
mData.Length()));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
mResult.SetLength(outLen);
|
||||
mResult.TruncateLength(outLen);
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
@ -848,7 +850,7 @@ private:
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
mResult.SetLength(outLen);
|
||||
mResult.TruncateLength(outLen);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@ -934,10 +936,10 @@ private:
|
||||
rv = MapSECStatus(PK11_DigestOp(ctx.get(), mData.Elements(), mData.Length()));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
|
||||
rv = MapSECStatus(PK11_DigestFinal(ctx.get(), mResult.Elements(),
|
||||
&outLen, HASH_LENGTH_MAX));
|
||||
&outLen, mResult.Length()));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
mResult.SetLength(outLen);
|
||||
mResult.TruncateLength(outLen);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1644,7 +1646,7 @@ public:
|
||||
const ObjectOrString& aAlgorithm, bool aExtractable,
|
||||
const Sequence<nsString>& aKeyUsages)
|
||||
{
|
||||
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
|
||||
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
|
||||
}
|
||||
|
||||
ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
|
||||
@ -1652,7 +1654,7 @@ public:
|
||||
const ObjectOrString& aAlgorithm, bool aExtractable,
|
||||
const Sequence<nsString>& aKeyUsages)
|
||||
{
|
||||
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
|
||||
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
|
||||
if (NS_FAILED(mEarlyRv)) {
|
||||
return;
|
||||
}
|
||||
@ -1661,6 +1663,30 @@ public:
|
||||
NS_ENSURE_SUCCESS_VOID(mEarlyRv);
|
||||
}
|
||||
|
||||
void Init(JSContext* aCx, const nsAString& aFormat,
|
||||
const ObjectOrString& aAlgorithm, bool aExtractable,
|
||||
const Sequence<nsString>& aKeyUsages)
|
||||
{
|
||||
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
|
||||
if (NS_FAILED(mEarlyRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
|
||||
RootedDictionary<EcKeyImportParams> params(aCx);
|
||||
mEarlyRv = Coerce(aCx, params, aAlgorithm);
|
||||
if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
|
||||
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NormalizeToken(params.mNamedCurve.Value(), mNamedCurve)) {
|
||||
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mNamedCurve;
|
||||
|
||||
@ -1680,14 +1706,19 @@ private:
|
||||
|
||||
mKey->SetPrivateKey(privKey.get());
|
||||
mKey->SetType(CryptoKey::PRIVATE);
|
||||
} else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) ||
|
||||
} else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) ||
|
||||
mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) ||
|
||||
(mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK) &&
|
||||
!mJwk.mD.WasPassed())) {
|
||||
// Public key import
|
||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
|
||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
|
||||
pubKey = CryptoKey::PublicECKeyFromRaw(mKeyData, mNamedCurve, locker);
|
||||
} else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
|
||||
pubKey = CryptoKey::PublicKeyFromSpki(mKeyData, locker);
|
||||
} else {
|
||||
} else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
||||
pubKey = CryptoKey::PublicKeyFromJwk(mJwk, locker);
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
|
||||
if (!pubKey) {
|
||||
@ -1901,6 +1932,14 @@ private:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mPublicKey && mPublicKey->keyType == ecKey) {
|
||||
nsresult rv = CryptoKey::PublicECKeyToRaw(mPublicKey, mResult, locker);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mResult = mSymKey;
|
||||
if (mResult.Length() == 0) {
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
@ -1966,7 +2005,7 @@ private:
|
||||
|
||||
if (!mKeyUsages.IsEmpty()) {
|
||||
mJwk.mKey_ops.Construct();
|
||||
if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages)) {
|
||||
if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -518,6 +518,11 @@ tv = {
|
||||
"405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0adf"
|
||||
),
|
||||
|
||||
raw: util.hex2abv(
|
||||
"045ce7b86e3b32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e" +
|
||||
"98f4cf075b39405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0adf"
|
||||
),
|
||||
|
||||
secret: util.hex2abv(
|
||||
"35669cd5c244ba6c1ea89b8802c3d1db815cd769979072e6556eb98548c65f7d"
|
||||
)
|
||||
@ -606,7 +611,31 @@ tv = {
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
|
||||
}
|
||||
},
|
||||
|
||||
// Public point with Y not on the curve.
|
||||
raw_bad: util.hex2abv(
|
||||
"045ce7b86e3b32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e" +
|
||||
"98f4cf075b39405dd1f1adeb090106edcfb2b4963739d87679e3056cb0557d0adf"
|
||||
),
|
||||
|
||||
// Public point with Y a little too short.
|
||||
raw_short: util.hex2abv(
|
||||
"045ce7b86e3b32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e" +
|
||||
"98f4cf075b39405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0a"
|
||||
),
|
||||
|
||||
// Public point with Y a little too long.
|
||||
raw_long: util.hex2abv(
|
||||
"045ce7b86e3b32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e" +
|
||||
"98f4cf075b39405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0adfff"
|
||||
),
|
||||
|
||||
// Public point with EC_POINT_FORM_COMPRESSED_Y0.
|
||||
raw_compressed: util.hex2abv(
|
||||
"025ce7b86e3b32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e" +
|
||||
"98f4cf075b39405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0adf"
|
||||
)
|
||||
},
|
||||
|
||||
// NIST ECDSA test vectors
|
||||
@ -626,6 +655,13 @@ tv = {
|
||||
"9Y33NGQ1_wQ0GZWDyXxmWpfxL3BvI1faS0Aoje-Ijlnm",
|
||||
},
|
||||
|
||||
raw: util.hex2abv(
|
||||
"040061387fd6b95914e885f912edfbb5fb274655027f216c4091ca83e19336740fd" +
|
||||
"81aedfe047f51b42bdf68161121013e0d55b117a14e4303f926c8debb77a7fdaad1" +
|
||||
"00e7d0c75c38626e895ca21526b9f9fdf84dcecb93f2b233390550d2b1463b7ee3f" +
|
||||
"58df7346435ff0434199583c97c665a97f12f706f2357da4b40288def888e59e6"
|
||||
),
|
||||
|
||||
"data": util.hex2abv(
|
||||
"9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1" +
|
||||
"964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d255216" +
|
||||
|
@ -438,6 +438,114 @@ TestArray.addTest(
|
||||
.then(memcmp_complete(that, tv.ecdh_p256.secret), error(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Raw import/export of a public ECDH key (P-256)",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
|
||||
function doExport(x) {
|
||||
return crypto.subtle.exportKey("raw", x);
|
||||
}
|
||||
|
||||
crypto.subtle.importKey("raw", tv.ecdh_p256.raw, alg, true, ["deriveBits"])
|
||||
.then(doExport)
|
||||
.then(memcmp_complete(that, tv.ecdh_p256.raw), error(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Test that importing bad raw ECDH keys fails",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
var tvs = tv.ecdh_p256_negative.raw_bad;
|
||||
|
||||
crypto.subtle.importKey("raw", tv, alg, false, ["deriveBits"])
|
||||
.then(error(that), complete(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Test that importing ECDH keys with an unknown format fails",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
var tvs = tv.ecdh_p256.raw;
|
||||
|
||||
crypto.subtle.importKey("unknown", tv, alg, false, ["deriveBits"])
|
||||
.then(error(that), complete(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Test that importing too short raw ECDH keys fails",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
var tvs = tv.ecdh_p256_negative.raw_short;
|
||||
|
||||
crypto.subtle.importKey("raw", tv, alg, false, ["deriveBits"])
|
||||
.then(error(that), complete(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Test that importing too long raw ECDH keys fails",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
var tvs = tv.ecdh_p256_negative.raw_long;
|
||||
|
||||
crypto.subtle.importKey("raw", tv, alg, false, ["deriveBits"])
|
||||
.then(error(that), complete(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Test that importing compressed raw ECDH keys fails",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
var tvs = tv.ecdh_p256_negative.raw_compressed;
|
||||
|
||||
crypto.subtle.importKey("raw", tv, alg, false, ["deriveBits"])
|
||||
.then(error(that), complete(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"RAW/JWK import ECDH keys (P-256) and derive a known secret",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||
|
||||
var pubKey, privKey;
|
||||
function setPub(x) { pubKey = x; }
|
||||
function setPriv(x) { privKey = x; }
|
||||
|
||||
function doDerive() {
|
||||
var alg = { name: "ECDH", public: pubKey };
|
||||
return crypto.subtle.deriveBits(alg, privKey, tv.ecdh_p256.secret.byteLength * 8);
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
crypto.subtle.importKey("raw", tv.ecdh_p256.raw, alg, false, ["deriveBits"])
|
||||
.then(setPub),
|
||||
crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, false, ["deriveBits"])
|
||||
.then(setPriv)
|
||||
]).then(doDerive)
|
||||
.then(memcmp_complete(that, tv.ecdh_p256.secret), error(that));
|
||||
}
|
||||
);
|
||||
/*]]>*/</script>
|
||||
</head>
|
||||
|
||||
|
@ -144,6 +144,40 @@ TestArray.addTest(
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"Raw import/export of a public ECDSA key (P-521)",
|
||||
function () {
|
||||
var that = this;
|
||||
var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
||||
|
||||
function doExport(x) {
|
||||
return crypto.subtle.exportKey("raw", x);
|
||||
}
|
||||
|
||||
crypto.subtle.importKey("raw", tv.ecdsa_verify.raw, alg, true, ["verify"])
|
||||
.then(doExport)
|
||||
.then(memcmp_complete(that, tv.ecdsa_verify.raw), error(that));
|
||||
}
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
TestArray.addTest(
|
||||
"ECDSA raw import and verify a known-good signature",
|
||||
function() {
|
||||
var that = this;
|
||||
var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
||||
|
||||
function doVerify(x) {
|
||||
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig, tv.ecdsa_verify.data);
|
||||
}
|
||||
|
||||
crypto.subtle.importKey("raw", tv.ecdsa_verify.raw, alg, true, ["verify"])
|
||||
.then(doVerify)
|
||||
.then(complete(that), error(that))
|
||||
}
|
||||
);
|
||||
|
||||
/*]]>*/</script>
|
||||
</head>
|
||||
|
||||
|
@ -316,7 +316,8 @@ DataStoreDB::DatabaseOpened()
|
||||
}
|
||||
|
||||
StringOrStringSequence objectStores;
|
||||
if (!objectStores.RawSetAsStringSequence().AppendElements(mObjectStores)) {
|
||||
if (!objectStores.RawSetAsStringSequence().AppendElements(mObjectStores,
|
||||
fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1358,7 +1358,7 @@ DataStoreService::CreateFirstRevisionId(uint32_t aAppId,
|
||||
new FirstRevisionIdCallback(aAppId, aName, aManifestURL);
|
||||
|
||||
Sequence<nsString> dbs;
|
||||
if (!dbs.AppendElement(NS_LITERAL_STRING(DATASTOREDB_REVISION))) {
|
||||
if (!dbs.AppendElement(NS_LITERAL_STRING(DATASTOREDB_REVISION), fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,13 @@ HTMLAnchorElement::~HTMLAnchorElement()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLAnchorElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
|
||||
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||
}
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement)
|
||||
NS_INTERFACE_TABLE_INHERITED(HTMLAnchorElement,
|
||||
nsIDOMHTMLAnchorElement,
|
||||
|
@ -43,10 +43,7 @@ public:
|
||||
virtual bool Draggable() const override;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||
|
||||
// nsIDOMHTMLAnchorElement
|
||||
NS_DECL_NSIDOMHTMLANCHORELEMENT
|
||||
|
@ -1860,7 +1860,7 @@ HTMLInputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
|
||||
return;
|
||||
}
|
||||
Sequence<nsString> list;
|
||||
if (!list.AppendElement(aValue)) {
|
||||
if (!list.AppendElement(aValue, fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
@ -2445,7 +2445,7 @@ HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames, uint32_t aLen
|
||||
|
||||
Sequence<nsString> list;
|
||||
for (uint32_t i = 0; i < aLength; ++i) {
|
||||
if (!list.AppendElement(nsDependentString(aFileNames[i]))) {
|
||||
if (!list.AppendElement(nsDependentString(aFileNames[i]), fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@ -2498,7 +2498,7 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
|
||||
if (mType == NS_FORM_INPUT_FILE)
|
||||
{
|
||||
Sequence<nsString> list;
|
||||
if (!list.AppendElement(aValue)) {
|
||||
if (!list.AppendElement(aValue, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -3251,8 +3251,11 @@ nsHTMLDocument::ExecCommand(const nsAString& commandID,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isCutCopy = (commandID.LowerCaseEqualsLiteral("cut") ||
|
||||
commandID.LowerCaseEqualsLiteral("copy"));
|
||||
|
||||
// if editing is not on, bail
|
||||
if (!IsEditingOnAfterFlush()) {
|
||||
if (!isCutCopy && !IsEditingOnAfterFlush()) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
}
|
||||
@ -3262,14 +3265,33 @@ nsHTMLDocument::ExecCommand(const nsAString& commandID,
|
||||
return false;
|
||||
}
|
||||
|
||||
// special case for cut & copy
|
||||
// cut & copy are allowed in non editable documents
|
||||
if (isCutCopy) {
|
||||
if (!nsContentUtils::IsCutCopyAllowed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For cut & copy commands, we need the behaviour from nsWindowRoot::GetControllers
|
||||
// which is to look at the focused element, and defer to a focused textbox's controller
|
||||
// The code past taken by other commands in ExecCommand always uses the window directly,
|
||||
// rather than deferring to the textbox, which is desireable for most editor commands,
|
||||
// but not 'cut' and 'copy' (as those should allow copying out of embedded editors).
|
||||
// This behaviour is invoked if we call DoCommand directly on the docShell.
|
||||
nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
|
||||
if (docShell) {
|
||||
nsresult res = docShell->DoCommand(cmdToDispatch.get());
|
||||
return NS_SUCCEEDED(res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (commandID.LowerCaseEqualsLiteral("gethtml")) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool restricted = commandID.LowerCaseEqualsLiteral("cut") ||
|
||||
commandID.LowerCaseEqualsLiteral("copy")||
|
||||
commandID.LowerCaseEqualsLiteral("paste");
|
||||
bool restricted = commandID.LowerCaseEqualsLiteral("paste");
|
||||
if (restricted && !nsContentUtils::IsCallerChrome()) {
|
||||
rv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return false;
|
||||
|
@ -33,6 +33,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=229925
|
||||
<textarea class="yes" cols="1" rows="1"></textarea>
|
||||
<video class="yes" controls></video>
|
||||
|
||||
<a class="no">a</a>
|
||||
<audio class="no"></audio>
|
||||
<img class="no" src="data:image/png,">
|
||||
<input class="no" type="hidden">
|
||||
|
@ -8521,7 +8521,7 @@ ConvertBlobsToActors(PBackgroundParent* aBackgroundActor,
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(aActors.AppendElement(actor));
|
||||
MOZ_ALWAYS_TRUE(aActors.AppendElement(actor, fallible));
|
||||
|
||||
if (collectFileInfos) {
|
||||
nsRefPtr<FileInfo> fileInfo = file.mFileInfo;
|
||||
@ -8529,7 +8529,7 @@ ConvertBlobsToActors(PBackgroundParent* aBackgroundActor,
|
||||
// Transfer a reference to the receiver.
|
||||
auto transferedFileInfo =
|
||||
reinterpret_cast<intptr_t>(fileInfo.forget().take());
|
||||
MOZ_ALWAYS_TRUE(aFileInfos.AppendElement(transferedFileInfo));
|
||||
MOZ_ALWAYS_TRUE(aFileInfos.AppendElement(transferedFileInfo, fallible));
|
||||
}
|
||||
}
|
||||
|
||||
@ -12358,7 +12358,7 @@ Database::Invalidate()
|
||||
auto* array =
|
||||
static_cast<FallibleTArray<nsRefPtr<TransactionBase>>*>(aUserData);
|
||||
|
||||
if (NS_WARN_IF(!array->AppendElement(aEntry->GetKey()))) {
|
||||
if (NS_WARN_IF(!array->AppendElement(aEntry->GetKey(), fallible))) {
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
@ -12626,7 +12626,7 @@ Database::AllocPBackgroundIDBTransactionParent(
|
||||
|
||||
if (closure->mName == aValue->mCommonMetadata.name() &&
|
||||
!aValue->mDeleted) {
|
||||
MOZ_ALWAYS_TRUE(closure->mObjectStores.AppendElement(aValue));
|
||||
MOZ_ALWAYS_TRUE(closure->mObjectStores.AppendElement(aValue, fallible));
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
@ -18785,7 +18785,7 @@ FactoryOp::SendVersionChangeMessages(DatabaseActorInfo* aDatabaseActorInfo,
|
||||
Database* database = aDatabaseActorInfo->mLiveDatabases[index];
|
||||
if ((!aOpeningDatabase || database != aOpeningDatabase) &&
|
||||
!database->IsClosed() &&
|
||||
NS_WARN_IF(!maybeBlockedDatabases.AppendElement(database))) {
|
||||
NS_WARN_IF(!maybeBlockedDatabases.AppendElement(database, fallible))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@ -20904,7 +20904,8 @@ VersionChangeOp::RunOnOwningThread()
|
||||
MOZ_ASSERT(!info->mLiveDatabases.IsEmpty());
|
||||
|
||||
FallibleTArray<Database*> liveDatabases;
|
||||
if (NS_WARN_IF(!liveDatabases.AppendElements(info->mLiveDatabases))) {
|
||||
if (NS_WARN_IF(!liveDatabases.AppendElements(info->mLiveDatabases,
|
||||
fallible))) {
|
||||
deleteOp->SetFailureCode(NS_ERROR_OUT_OF_MEMORY);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
@ -23046,7 +23047,7 @@ ObjectStoreAddOrPutRequestOp::Init(TransactionBase* aTransaction)
|
||||
TPBackgroundIDBDatabaseFileParent ||
|
||||
fileOrFileId.type() == DatabaseFileOrMutableFileId::Tint64_t);
|
||||
|
||||
StoredFileInfo* storedFileInfo = mStoredFileInfos.AppendElement();
|
||||
StoredFileInfo* storedFileInfo = mStoredFileInfos.AppendElement(fallible);
|
||||
MOZ_ASSERT(storedFileInfo);
|
||||
|
||||
switch (fileOrFileId.type()) {
|
||||
@ -23609,7 +23610,7 @@ ObjectStoreGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
|
||||
bool hasResult;
|
||||
while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
|
||||
StructuredCloneReadInfo* cloneInfo = mResponse.AppendElement();
|
||||
StructuredCloneReadInfo* cloneInfo = mResponse.AppendElement(fallible);
|
||||
if (NS_WARN_IF(!cloneInfo)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -23736,7 +23737,7 @@ ObjectStoreGetAllKeysRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
|
||||
bool hasResult;
|
||||
while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
|
||||
Key* key = mResponse.AppendElement();
|
||||
Key* key = mResponse.AppendElement(fallible);
|
||||
if (NS_WARN_IF(!key)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -24158,7 +24159,7 @@ IndexGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
|
||||
bool hasResult;
|
||||
while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
|
||||
StructuredCloneReadInfo* cloneInfo = mResponse.AppendElement();
|
||||
StructuredCloneReadInfo* cloneInfo = mResponse.AppendElement(fallible);
|
||||
if (NS_WARN_IF(!cloneInfo)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -24350,7 +24351,7 @@ IndexGetKeyRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
|
||||
bool hasResult;
|
||||
while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
|
||||
Key* key = mResponse.AppendElement();
|
||||
Key* key = mResponse.AppendElement(fallible);
|
||||
if (NS_WARN_IF(!key)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1230,14 +1230,17 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(fileActorOrMutableFileIds.AppendElement(fileActor));
|
||||
MOZ_ALWAYS_TRUE(fileActorOrMutableFileIds.AppendElement(fileActor,
|
||||
fallible));
|
||||
} else {
|
||||
const int64_t fileId = blobOrFileInfo.mFileInfo->Id();
|
||||
MOZ_ASSERT(fileId > 0);
|
||||
|
||||
MOZ_ALWAYS_TRUE(fileActorOrMutableFileIds.AppendElement(fileId));
|
||||
MOZ_ALWAYS_TRUE(fileActorOrMutableFileIds.AppendElement(fileId,
|
||||
fallible));
|
||||
|
||||
nsRefPtr<FileInfo>* newFileInfo = fileInfosToKeepAlive.AppendElement();
|
||||
nsRefPtr<FileInfo>* newFileInfo =
|
||||
fileInfosToKeepAlive.AppendElement(fallible);
|
||||
if (NS_WARN_IF(!newFileInfo)) {
|
||||
aRv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return nullptr;
|
||||
|
@ -2035,6 +2035,15 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
|
||||
}
|
||||
|
||||
// Remove any and all idle listeners.
|
||||
nsCOMPtr<nsIIdleService> idleService =
|
||||
do_GetService("@mozilla.org/widget/idleservice;1");
|
||||
MOZ_ASSERT(idleService);
|
||||
nsRefPtr<ParentIdleListener> listener;
|
||||
for (int32_t i = mIdleListeners.Length() - 1; i >= 0; --i) {
|
||||
listener = static_cast<ParentIdleListener*>(mIdleListeners[i].get());
|
||||
idleService->RemoveIdleObserver(listener, listener->mTime);
|
||||
}
|
||||
mIdleListeners.Clear();
|
||||
|
||||
MessageLoop::current()->
|
||||
@ -4660,30 +4669,34 @@ ContentParent::RecvAddIdleObserver(const uint64_t& aObserver, const uint32_t& aI
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIIdleService> idleService =
|
||||
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsRefPtr<ParentIdleListener> listener = new ParentIdleListener(this, aObserver);
|
||||
mIdleListeners.Put(aObserver, listener);
|
||||
idleService->AddIdleObserver(listener, aIdleTimeInS);
|
||||
nsRefPtr<ParentIdleListener> listener =
|
||||
new ParentIdleListener(this, aObserver, aIdleTimeInS);
|
||||
rv = idleService->AddIdleObserver(listener, aIdleTimeInS);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
mIdleListeners.AppendElement(listener);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIIdleService> idleService =
|
||||
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsRefPtr<ParentIdleListener> listener;
|
||||
bool found = mIdleListeners.Get(aObserver, &listener);
|
||||
if (found) {
|
||||
mIdleListeners.Remove(aObserver);
|
||||
idleService->RemoveIdleObserver(listener, aIdleTimeInS);
|
||||
for (int32_t i = mIdleListeners.Length() - 1; i >= 0; --i) {
|
||||
listener = static_cast<ParentIdleListener*>(mIdleListeners[i].get());
|
||||
if (listener->mObserver == aObserver &&
|
||||
listener->mTime == aIdleTimeInS) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIIdleService> idleService =
|
||||
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
idleService->RemoveIdleObserver(listener, aIdleTimeInS);
|
||||
mIdleListeners.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -922,7 +922,7 @@ private:
|
||||
nsRefPtr<nsConsoleService> mConsoleService;
|
||||
nsConsoleService* GetConsoleService();
|
||||
|
||||
nsDataHashtable<nsUint64HashKey, nsRefPtr<ParentIdleListener> > mIdleListeners;
|
||||
nsTArray<nsCOMPtr<nsIObserver>> mIdleListeners;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Dup of child's X socket, used to scope its resources to this
|
||||
@ -942,17 +942,20 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
class ParentIdleListener : public nsIObserver {
|
||||
friend class mozilla::dom::ContentParent;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
ParentIdleListener(mozilla::dom::ContentParent* aParent, uint64_t aObserver)
|
||||
: mParent(aParent), mObserver(aObserver)
|
||||
ParentIdleListener(mozilla::dom::ContentParent* aParent, uint64_t aObserver, uint32_t aTime)
|
||||
: mParent(aParent), mObserver(aObserver), mTime(aTime)
|
||||
{}
|
||||
private:
|
||||
virtual ~ParentIdleListener() {}
|
||||
nsRefPtr<mozilla::dom::ContentParent> mParent;
|
||||
uint64_t mObserver;
|
||||
uint32_t mTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -508,8 +508,8 @@ MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
|
||||
}
|
||||
|
||||
// We ensure sufficient capacity above so this shouldn't fail.
|
||||
MOZ_ALWAYS_TRUE(mBuffer->AppendElements(aData, aSize));
|
||||
MOZ_ALWAYS_TRUE(mBuffer->AppendElements(RAW_DATA_ALIGNMENT));
|
||||
MOZ_ALWAYS_TRUE(mBuffer->AppendElements(aData, aSize, fallible));
|
||||
MOZ_ALWAYS_TRUE(mBuffer->AppendElements(RAW_DATA_ALIGNMENT, fallible));
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
@ -530,8 +530,8 @@ MediaRawData::Clone() const
|
||||
}
|
||||
|
||||
// We ensure sufficient capacity above so this shouldn't fail.
|
||||
MOZ_ALWAYS_TRUE(s->mBuffer->AppendElements(mData, mSize));
|
||||
MOZ_ALWAYS_TRUE(s->mBuffer->AppendElements(RAW_DATA_ALIGNMENT));
|
||||
MOZ_ALWAYS_TRUE(s->mBuffer->AppendElements(mData, mSize, fallible));
|
||||
MOZ_ALWAYS_TRUE(s->mBuffer->AppendElements(RAW_DATA_ALIGNMENT, fallible));
|
||||
s->mSize = mSize;
|
||||
}
|
||||
return s.forget();
|
||||
|
@ -579,8 +579,8 @@ void MediaDecoder::CallSeek(const SeekTarget& aTarget)
|
||||
mSeekRequest.Begin(ProxyMediaCall(mDecoderStateMachine->TaskQueue(),
|
||||
mDecoderStateMachine.get(), __func__,
|
||||
&MediaDecoderStateMachine::Seek, aTarget)
|
||||
->RefableThen(AbstractThread::MainThread(), __func__, this,
|
||||
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
|
||||
->Then(AbstractThread::MainThread(), __func__, this,
|
||||
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
|
||||
}
|
||||
|
||||
double MediaDecoder::GetCurrentTime()
|
||||
|
@ -1019,7 +1019,7 @@ protected:
|
||||
|
||||
virtual void CallSeek(const SeekTarget& aTarget);
|
||||
|
||||
MediaPromiseConsumerHolder<SeekPromise> mSeekRequest;
|
||||
MediaPromiseRequestHolder<SeekPromise> mSeekRequest;
|
||||
|
||||
// True when seeking or otherwise moving the play position around in
|
||||
// such a manner that progress event data is inaccurate. This is set
|
||||
|
@ -182,9 +182,6 @@ MediaDecoderReader::AsyncReadMetadata()
|
||||
mDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
|
||||
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
|
||||
|
||||
// PreReadMetadata causes us to try to allocate various hardware and OS
|
||||
// resources, which may not be available at the moment.
|
||||
PreReadMetadata();
|
||||
if (IsWaitingMediaResources()) {
|
||||
return MetadataPromise::CreateAndReject(Reason::WAITING_FOR_RESOURCES, __func__);
|
||||
}
|
||||
|
@ -165,13 +165,10 @@ public:
|
||||
virtual bool HasVideo() = 0;
|
||||
|
||||
// The default implementation of AsyncReadMetadata is implemented in terms of
|
||||
// synchronous PreReadMetadata() / ReadMetadata() calls. Implementations may also
|
||||
// synchronous ReadMetadata() calls. Implementations may also
|
||||
// override AsyncReadMetadata to create a more proper async implementation.
|
||||
virtual nsRefPtr<MetadataPromise> AsyncReadMetadata();
|
||||
|
||||
// A function that is called before ReadMetadata() call.
|
||||
virtual void PreReadMetadata() {};
|
||||
|
||||
// Read header data for all bitstreams in the file. Fills aInfo with
|
||||
// the data required to present the media, and optionally fills *aTags
|
||||
// with tag metadata from the file.
|
||||
|
@ -976,16 +976,16 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
|
||||
nsRefPtr<MediaDecoderStateMachine> self = this;
|
||||
WaitRequestRef(aType).Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::WaitForData, aType)
|
||||
->RefableThen(TaskQueue(), __func__,
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->WaitRequestRef(aType).Complete();
|
||||
self->DispatchDecodeTasksIfNeeded();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->WaitRequestRef(aRejection.mType).Complete();
|
||||
}));
|
||||
->Then(TaskQueue(), __func__,
|
||||
[self] (MediaData::Type aType) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->WaitRequestRef(aType).Complete();
|
||||
self->DispatchDecodeTasksIfNeeded();
|
||||
},
|
||||
[self] (WaitForDataRejectValue aRejection) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->WaitRequestRef(aRejection.mType).Complete();
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1961,20 +1961,20 @@ MediaDecoderStateMachine::InitiateSeek()
|
||||
mSeekRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::Seek, mCurrentSeek.mTarget.mTime,
|
||||
GetEndTime())
|
||||
->RefableThen(TaskQueue(), __func__,
|
||||
[self] (int64_t) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mSeekRequest.Complete();
|
||||
// We must decode the first samples of active streams, so we can determine
|
||||
// the new stream time. So dispatch tasks to do that.
|
||||
self->mDecodeToSeekTarget = true;
|
||||
self->DispatchDecodeTasksIfNeeded();
|
||||
}, [self] (nsresult aResult) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mSeekRequest.Complete();
|
||||
MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
|
||||
self->DecodeError();
|
||||
}));
|
||||
->Then(TaskQueue(), __func__,
|
||||
[self] (int64_t) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mSeekRequest.Complete();
|
||||
// We must decode the first samples of active streams, so we can determine
|
||||
// the new stream time. So dispatch tasks to do that.
|
||||
self->mDecodeToSeekTarget = true;
|
||||
self->DispatchDecodeTasksIfNeeded();
|
||||
}, [self] (nsresult aResult) -> void {
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mSeekRequest.Complete();
|
||||
MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
|
||||
self->DecodeError();
|
||||
}));
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2020,9 +2020,9 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
|
||||
|
||||
mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
|
||||
__func__, &MediaDecoderReader::RequestAudioData)
|
||||
->RefableThen(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded));
|
||||
->Then(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2080,9 +2080,9 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
|
||||
mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::RequestVideoData,
|
||||
skipToNextKeyFrame, currentTime)
|
||||
->RefableThen(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded));
|
||||
->Then(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2364,18 +2364,18 @@ MediaDecoderStateMachine::DecodeFirstFrame()
|
||||
if (HasAudio()) {
|
||||
mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
|
||||
__func__, &MediaDecoderReader::RequestAudioData)
|
||||
->RefableThen(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded));
|
||||
->Then(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded));
|
||||
}
|
||||
if (HasVideo()) {
|
||||
mVideoDecodeStartTime = TimeStamp::Now();
|
||||
mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
|
||||
__func__, &MediaDecoderReader::RequestVideoData, false,
|
||||
int64_t(0))
|
||||
->RefableThen(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded));
|
||||
->Then(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2648,9 +2648,9 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
DECODER_LOG("Dispatching AsyncReadMetadata");
|
||||
mMetadataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::AsyncReadMetadata)
|
||||
->RefableThen(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnMetadataRead,
|
||||
&MediaDecoderStateMachine::OnMetadataNotRead));
|
||||
->Then(TaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnMetadataRead,
|
||||
&MediaDecoderStateMachine::OnMetadataNotRead));
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user