merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-05-25 15:04:00 +02:00
Родитель c9627dfdcd ea8362bfe9
Коммит c715836c7f
938 изменённых файлов: 15999 добавлений и 4972 удалений

Просмотреть файл

@ -34,7 +34,7 @@ unwantedBlocked=The site at %S has been reported as serving unwanted software an
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
corruptedContentError=The site at %S has experienced a network protocol violation that cannot be repaired.
corruptedContentErrorv2=The site at %S has experienced a network protocol violation that cannot be repaired.
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
sslv3Used=Firefox cannot guarantee the safety of your data on %S because it uses SSLv3, a broken security protocol.
weakCryptoUsed=The owner of %S has configured their website improperly. To protect your information from being stolen, Firefox has not connected to this website.

Просмотреть файл

@ -87,5 +87,8 @@ tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME)
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
endif

Просмотреть файл

@ -211,6 +211,11 @@
<true/>
<key>NSPrincipalClass</key>
<string>GeckoNSApplication</string>
<key>SMPrivilegedExecutables</key>
<dict>
<key>org.mozilla.updater</key>
<string>identifier "org.mozilla.updater" and ((anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]) or (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "43AQ936H96"))</string>
</dict>
<key>NSDisablePersistence</key>
<true/>
</dict>

Просмотреть файл

@ -10,6 +10,9 @@ Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx";
const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never";
var gAppUpdater;
function onUnload(aEvent) {
@ -76,7 +79,8 @@ function appUpdater()
// update checks, but also in the About dialog, by presenting a
// "Check for updates" button.
// If updates are found, the user is then asked if he wants to "Update to <version>".
if (!this.updateEnabled) {
if (!this.updateEnabled ||
Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
this.selectPanel("checkForUpdates");
return;
}
@ -98,11 +102,13 @@ appUpdater.prototype =
get isPending() {
if (this.update) {
return this.update.state == "pending" ||
this.update.state == "pending-service";
this.update.state == "pending-service" ||
this.update.state == "pending-elevate";
}
return this.um.activeUpdate &&
(this.um.activeUpdate.state == "pending" ||
this.um.activeUpdate.state == "pending-service");
this.um.activeUpdate.state == "pending-service" ||
this.um.activeUpdate.state == "pending-elevate");
},
// true when there is an update already installed in the background.
@ -183,6 +189,13 @@ appUpdater.prototype =
* Check for updates
*/
checkForUpdates: function() {
// Clear prefs that could prevent a user from discovering available updates.
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
}
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
}
this.selectPanel("checkingForUpdates");
this.isChecking = true;
this.checker.checkForUpdates(this.updateCheckListener, true);
@ -194,30 +207,32 @@ appUpdater.prototype =
* which is presented after the download has been downloaded.
*/
buttonRestartAfterDownload: function() {
if (!this.isPending && !this.isApplied)
if (!this.isPending && !this.isApplied) {
return;
}
// Notify all windows that an application quit has been requested.
let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
createInstance(Components.interfaces.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
// Notify all windows that an application quit has been requested.
let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
createInstance(Components.interfaces.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
// Something aborted the quit process.
if (cancelQuit.data)
return;
// Something aborted the quit process.
if (cancelQuit.data) {
return;
}
let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
getService(Components.interfaces.nsIAppStartup);
let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
getService(Components.interfaces.nsIAppStartup);
// If already in safe mode restart in safe mode (bug 327119)
if (Services.appinfo.inSafeMode) {
appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
return;
}
// If already in safe mode restart in safe mode (bug 327119)
if (Services.appinfo.inSafeMode) {
appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
return;
}
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
Components.interfaces.nsIAppStartup.eRestart);
},
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
Components.interfaces.nsIAppStartup.eRestart);
},
/**
* Handles oncommand for the "Apply Update…" button
@ -371,7 +386,8 @@ appUpdater.prototype =
// Update the UI when the background updater is finished
let status = aData;
if (status == "applied" || status == "applied-service" ||
status == "pending" || status == "pending-service") {
status == "pending" || status == "pending-service" ||
status == "pending-elevate") {
// If the update is successfully applied, or if the updater has
// fallen back to non-staged updates, show the "Restart to Update"
// button.

Просмотреть файл

@ -521,7 +521,7 @@
<h1 id="et_nssBadCert">&certerror.longpagetitle1;</h1>
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
<h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
<h1 id="et_sslv3Used">&sslv3Used.title;</h1>
<h1 id="et_weakCryptoUsed">&weakCryptoUsed.title;</h1>
<h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
@ -550,7 +550,7 @@
<div id="ed_nssBadCert">&certerror.introPara;</div>
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
<div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
<div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
<div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc2;</div>
<div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>

24
browser/base/content/browser.js Normal file → Executable file
Просмотреть файл

@ -2568,6 +2568,7 @@ var gMenuButtonUpdateBadge = {
enabled: false,
badgeWaitTime: 0,
timer: null,
cancelObserverRegistered: false,
init: function () {
try {
@ -2592,6 +2593,10 @@ var gMenuButtonUpdateBadge = {
Services.obs.removeObserver(this, "update-downloaded");
this.enabled = false;
}
if (this.cancelObserverRegistered) {
Services.obs.removeObserver(this, "update-canceled");
this.cancelObserverRegistered = false;
}
},
onMenuPanelCommand: function(event) {
@ -2612,11 +2617,15 @@ var gMenuButtonUpdateBadge = {
},
observe: function (subject, topic, status) {
if (topic == "update-canceled") {
this.reset();
return;
}
if (status == "failed") {
// Background update has failed, let's show the UI responsible for
// prompting the user to update manually.
this.displayBadge(false);
this.uninit();
this.displayBadge(false);
return;
}
@ -2631,8 +2640,8 @@ var gMenuButtonUpdateBadge = {
// If the update is successfully applied, or if the updater has fallen back
// to non-staged updates, add a badge to the hamburger menu to indicate an
// update will be applied once the browser restarts.
this.displayBadge(true);
this.uninit();
this.displayBadge(true);
},
displayBadge: function (succeeded) {
@ -2648,6 +2657,8 @@ var gMenuButtonUpdateBadge = {
stringId = "appmenu.restartNeeded.description";
updateButtonText = gNavigatorBundle.getFormattedString(stringId,
[brandShortName]);
Services.obs.addObserver(this, "update-canceled", false);
this.cancelObserverRegistered = true;
} else {
stringId = "appmenu.updateFailed.description";
updateButtonText = gNavigatorBundle.getString(stringId);
@ -2657,6 +2668,15 @@ var gMenuButtonUpdateBadge = {
updateButton.setAttribute("label", updateButtonText);
updateButton.setAttribute("update-status", status);
updateButton.hidden = false;
},
reset: function () {
gMenuButtonBadgeManager.removeBadge(
gMenuButtonBadgeManager.BADGEID_APPUPDATE);
let updateButton = document.getElementById("PanelUI-update-status");
updateButton.hidden = true;
this.uninit();
this.init();
}
};

Просмотреть файл

@ -60,6 +60,73 @@ var TabStateCacheInternal = {
return this._data.get(browserOrTab.permanentKey);
},
/**
* Helper function used by update (see below). For message size
* optimization sometimes we don't update the whole session storage
* only the values those have been changed.
*
* @param data (object)
* The cached data where we want to update the changes.
* @param change (object)
* The actual changed values per domain.
*/
updatePartialStorageChange: function (data, change) {
if (!data.storage) {
data.storage = {};
}
let storage = data.storage;
for (let domain of Object.keys(change)) {
for (let key of Object.keys(change[domain])) {
let value = change[domain][key];
if (value === null) {
if (storage[domain] && storage[domain][key]) {
delete storage[domain][key];
}
} else {
if (!storage[domain]) {
storage[domain] = {};
}
storage[domain][key] = value;
}
}
}
},
/**
* Helper function used by update (see below). For message size
* optimization sometimes we don't update the whole browser history
* only the current index and the tail of the history from a certain
* index (specified by change.fromIdx)
*
* @param data (object)
* The cached data where we want to update the changes.
* @param change (object)
* Object containing the tail of the history array, and
* some additional metadata.
*/
updatePartialHistoryChange: function (data, change) {
const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
if (!data.history) {
data.history = { entries: [] };
}
let history = data.history;
for (let key of Object.keys(change)) {
if (key == "entries") {
if (change.fromIdx != kLastIndex) {
history.entries.splice(change.fromIdx + 1);
while (change.entries.length) {
history.entries.push(change.entries.shift());
}
}
} else if (key != "fromIndex") {
history[key] = change[key];
}
}
},
/**
* Updates cached data for a given |tab| or associated |browser|.
*
@ -73,6 +140,16 @@ var TabStateCacheInternal = {
let data = this._data.get(browserOrTab.permanentKey) || {};
for (let key of Object.keys(newData)) {
if (key == "storagechange") {
this.updatePartialStorageChange(data, newData.storagechange);
continue;
}
if (key == "historychange") {
this.updatePartialHistoryChange(data, newData.historychange);
continue;
}
let value = newData[key];
if (value === null) {
delete data[key];

Просмотреть файл

@ -49,6 +49,9 @@ const DOM_STORAGE_MAX_CHARS = 10000000; // 10M characters
// or not, and should only be used for tests or debugging.
const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates";
const kNoIndex = Number.MAX_SAFE_INTEGER;
const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
/**
* Returns a lazy function that will evaluate the given
* function |fn| only once and cache its return value.
@ -252,11 +255,51 @@ var SessionHistoryListener = {
},
collect: function () {
this._fromIdx = kNoIndex;
if (docShell) {
MessageQueue.push("history", () => SessionHistory.collect(docShell));
}
},
_fromIdx: kNoIndex,
// History can grow relatively big with the nested elements, so if we don't have to, we
// don't want to send the entire history all the time. For a simple optimization
// we keep track of the smallest index from after any change has occured and we just send
// the elements from that index. If something more complicated happens we just clear it
// and send the entire history. We always send the additional info like the current selected
// index (so for going back and forth between history entries we set the index to kLastIndex
// if nothing else changed send an empty array and the additonal info like the selected index)
collectFrom: function (idx) {
if (this._fromIdx <= idx) {
// If we already know that we need to update history fromn index N we can ignore any changes
// tha happened with an element with index larger than N.
// Note: initially we use kNoIndex which is MAX_SAFE_INTEGER which means we don't ignore anything
// here, and in case of navigation in the history back and forth we use kLastIndex which ignores
// only the subsequent navigations, but not any new elements added.
return;
}
this._fromIdx = idx;
MessageQueue.push("historychange", () => {
if (this._fromIdx === kNoIndex) {
return null;
}
let history = SessionHistory.collect(docShell);
if (kLastIndex == idx) {
history.entries = [];
} else {
history.entries.splice(0, this._fromIdx + 1);
}
history.fromIdx = this._fromIdx;
this._fromIdx = kNoIndex;
return history;
});
},
handleEvent(event) {
this.collect();
},
@ -269,22 +312,22 @@ var SessionHistoryListener = {
this.collect();
},
OnHistoryNewEntry: function (newURI) {
this.collect();
OnHistoryNewEntry: function (newURI, oldIndex) {
this.collectFrom(oldIndex);
},
OnHistoryGoBack: function (backURI) {
this.collect();
this.collectFrom(kLastIndex);
return true;
},
OnHistoryGoForward: function (forwardURI) {
this.collect();
this.collectFrom(kLastIndex);
return true;
},
OnHistoryGotoIndex: function (index, gotoURI) {
this.collect();
this.collectFrom(kLastIndex);
return true;
},
@ -496,7 +539,7 @@ var SessionStorageListener = {
handleEvent: function (event) {
if (gFrameTree.contains(event.target)) {
this.collect();
this.collectFromEvent(event);
}
},
@ -537,8 +580,47 @@ var SessionStorageListener = {
return size;
},
// We don't want to send all the session storage data for all the frames
// for every change. So if only a few value changed we send them over as
// a "storagechange" event. If however for some reason before we send these
// changes we have to send over the entire sessions storage data, we just
// reset these changes.
_changes: undefined,
resetChanges: function () {
this._changes = undefined;
},
collectFromEvent: function (event) {
// TODO: we should take browser.sessionstore.dom_storage_limit into an account here.
if (docShell) {
let {url, key, newValue} = event;
let uri = Services.io.newURI(url, null, null);
let domain = uri.prePath;
if (!this._changes) {
this._changes = {};
}
if (!this._changes[domain]) {
this._changes[domain] = {};
}
this._changes[domain][key] = newValue;
MessageQueue.push("storagechange", () => {
let tmp = this._changes;
// If there were multiple changes we send them merged.
// First one will collect all the changes the rest of
// these messages will be ignored.
this.resetChanges();
return tmp;
});
}
},
collect: function () {
if (docShell) {
// We need the entire session storage, let's reset the pending individual change
// messages.
this.resetChanges();
MessageQueue.push("storage", () => {
let collected = SessionStorage.collect(docShell, gFrameTree);
@ -727,7 +809,7 @@ var MessageQueue = {
for (let histogramId of Object.keys(value)) {
telemetry[histogramId] = value[histogramId];
}
} else {
} else if (value || (key != "storagechange" && key != "historychange")) {
data[key] = value;
}
}

Просмотреть файл

@ -35,6 +35,7 @@
#ifdef XP_MACOSX
; Mac bundle stuff
@APPNAME@/Contents/Info.plist
@APPNAME@/Contents/Library/LaunchServices
@APPNAME@/Contents/PkgInfo
@RESPATH@/firefox.icns
@RESPATH@/document.icns

Просмотреть файл

@ -35,7 +35,7 @@ unwantedBlocked=The site at %S has been reported as serving unwanted software an
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
corruptedContentError=The site at %S has experienced a network protocol violation that cannot be repaired.
corruptedContentErrorv2=The site at %S has experienced a network protocol violation that cannot be repaired.
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
## LOCALIZATION NOTE (sslv3Used) - Do not translate "%S".
sslv3Used=Firefox cannot guarantee the safety of your data on %S because it uses SSLv3, a broken security protocol.

Просмотреть файл

@ -165,8 +165,8 @@ was trying to connect. -->
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
<!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
<!ENTITY corruptedContentError.title "Corrupted Content Error">
<!ENTITY corruptedContentError.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
<!ENTITY corruptedContentErrorv2.title "Corrupted Content Error">
<!ENTITY corruptedContentErrorv2.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">

Просмотреть файл

@ -251,7 +251,6 @@ def old_configure_options(*options):
'--enable-system-pixman',
'--enable-system-sqlite',
'--enable-tasktracer',
'--enable-tests',
'--enable-thread-sanitizer',
'--enable-trace-logging',
'--enable-tree-freetype',

Просмотреть файл

@ -36,12 +36,15 @@ def get_hg_info(workdir):
repo = 'https://' + repo[6:]
repo = repo.rstrip('/')
changeset = get_program_output(
'hg', '-R', workdir, 'parent', '--template={node}')
changeset = get_hg_changeset(workdir)
return repo, changeset
def get_hg_changeset(path):
return get_program_output('hg', '-R', path, 'parent', '--template={node}')
def source_repo_header(output):
# We allow the source repo and changeset to be specified via the
# environment (see configure)
@ -50,13 +53,14 @@ def source_repo_header(output):
changeset = buildconfig.substs.get('MOZ_SOURCE_CHANGESET')
source = ''
if bool(repo) != bool(changeset):
raise Exception('MOZ_SOURCE_REPO and MOZ_SOURCE_CHANGESET both must '
'be set (or not set).')
if not repo:
if os.path.exists(os.path.join(buildconfig.topsrcdir, '.hg')):
repo, changeset = get_hg_info(buildconfig.topsrcdir)
elif not changeset:
changeset = get_hg_changeset(buildconfig.topsrcdir)
if not changeset:
raise Exception('could not resolve changeset; '
'try setting MOZ_SOURCE_CHANGESET')
if changeset:
output.write('#define MOZ_SOURCE_STAMP %s\n' % changeset)

1
config/external/nss/nss.symbols поставляемый
Просмотреть файл

@ -690,6 +690,7 @@ SSL_SetSockPeerID
SSL_SetSRTPCiphers
SSL_SetStapledOCSPResponses
SSL_SetURL
SSL_ShutdownServerSessionIDCache
SSL_SNISocketConfigHook
SSL_VersionRangeGet
SSL_VersionRangeGetDefault

Просмотреть файл

@ -73,14 +73,14 @@ class _MozTestResult(_TestResult):
def printFail(self, test, err):
exctype, value, tb = err
message = value.message.splitlines()[0]
# Skip test runner traceback levels
while tb and self._is_relevant_tb_level(tb):
tb = tb.tb_next
if not tb:
self.stream.writeln("TEST-UNEXPECTED-FAIL | NO TRACEBACK |")
_f, _ln, _t = inspect.getframeinfo(tb)[:3]
self.printStatus('TEST-UNEXPECTED-FAIL', test,
'line {0}: {1}'.format(_ln, value.message))
if tb:
_, ln, _ = inspect.getframeinfo(tb)[:3]
message = 'line {0}: {1}'.format(ln, message)
self.printStatus("TEST-UNEXPECTED-FAIL", test, message)
class MozTestRunner(_TestRunner):

Просмотреть файл

@ -23,7 +23,7 @@ var testData = [
["n", {}, "none", -1, 0, true],
["VK_TAB", {shiftKey: true}, "display", -1, 0, true],
["VK_BACK_SPACE", {}, "", -1, 0, false],
["o", {}, "overflow", 13, 16, false],
["o", {}, "overflow", 13, 17, false],
["u", {}, "outline", 0, 5, false],
["VK_DOWN", {}, "outline-color", 1, 5, false],
["VK_TAB", {}, "none", -1, 0, true],

Просмотреть файл

@ -602,19 +602,19 @@ ResponsiveUI.prototype = {
let volumeUp = this.chromeDoc.createElement("button");
volumeUp.className = "devtools-responsiveui-volume-up-button";
volumeUp.addEventListener("mousedown", () => {
SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeUp"});
SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "AudioVolumeUp"});
});
volumeUp.addEventListener("mouseup", () => {
SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeUp"});
SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "AudioVolumeUp"});
});
let volumeDown = this.chromeDoc.createElement("button");
volumeDown.className = "devtools-responsiveui-volume-down-button";
volumeDown.addEventListener("mousedown", () => {
SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeDown"});
SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "AudioVolumeDown"});
});
volumeDown.addEventListener("mouseup", () => {
SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeDown"});
SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "AudioVolumeDown"});
});
volumeButtons.appendChild(volumeUp);

Просмотреть файл

@ -5066,11 +5066,11 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
break;
case NS_ERROR_CORRUPTED_CONTENT:
// Broken Content Detected. e.g. Content-MD5 check failure.
error.AssignLiteral("corruptedContentError");
error.AssignLiteral("corruptedContentErrorv2");
break;
case NS_ERROR_INTERCEPTION_FAILED:
// ServiceWorker intercepted request, but something went wrong.
error.AssignLiteral("corruptedContentError");
error.AssignLiteral("corruptedContentErrorv2");
break;
case NS_ERROR_NET_INADEQUATE_SECURITY:
// Server negotiated bad TLS for HTTP/2.

Просмотреть файл

@ -307,7 +307,7 @@
<h1 id="et_nssBadCert">&nssBadCert.title;</h1>
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
<h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
<h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
</div>
<div id="errorDescriptionsContainer">
@ -334,7 +334,7 @@
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
<div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
<div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>
</div>
</div>

Просмотреть файл

@ -30,8 +30,9 @@ interface nsISHistoryListener : nsISupports
* or content area, for example via nsIWebNavigation::loadURI()
*
* @param aNewURI The URI of the document to be added to session history.
* @param aOldIndex The index of the current history item before the operation.
*/
void OnHistoryNewEntry(in nsIURI aNewURI);
void OnHistoryNewEntry(in nsIURI aNewURI, in long aOldIndex);
/**
* Called when navigating to a previous session history entry, for example

Просмотреть файл

@ -402,7 +402,7 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
nsCOMPtr<nsIURI> uri;
aSHEntry->GetURI(getter_AddRefs(uri));
NOTIFY_LISTENERS(OnHistoryNewEntry, (uri));
NOTIFY_LISTENERS(OnHistoryNewEntry, (uri, currentIndex));
// If a listener has changed mIndex, we need to get currentTxn again,
// otherwise we'll be left at an inconsistent state (see bug 320742)

Просмотреть файл

@ -553,7 +553,8 @@ ScreenOrientation::UpdateActiveOrientationLock(ScreenOrientationInternal aOrient
if (aOrientation == eScreenOrientation_None) {
hal::UnlockScreenOrientation();
} else {
hal::LockScreenOrientation(aOrientation);
bool rv = hal::LockScreenOrientation(aOrientation);
NS_WARN_IF(!rv);
}
}

Просмотреть файл

@ -444,6 +444,7 @@ LOCAL_INCLUDES += [
'/js/xpconnect/src',
'/js/xpconnect/wrappers',
'/layout/base',
'/layout/forms',
'/layout/generic',
'/layout/style',
'/layout/svg',

Просмотреть файл

@ -3056,10 +3056,11 @@ nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr);
if (!aDoc) {
return imgLoader::Singleton();
return imgLoader::NormalLoader();
}
bool isPrivate = IsInPrivateBrowsing(aDoc);
return isPrivate ? imgLoader::PBSingleton() : imgLoader::Singleton();
return isPrivate ? imgLoader::PrivateBrowsingLoader()
: imgLoader::NormalLoader();
}
// static
@ -3069,11 +3070,14 @@ nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
{
NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr);
if (!aChannel)
return imgLoader::Singleton();
if (!aChannel) {
return imgLoader::NormalLoader();
}
nsCOMPtr<nsILoadContext> context;
NS_QueryNotificationCallbacks(aChannel, context);
return context && context->UsePrivateBrowsing() ? imgLoader::PBSingleton() : imgLoader::Singleton();
return context && context->UsePrivateBrowsing() ?
imgLoader::PrivateBrowsingLoader() :
imgLoader::NormalLoader();
}
// static

Просмотреть файл

@ -2634,15 +2634,6 @@ private:
static nsIIOService *sIOService;
static nsIUUIDGenerator *sUUIDGenerator;
static bool sImgLoaderInitialized;
static void InitImgLoader();
// The following four members are initialized lazily
static imgLoader* sImgLoader;
static imgLoader* sPrivateImgLoader;
static imgICache* sImgCache;
static imgICache* sPrivateImgCache;
static nsIConsoleService* sConsoleService;
static nsDataHashtable<nsISupportsHashKey, EventNameMapping>* sAtomEventTable;

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsStyleCoord.h"
#include "TabChild.h"
#include "nsFrameLoader.h"
#include "nsNumberControlFrame.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/dom/Element.h"
@ -310,6 +311,24 @@ nsFocusManager::GetFocusedDescendant(nsPIDOMWindowOuter* aWindow, bool aDeep,
nsIContent*
nsFocusManager::GetRedirectedFocus(nsIContent* aContent)
{
// For input number, redirect focus to our anonymous text control.
if (aContent->IsHTMLElement(nsGkAtoms::input)) {
bool typeIsNumber =
static_cast<dom::HTMLInputElement*>(aContent)->GetType() ==
NS_FORM_INPUT_NUMBER;
if (typeIsNumber) {
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(aContent->GetPrimaryFrame());
if (numberControlFrame) {
HTMLInputElement* textControl =
numberControlFrame->GetAnonTextControl();
return static_cast<nsIContent*>(textControl);
}
}
}
#ifdef MOZ_XUL
if (aContent->IsXULElement()) {
nsCOMPtr<nsIDOMNode> inputField;
@ -1505,8 +1524,8 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags)
if (!aContent)
return nullptr;
// this is a special case for some XUL elements where an anonymous child is
// actually focusable and not the element itself.
// this is a special case for some XUL elements or input number, where an
// anonymous child is actually focusable and not the element itself.
nsIContent* redirectedFocus = GetRedirectedFocus(aContent);
if (redirectedFocus)
return CheckIfFocusable(redirectedFocus, aFlags);

Просмотреть файл

@ -114,7 +114,7 @@ public:
/**
* Returns the content node that focus will be redirected to if aContent was
* focused. This is used for the special case of certain XUL elements such
* as textboxes which redirect focus to an anonymous child.
* as textboxes or input number which redirect focus to an anonymous child.
*
* aContent must be non-null.
*

Просмотреть файл

@ -2770,9 +2770,9 @@ function runKeyTests()
{ key: "F24", keyCode: KeyboardEvent.DOM_VK_F24 },
{ key: "NumLock", keyCode: KeyboardEvent.DOM_VK_NUM_LOCK, isModifier: true, isLockableModifier: true },
{ key: "ScrollLock", keyCode: KeyboardEvent.DOM_VK_SCROLL_LOCK, isModifier: true, isLockableModifier: true },
{ key: "VolumeMute", keyCode: KeyboardEvent.DOM_VK_VOLUME_MUTE },
{ key: "VolumeDown", keyCode: KeyboardEvent.DOM_VK_VOLUME_DOWN },
{ key: "VolumeUp", keyCode: KeyboardEvent.DOM_VK_VOLUME_UP },
{ key: "AudioVolumeMute", keyCode: KeyboardEvent.DOM_VK_VOLUME_MUTE },
{ key: "AudioVolumeDown", keyCode: KeyboardEvent.DOM_VK_VOLUME_DOWN },
{ key: "AudioVolumeUp", keyCode: KeyboardEvent.DOM_VK_VOLUME_UP },
{ key: "Meta", keyCode: KeyboardEvent.DOM_VK_META, isModifier: true },
{ key: "AltGraph", keyCode: KeyboardEvent.DOM_VK_ALTGR, isModifier: true },
{ key: "Attn", keyCode: KeyboardEvent.DOM_VK_ATTN },

Просмотреть файл

@ -1673,7 +1673,7 @@ BrowserElementChild.prototype = {
sendAsyncMsg('error', { type: 'unsafeContentType' });
return;
case Cr.NS_ERROR_CORRUPTED_CONTENT :
sendAsyncMsg('error', { type: 'corruptedContentError' });
sendAsyncMsg('error', { type: 'corruptedContentErrorv2' });
return;
default:

Просмотреть файл

@ -26,6 +26,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/EventTimelineMarker.h"
@ -1714,12 +1715,25 @@ EventListenerManager::IsApzAwareListener(Listener* aListener)
bool
EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
{
return aEvent == nsGkAtoms::ontouchstart ||
aEvent == nsGkAtoms::ontouchmove ||
aEvent == nsGkAtoms::onwheel ||
aEvent == nsGkAtoms::onDOMMouseScroll ||
aEvent == nsHtml5Atoms::onmousewheel ||
aEvent == nsGkAtoms::onMozMousePixelScroll;
if (aEvent == nsGkAtoms::onwheel ||
aEvent == nsGkAtoms::onDOMMouseScroll ||
aEvent == nsHtml5Atoms::onmousewheel ||
aEvent == nsGkAtoms::onMozMousePixelScroll) {
return true;
}
// In theory we should schedule a repaint if the touch event pref changes,
// because the event regions might be out of date. In practice that seems like
// overkill because users generally shouldn't be flipping this pref, much
// less expecting touch listeners on the page to immediately start preventing
// scrolling without so much as a repaint. Tests that we write can work
// around this constraint easily enough.
if (TouchEvent::PrefEnabled()) {
if (aEvent == nsGkAtoms::ontouchstart ||
aEvent == nsGkAtoms::ontouchmove) {
return true;
}
}
return false;
}
already_AddRefed<nsIScriptGlobalObject>

Просмотреть файл

@ -29,12 +29,14 @@ DEFINE_KEYNAME_WITH_SAME_NAME(Unidentified)
* Our Internal Key Values (must have "Moz" prefix)
*****************************************************************************/
DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey")
DEFINE_KEYNAME_INTERNAL(HomeScreen, "MozHomeScreen")
DEFINE_KEYNAME_INTERNAL(CameraFocusAdjust, "MozCameraFocusAdjust")
DEFINE_KEYNAME_INTERNAL(PhoneCall, "MozPhoneCall")
DEFINE_KEYNAME_INTERNAL(SoftLeft, "MozSoftLeft")
DEFINE_KEYNAME_INTERNAL(SoftRight, "MozSoftRight")
#ifdef MOZ_B2G
DEFINE_KEYNAME_INTERNAL(HomeScreen, "MozHomeScreen")
DEFINE_KEYNAME_INTERNAL(CameraFocusAdjust, "MozCameraFocusAdjust")
#endif // #ifdef MOZ_B2G
/******************************************************************************
* Modifier Keys
*****************************************************************************/
@ -248,9 +250,16 @@ DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderRear)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioSurroundModeNext)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioTrebleDown)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioTrebleUp)
#ifndef MOZ_B2G
DEFINE_KEYNAME_WITH_SAME_NAME(AudioVolumeDown)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioVolumeUp)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioVolumeMute)
#else
// Temporarily, remaining for B2G
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeDown)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeUp)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeMute)
#endif
DEFINE_KEYNAME_WITH_SAME_NAME(MicrophoneToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(MicrophoneVolumeDown)
DEFINE_KEYNAME_WITH_SAME_NAME(MicrophoneVolumeUp)

Просмотреть файл

@ -165,28 +165,33 @@ TouchEvent::ChangedTouches()
bool
TouchEvent::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
{
static bool sPrefCached = false;
static int32_t sPrefCacheValue = 0;
if (!sPrefCached) {
sPrefCached = true;
Preferences::AddIntVarCache(&sPrefCacheValue, "dom.w3c_touch_events.enabled");
}
bool prefValue = false;
int32_t flag = 0;
if (NS_SUCCEEDED(Preferences::GetInt("dom.w3c_touch_events.enabled", &flag))) {
if (flag == 2) {
if (sPrefCacheValue == 2) {
#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
prefValue = true;
// Touch support is always enabled on B2G and android.
prefValue = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
static bool sDidCheckTouchDeviceSupport = false;
static bool sIsTouchDeviceSupportPresent = false;
// On Windows and GTK3 we auto-detect based on device support.
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
}
prefValue = sIsTouchDeviceSupportPresent;
#else
prefValue = false;
#endif
} else {
prefValue = !!flag;
static bool sDidCheckTouchDeviceSupport = false;
static bool sIsTouchDeviceSupportPresent = false;
// On Windows and GTK3 we auto-detect based on device support.
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
}
prefValue = sIsTouchDeviceSupportPresent;
#else
prefValue = false;
#endif
} else {
prefValue = !!sPrefCacheValue;
}
if (prefValue) {
nsContentUtils::InitializeTouchEventTable();

Просмотреть файл

@ -51,6 +51,7 @@ skip-if = os == "android" || buildapp == "mulet"
[test_input_number_validation.html]
# We don't build ICU for Firefox for Android or Firefox OS:
skip-if = os == "android" || appname == "b2g"
[test_input_number_focus.html]
[test_input_range_attr_order.html]
[test_input_range_key_events.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage

Просмотреть файл

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1268556
-->
<head>
<title>Test focus behaviour for &lt;input type='number'&gt;</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268556">Mozilla Bug 1268556</a>
<p id="display"></p>
<div id="content">
<input id="input" type="number">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Test for Bug 1268556.
* This test checks that when focusing on an input type=number, the focus is
* redirected to the anonymous text control, but the document.activeElement
* still returns the <input type=number>.
**/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
test();
SimpleTest.finish();
});
function test() {
var number = document.getElementById("input");
number.focus();
// The active element returns the input type=number.
var activeElement = document.activeElement;
is (activeElement, number, "activeElement should be the number element");
is (activeElement.localName, "input", "activeElement should be an input element");
is (activeElement.getAttribute("type"), "number", "activeElement should of type number");
// Use FocusManager to check that the actual focus is on the anonymous
// text control.
var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]
.getService(SpecialPowers.Ci.nsIFocusManager);
var focusedElement = fm.focusedElement;
is (focusedElement.localName, "input", "focusedElement should be an input element");
is (focusedElement.getAttribute("type"), "text", "focusedElement should of type text");
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -6,7 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=369370
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test for Bug 369370</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -141,7 +141,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=369370
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set":[["browser.enable_automatic_image_resizing", true]]}, function() {
kidWin = window.open("bug369370-popup.png", "bug369370", "width=400,height=300");
kidWin = window.open("bug369370-popup.png", "bug369370", "width=400,height=300,scrollbars=no");
// will init onload
ok(kidWin, "opened child window");
kidWin.onload = childLoaded;

Просмотреть файл

@ -202,12 +202,21 @@ function guessKeyNameFromKeyCode(KeyboardEvent, aKeyCode) {
return "NumLock";
case KeyboardEvent.DOM_VK_SCROLL_LOCK:
return "ScrollLock";
#ifndef MOZ_B2G
case KeyboardEvent.DOM_VK_VOLUME_MUTE:
return "AudioVolumeMute";
case KeyboardEvent.DOM_VK_VOLUME_DOWN:
return "AudioVolumeDown";
case KeyboardEvent.DOM_VK_VOLUME_UP:
return "AudioVolumeUp";
#else
case KeyboardEvent.DOM_VK_VOLUME_MUTE:
return "VolumeMute";
case KeyboardEvent.DOM_VK_VOLUME_DOWN:
return "VolumeDown";
case KeyboardEvent.DOM_VK_VOLUME_UP:
return "VolumeUp";
#endif
case KeyboardEvent.DOM_VK_META:
return "Meta";
case KeyboardEvent.DOM_VK_ALTGR:

Просмотреть файл

@ -3,4 +3,4 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
content/global/forms.js (forms.js)
* content/global/forms.js (forms.js)

Просмотреть файл

@ -34,7 +34,7 @@ unwantedBlocked=The site at %S has been reported as serving unwanted software an
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
corruptedContentError=The site at %S has experienced a network protocol violation that cannot be repaired.
corruptedContentErrorv2=The site at %S has experienced a network protocol violation that cannot be repaired.
remoteXUL=This page uses an unsupported technology that is no longer available by default.
sslv3Used=The safety of your data on %S could not be guaranteed because it uses SSLv3, a broken security protocol.
weakCryptoUsed=The owner of %S has configured their website improperly. To protect your information from being stolen, the connection to this website has not been established.

Просмотреть файл

@ -87,8 +87,8 @@
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
<!ENTITY cspBlocked.longDesc "<p>The browser prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
<!ENTITY corruptedContentError.title "Corrupted Content Error">
<!ENTITY corruptedContentError.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
<!ENTITY corruptedContentErrorv2.title "Corrupted Content Error">
<!ENTITY corruptedContentErrorv2.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
<!ENTITY remoteXUL.title "Remote XUL">
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">

Просмотреть файл

@ -473,6 +473,7 @@ nsMathMLElement::ParseNumericValue(const nsString& aString,
else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter;
else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point;
else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica;
else if (unit.EqualsLiteral("q")) cssUnit = eCSSUnit_Quarter;
else { // unexpected unit
if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) {
ReportLengthParseError(aString, aDocument);

Просмотреть файл

@ -1251,7 +1251,8 @@ MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
mLogicallySeeking = false;
}
UpdateLogicalPosition(aVal.mEventVisibility);
// Ensure logical position is updated after seek.
UpdateLogicalPositionInternal(aVal.mEventVisibility);
if (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed) {
mOwner->SeekCompleted();
@ -1302,14 +1303,10 @@ MediaDecoder::ChangeState(PlayState aState)
}
void
MediaDecoder::UpdateLogicalPosition(MediaDecoderEventVisibility aEventVisibility)
MediaDecoder::UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown)
return;
// Per spec, offical position remains stable during pause and seek.
if (mPlayState == PLAY_STATE_PAUSED || IsSeeking()) {
if (mShuttingDown) {
return;
}

Просмотреть файл

@ -411,11 +411,15 @@ private:
// thread.
void SeekingStarted(MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable);
void UpdateLogicalPosition(MediaDecoderEventVisibility aEventVisibility);
void UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility);
void UpdateLogicalPosition()
{
MOZ_ASSERT(NS_IsMainThread());
UpdateLogicalPosition(MediaDecoderEventVisibility::Observable);
// Per spec, offical position remains stable during pause and seek.
if (mPlayState == PLAY_STATE_PAUSED || IsSeeking()) {
return;
}
UpdateLogicalPositionInternal(MediaDecoderEventVisibility::Observable);
}
// Find the end of the cached data starting at the current decoder

Просмотреть файл

@ -87,10 +87,6 @@ MediaFormatReader::Shutdown()
{
MOZ_ASSERT(OnTaskQueue());
if (HasVideo()) {
ReportDroppedFramesTelemetry();
}
mDemuxerInitRequest.DisconnectIfExists();
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mSeekPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
@ -959,9 +955,6 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
LOG("%s stream id has changed from:%d to:%d, draining decoder.",
TrackTypeToStr(aTrack), decoder.mLastStreamSourceID,
info->GetID());
if (aTrack == TrackType::kVideoTrack) {
ReportDroppedFramesTelemetry();
}
decoder.mNeedDraining = true;
decoder.mNextStreamSourceID = Some(info->GetID());
ScheduleUpdate(aTrack);
@ -1160,7 +1153,6 @@ MediaFormatReader::Update(TrackType aTrack)
Some(TimeInterval(TimeUnit::FromMicroseconds(output->mTime),
TimeUnit::FromMicroseconds(output->GetEndTime())));
decoder.mNumSamplesOutputTotal++;
decoder.mNumSamplesOutputTotalSinceTelemetry++;
ReturnOutput(output, aTrack);
// We have a decoded sample ready to be returned.
if (aTrack == TrackType::kVideoTrack) {
@ -1205,6 +1197,15 @@ MediaFormatReader::Update(TrackType aTrack)
LOGV("Nothing more to do");
return;
}
} else if (decoder.mDemuxEOS && !decoder.mNeedDraining &&
!decoder.mDraining && !decoder.mDrainComplete &&
decoder.mQueuedSamples.IsEmpty()) {
// It is possible to transition from WAITING_FOR_DATA directly to EOS
// state during the internal seek; in which case no draining would occur.
// There is no more samples left to be decoded and we are already in
// EOS state. We can immediately reject the data promise.
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
decoder.RejectPromise(END_OF_STREAM, __func__);
}
}
@ -1452,7 +1453,6 @@ MediaFormatReader::VideoSkipReset(uint32_t aSkipped)
}
mVideo.mNumSamplesSkippedTotal += aSkipped;
mVideo.mNumSamplesSkippedTotalSinceTelemetry += aSkipped;
}
void
@ -1894,51 +1894,4 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
aString += NS_ConvertUTF8toUTF16(result);
}
void
MediaFormatReader::ReportDroppedFramesTelemetry()
{
MOZ_ASSERT(OnTaskQueue());
const VideoInfo* info =
mVideo.mInfo ? mVideo.mInfo->GetAsVideoInfo() : &mInfo.mVideo;
if (!info || !mVideo.mDecoder) {
return;
}
nsCString keyPhrase = nsCString("MimeType=");
keyPhrase.Append(info->mMimeType);
keyPhrase.Append("; ");
keyPhrase.Append("Resolution=");
keyPhrase.AppendInt(info->mDisplay.width);
keyPhrase.Append('x');
keyPhrase.AppendInt(info->mDisplay.height);
keyPhrase.Append("; ");
keyPhrase.Append("HardwareAcceleration=");
if (VideoIsHardwareAccelerated()) {
keyPhrase.Append(mVideo.mDecoder->GetDescriptionName());
keyPhrase.Append("enabled");
} else {
keyPhrase.Append("disabled");
}
if (mVideo.mNumSamplesOutputTotalSinceTelemetry) {
uint32_t percentage =
100 * mVideo.mNumSamplesSkippedTotalSinceTelemetry /
mVideo.mNumSamplesOutputTotalSinceTelemetry;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
LOG("Reporting telemetry DROPPED_FRAMES_IN_VIDEO_PLAYBACK");
Telemetry::Accumulate(Telemetry::VIDEO_DETAILED_DROPPED_FRAMES_PROPORTION,
keyPhrase,
percentage);
});
AbstractThread::MainThread()->Dispatch(task.forget());
}
mVideo.mNumSamplesSkippedTotalSinceTelemetry = 0;
mVideo.mNumSamplesOutputTotalSinceTelemetry = 0;
}
} // namespace mozilla

Просмотреть файл

@ -243,8 +243,6 @@ private:
, mNumSamplesOutput(0)
, mNumSamplesOutputTotal(0)
, mNumSamplesSkippedTotal(0)
, mNumSamplesOutputTotalSinceTelemetry(0)
, mNumSamplesSkippedTotalSinceTelemetry(0)
, mSizeOfQueue(0)
, mIsHardwareAccelerated(false)
, mLastStreamSourceID(UINT32_MAX)
@ -325,9 +323,6 @@ private:
uint64_t mNumSamplesOutputTotal;
uint64_t mNumSamplesSkippedTotal;
uint64_t mNumSamplesOutputTotalSinceTelemetry;
uint64_t mNumSamplesSkippedTotalSinceTelemetry;
// These get overridden in the templated concrete class.
// Indicate if we have a pending promise for decoded frame.
// Rejecting the promise will stop the reader from decoding ahead.
@ -538,9 +533,6 @@ private:
{
OnSeekFailed(TrackType::kAudioTrack, aFailure);
}
void ReportDroppedFramesTelemetry();
// The SeekTarget that was last given to Seek()
SeekTarget mOriginalSeekTarget;
// Temporary seek information while we wait for the data

Просмотреть файл

@ -4,18 +4,19 @@
* 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 "MediaShutdownManager.h"
#include "nsContentUtils.h"
#include "mozilla/StaticPtr.h"
#include "MediaDecoder.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPtr.h"
#include "nsContentUtils.h"
#include "MediaDecoder.h"
#include "MediaShutdownManager.h"
namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
#define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIObserver)
NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIAsyncShutdownBlocker)
MediaShutdownManager::MediaShutdownManager()
: mIsObservingShutdown(false)
@ -45,6 +46,23 @@ MediaShutdownManager::Instance()
return *sInstance;
}
static nsCOMPtr<nsIAsyncShutdownClient>
GetShutdownBarrier()
{
nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
MOZ_RELEASE_ASSERT(svc);
nsCOMPtr<nsIAsyncShutdownClient> barrier;
nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
if (!barrier) {
// We are probably in a content process.
rv = svc->GetContentChildShutdown(getter_AddRefs(barrier));
}
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
MOZ_RELEASE_ASSERT(barrier);
return barrier.forget();
}
void
MediaShutdownManager::EnsureCorrectShutdownObserverState()
{
@ -52,12 +70,16 @@ MediaShutdownManager::EnsureCorrectShutdownObserverState()
if (needShutdownObserver != mIsObservingShutdown) {
mIsObservingShutdown = needShutdownObserver;
if (mIsObservingShutdown) {
nsContentUtils::RegisterShutdownObserver(this);
nsresult rv = GetShutdownBarrier()->AddBlocker(
this, NS_LITERAL_STRING(__FILE__), __LINE__,
NS_LITERAL_STRING("MediaShutdownManager shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
} else {
nsContentUtils::UnregisterShutdownObserver(this);
GetShutdownBarrier()->RemoveBlocker(this);
// Clear our singleton reference. This will probably delete
// this instance, so don't deref |this| clearing sInstance.
sInstance = nullptr;
DECODER_LOG(LogLevel::Debug, ("MediaShutdownManager::BlockShutdown() end."));
}
}
}
@ -86,24 +108,25 @@ MediaShutdownManager::Unregister(MediaDecoder* aDecoder)
}
NS_IMETHODIMP
MediaShutdownManager::Observe(nsISupports *aSubjet,
const char *aTopic,
const char16_t *someData)
MediaShutdownManager::GetName(nsAString& aName)
{
MOZ_ASSERT(NS_IsMainThread());
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
Shutdown();
}
aName = NS_LITERAL_STRING("MediaShutdownManager: shutdown");
return NS_OK;
}
void
MediaShutdownManager::Shutdown()
NS_IMETHODIMP
MediaShutdownManager::GetState(nsIPropertyBag**)
{
return NS_OK;
}
NS_IMETHODIMP
MediaShutdownManager::BlockShutdown(nsIAsyncShutdownClient*)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sInstance);
DECODER_LOG(LogLevel::Debug, ("MediaShutdownManager::Shutdown() start..."));
DECODER_LOG(LogLevel::Debug, ("MediaShutdownManager::BlockShutdown() start..."));
// Set this flag to ensure no Register() is allowed when Shutdown() begins.
mIsDoingXPCOMShutDown = true;
@ -119,15 +142,7 @@ MediaShutdownManager::Shutdown()
MOZ_ASSERT(mDecoders.Count() == oldCount);
}
// Spin the loop until all decoders are unregistered
// which will then clear |sInstance|.
while (sInstance) {
NS_ProcessNextEvent(NS_GetCurrentThread(), true);
}
// Note: Don't access |this| which might be deleted after clearing sInstance.
DECODER_LOG(LogLevel::Debug, ("MediaShutdownManager::Shutdown() end."));
return NS_OK;
}
} // namespace mozilla

Просмотреть файл

@ -7,43 +7,35 @@
#if !defined(MediaShutdownManager_h_)
#define MediaShutdownManager_h_
#include "nsIObserver.h"
#include "mozilla/Monitor.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPtr.h"
#include "nsIThread.h"
#include "nsCOMPtr.h"
#include "nsTHashtable.h"
#include "nsIAsyncShutdown.h"
#include "nsIThread.h"
#include "nsHashKeys.h"
#include "nsTHashtable.h"
namespace mozilla {
class MediaDecoder;
// The MediaShutdownManager manages shutting down the MediaDecoder
// infrastructure in response to an xpcom-shutdown notification. This happens
// when Gecko is shutting down in the middle of operation. This is tricky, as
// there are a number of moving parts that must be shutdown in a particular
// order. Additionally the xpcom-shutdown observer *must* block until all
// threads are shutdown, which is tricky since we have a number of threads
// here and their shutdown is asynchronous. We can't have each element of
// our pipeline listening for xpcom-shutdown, as if each observer blocks
// waiting for its threads to shutdown it will block other xpcom-shutdown
// notifications from firing, and shutdown of one part of the media pipeline
// (say the State Machine thread) may depend another part to be shutdown
// first (the MediaDecoder threads). The MediaShutdownManager encapsulates
// all these dependencies, and provides a single xpcom-shutdown listener
// for the MediaDecoder infrastructure, to ensure that no shutdown order
// dependencies leak out of the MediaDecoder stack. The MediaShutdownManager
// is a singleton.
// infrastructure in response to an xpcom-shutdown notification.
// This happens when Gecko is shutting down in the middle of operation.
// This is tricky, as there are a number of moving parts that must
// be shutdown in a particular order. The MediaShutdownManager
// encapsulates all these dependencies to ensure that no shutdown
// order dependencies leak out of the MediaDecoder stack.
// The MediaShutdownManager is a singleton.
//
// The MediaShutdownManager ensures that the MediaDecoder stack is shutdown
// before returning from its xpcom-shutdown observer by keeping track of all
// the active MediaDecoders, and upon xpcom-shutdown calling Shutdown() on
// every MediaDecoder and then spinning the main thread event loop until all
// SharedThreadPools have shutdown. Once the SharedThreadPools are shutdown,
// all the state machines and their threads have been shutdown, the
// xpcom-shutdown observer returns.
// The MediaShutdownManager ensures that the MediaDecoder stack
// is shutdown before exiting xpcom-shutdown stage by registering
// itself with nsIAsyncShutdownService to receive notification
// when the stage of shutdown has started and then calls Shutdown()
// on every MediaDecoder. Shutdown will not proceed until all
// MediaDecoders finish shutdown and MediaShutdownManager unregisters
// itself from the async shutdown service.
//
// Note that calling the Unregister() functions may result in the singleton
// being deleted, so don't store references to the singleton, always use the
@ -57,10 +49,10 @@ class MediaDecoder;
// MediaShutdownManager& instance = MediaShutdownManager::Instance();
// instance.Unregister(someDecoder); // Warning! May delete instance!
// instance.Register(someOtherDecoder); // BAD! instance may be dangling!
class MediaShutdownManager : public nsIObserver {
class MediaShutdownManager : public nsIAsyncShutdownBlocker {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIASYNCSHUTDOWNBLOCKER
// The MediaShutdownManager is a singleton, access its instance with
// this accessor.
@ -80,8 +72,6 @@ private:
MediaShutdownManager();
virtual ~MediaShutdownManager();
void Shutdown();
// Ensures we have a shutdown listener if we need one, and removes the
// listener and destroys the singleton if we don't.
void EnsureCorrectShutdownObserverState();

Просмотреть файл

@ -10,6 +10,7 @@
#include "VorbisDecoder.h" // For VorbisLayout
#include "mozilla/Endian.h"
#include "mozilla/PodOperations.h"
#include "mozilla/SyncRunnable.h"
#include <stdint.h>
#include <inttypes.h> // For PRId64
@ -21,7 +22,7 @@ extern mozilla::LogModule* GetPDMLog();
namespace mozilla {
OpusDataDecoder::OpusDataDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mInfo(aConfig)
, mTaskQueue(aTaskQueue)
@ -31,6 +32,7 @@ OpusDataDecoder::OpusDataDecoder(const AudioInfo& aConfig,
, mDecodedHeader(false)
, mPaddingDiscarded(false)
, mFrames(0)
, mIsFlushing(false)
{
}
@ -133,15 +135,17 @@ nsresult
OpusDataDecoder::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
this, &OpusDataDecoder::Decode,
RefPtr<MediaRawData>(aSample)));
this, &OpusDataDecoder::ProcessDecode, aSample));
return NS_OK;
}
void
OpusDataDecoder::Decode(MediaRawData* aSample)
OpusDataDecoder::ProcessDecode(MediaRawData* aSample)
{
if (mIsFlushing) {
return;
}
if (DoDecode(aSample) == -1) {
mCallback->Error();
} else if(mTaskQueue->IsEmpty()) {
@ -299,7 +303,7 @@ OpusDataDecoder::DoDecode(MediaRawData* aSample)
}
void
OpusDataDecoder::DoDrain()
OpusDataDecoder::ProcessDrain()
{
mCallback->DrainComplete();
}
@ -307,21 +311,27 @@ OpusDataDecoder::DoDrain()
nsresult
OpusDataDecoder::Drain()
{
mTaskQueue->Dispatch(NewRunnableMethod(this, &OpusDataDecoder::DoDrain));
mTaskQueue->Dispatch(NewRunnableMethod(this, &OpusDataDecoder::ProcessDrain));
return NS_OK;
}
nsresult
OpusDataDecoder::Flush()
{
mTaskQueue->Flush();
if (mOpusDecoder) {
if (!mOpusDecoder) {
return NS_OK;
}
mIsFlushing = true;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([this] () {
MOZ_ASSERT(mOpusDecoder);
// Reset the decoder.
opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
mSkip = mOpusParser->mPreSkip;
mPaddingDiscarded = false;
mLastFrameTime.reset();
}
});
SyncRunnable::DispatchToThread(mTaskQueue, runnable);
mIsFlushing = false;
return NS_OK;
}

Просмотреть файл

@ -18,7 +18,7 @@ class OpusDataDecoder : public MediaDataDecoder
{
public:
OpusDataDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
~OpusDataDecoder();
@ -38,12 +38,12 @@ public:
private:
nsresult DecodeHeader(const unsigned char* aData, size_t aLength);
void Decode (MediaRawData* aSample);
int DoDecode (MediaRawData* aSample);
void DoDrain ();
void ProcessDecode(MediaRawData* aSample);
int DoDecode(MediaRawData* aSample);
void ProcessDrain();
const AudioInfo& mInfo;
RefPtr<FlushableTaskQueue> mTaskQueue;
const RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
// Opus decoder state
@ -60,6 +60,8 @@ private:
int64_t mFrames;
Maybe<int64_t> mLastFrameTime;
uint8_t mMappingTable[MAX_AUDIO_CHANNELS]; // Channel mapping table.
Atomic<bool> mIsFlushing;
};
} // namespace mozilla

Просмотреть файл

@ -808,17 +808,6 @@ WMFVideoMFTManager::IsHardwareAccelerated(nsACString& aFailureReason) const
return mDecoder && mUseHwAccel;
}
const char*
WMFVideoMFTManager::GetDescriptionName() const
{
if (mDecoder && mUseHwAccel && mDXVA2Manager) {
return (mDXVA2Manager->IsD3D11()) ?
"D3D11 Hardware Decoder" : "D3D9 Hardware Decoder";
} else {
return "wmf software video decoder";
}
}
void
WMFVideoMFTManager::ConfigurationChanged(const TrackInfo& aConfig)
{

Просмотреть файл

@ -41,7 +41,12 @@ public:
void ConfigurationChanged(const TrackInfo& aConfig) override;
const char* GetDescriptionName() const override;
const char* GetDescriptionName() const override
{
nsCString failureReason;
return IsHardwareAccelerated(failureReason)
? "wmf hardware video decoder" : "wmf software video decoder";
}
private:

Просмотреть файл

@ -91,8 +91,6 @@ MediaEngineRemoteVideoSource::Shutdown()
Deallocate();
}
mozilla::camera::Shutdown();
mState = kReleased;
mInitDone = false;
return;

Просмотреть файл

@ -55,6 +55,11 @@ onmessage = function(event) {
}
onpush = function(event) {
var pushResolve;
event.waitUntil(new Promise(function(resolve) {
pushResolve = resolve;
}));
// FIXME(catalinb): push message carry no data. So we assume the only
// push message we get is "wait"
clients.matchAll().then(function(client) {
@ -65,11 +70,10 @@ onpush = function(event) {
client[0].postMessage({type: "push", state: state});
state = "wait";
event.waitUntil(new Promise(function(res, rej) {
if (resolvePromiseCallback) {
dump("ERROR: service worker was already waiting on a promise.\n");
}
resolvePromiseCallback = res;
}));
if (resolvePromiseCallback) {
dump("ERROR: service worker was already waiting on a promise.\n");
} else {
resolvePromiseCallback = pushResolve;
}
});
}

Просмотреть файл

@ -257,7 +257,7 @@
.then(setShutdownObserver(false))
.then(checkStateAndUpdate(pushEvent, "from_scope", "wait"))
.then(setShutdownObserver(true))
.then(checkStateAndUpdate(messageEventIframe, "wait", "update"))
.then(checkStateAndUpdate(messageEventIframe, "wait", "release"))
.then(waitOnShutdownObserver)
.then(closeIframe)
}

Просмотреть файл

@ -58,7 +58,6 @@ function testWindow(w)
checkFeature('menubar');
checkFeature('toolbar');
checkFeature('personalbar');
checkFeature('scrollbars');
checkFeature('statusbar', 'status');
checkFeature('locationbar', 'location');

Просмотреть файл

@ -205,42 +205,152 @@ namespace {
// Holds the worker alive until the waitUntil promise is resolved or
// rejected.
class KeepAliveHandler final : public PromiseNativeHandler
class KeepAliveHandler final
{
nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
// Use an internal class to listen for the promise resolve/reject
// callbacks. This class also registers a feature so that it can
// preemptively cleanup if the service worker is timed out and
// terminated.
class InternalHandler final : public PromiseNativeHandler
, public WorkerFeature
{
nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
virtual ~KeepAliveHandler()
{}
// Worker thread only
WorkerPrivate* mWorkerPrivate;
RefPtr<Promise> mPromise;
bool mFeatureAdded;
~InternalHandler()
{
MaybeCleanup();
}
bool
AddFeature()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mFeatureAdded);
mFeatureAdded = mWorkerPrivate->AddFeature(this);
return mFeatureAdded;
}
void
MaybeCleanup()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mPromise) {
return;
}
if (mFeatureAdded) {
mWorkerPrivate->RemoveFeature(this);
}
mPromise = nullptr;
mKeepAliveToken = nullptr;
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MaybeCleanup();
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MaybeCleanup();
}
bool
Notify(Status aStatus) override
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (aStatus < Terminating) {
return true;
}
MaybeCleanup();
return true;
}
InternalHandler(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
WorkerPrivate* aWorkerPrivate,
Promise* aPromise)
: mKeepAliveToken(aKeepAliveToken)
, mWorkerPrivate(aWorkerPrivate)
, mPromise(aPromise)
, mFeatureAdded(false)
{
MOZ_ASSERT(mKeepAliveToken);
MOZ_ASSERT(mWorkerPrivate);
MOZ_ASSERT(mPromise);
}
public:
static already_AddRefed<InternalHandler>
Create(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
WorkerPrivate* aWorkerPrivate,
Promise* aPromise)
{
RefPtr<InternalHandler> ref = new InternalHandler(aKeepAliveToken,
aWorkerPrivate,
aPromise);
if (NS_WARN_IF(!ref->AddFeature())) {
return nullptr;
}
return ref.forget();
}
NS_DECL_ISUPPORTS
};
// This is really just a wrapper class to keep the InternalHandler
// private. We don't want any code to accidentally call
// Promise::AppendNativeHandler() without also referencing the promise.
// Therefore we force all code through the static CreateAndAttachToPromise()
// and use the private InternalHandler object.
KeepAliveHandler() = delete;
~KeepAliveHandler() = delete;
public:
NS_DECL_ISUPPORTS
explicit KeepAliveHandler(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken)
: mKeepAliveToken(aKeepAliveToken)
{ }
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
// Create a private handler object and attach it to the given Promise.
// This will also create a strong ref to the Promise in a ref cycle. The
// ref cycle is broken when the Promise is fulfilled or the worker thread
// is Terminated.
static void
CreateAndAttachToPromise(const nsMainThreadPtrHandle<KeepAliveToken>& aKeepAliveToken,
Promise* aPromise)
{
#ifdef DEBUG
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
#endif
}
MOZ_ASSERT(aKeepAliveToken);
MOZ_ASSERT(aPromise);
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
#ifdef DEBUG
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
#endif
// This creates a strong ref to the promise.
RefPtr<InternalHandler> handler = InternalHandler::Create(aKeepAliveToken,
workerPrivate,
aPromise);
if (NS_WARN_IF(!handler)) {
return;
}
// This then creates a strong ref cycle between the promise and the
// handler. The cycle is broken when the Promise is fulfilled or
// the worker thread is Terminated.
aPromise->AppendNativeHandler(handler);
}
};
NS_IMPL_ISUPPORTS0(KeepAliveHandler)
NS_IMPL_ISUPPORTS0(KeepAliveHandler::InternalHandler)
class RegistrationUpdateRunnable : public Runnable
{
@ -311,9 +421,8 @@ public:
}
MOZ_ASSERT(waitUntilPromise);
RefPtr<KeepAliveHandler> keepAliveHandler =
new KeepAliveHandler(mKeepAliveToken);
waitUntilPromise->AppendNativeHandler(keepAliveHandler);
KeepAliveHandler::CreateAndAttachToPromise(mKeepAliveToken,
waitUntilPromise);
if (aWaitUntilPromise) {
waitUntilPromise.forget(aWaitUntilPromise);
@ -1389,9 +1498,8 @@ private:
RefPtr<Promise> waitUntilPromise = event->GetPromise();
if (waitUntilPromise) {
RefPtr<KeepAliveHandler> keepAliveHandler =
new KeepAliveHandler(mKeepAliveToken);
waitUntilPromise->AppendNativeHandler(keepAliveHandler);
KeepAliveHandler::CreateAndAttachToPromise(mKeepAliveToken,
waitUntilPromise);
}
return true;

Просмотреть файл

@ -0,0 +1,23 @@
function postMessageToTest(msg) {
return clients.matchAll({ includeUncontrolled: true })
.then(list => {
for (var client of list) {
if (client.url.endsWith('test_install_event_gc.html')) {
client.postMessage(msg);
break;
}
}
});
}
addEventListener('install', evt => {
// This must be a simple promise to trigger the CC failure.
evt.waitUntil(new Promise(function() { }));
postMessageToTest({ type: 'INSTALL_EVENT' });
});
addEventListener('message', evt => {
if (evt.data.type === 'ping') {
postMessageToTest({ type: 'pong' });
}
});

Просмотреть файл

@ -203,6 +203,7 @@ support-files =
!/dom/security/test/cors/file_CrossSiteXHR_server.sjs
!/dom/tests/mochitest/notification/MockServices.js
!/dom/tests/mochitest/notification/NotificationTest.js
blocking_install_event_worker.js
[test_bug1151916.html]
[test_bug1240436.html]
@ -235,6 +236,7 @@ skip-if = (debug && e10s) # Bug 1262224
[test_importscript_mixedcontent.html]
tags = mcb
[test_install_event.html]
[test_install_event_gc.html]
[test_installation_simple.html]
[test_match_all.html]
[test_match_all_advanced.html]

Просмотреть файл

@ -0,0 +1,121 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test install event being GC'd before waitUntil fulfills</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
var script = 'blocking_install_event_worker.js';
var scope = 'sw_clients/simple.html?install-event-gc';
var registration;
function register() {
return navigator.serviceWorker.register(script, { scope: scope })
.then(swr => registration = swr);
}
function unregister() {
if (!registration) {
return;
}
return registration.unregister();
}
function waitForInstallEvent() {
return new Promise((resolve, reject) => {
navigator.serviceWorker.addEventListener('message', evt => {
if (evt.data.type === 'INSTALL_EVENT') {
resolve();
}
});
});
}
function gcWorker() {
return new Promise(function(resolve, reject) {
// We are able to trigger asynchronous garbage collection and cycle
// collection by emitting "child-cc-request" and "child-gc-request"
// observer notifications. The worker RuntimeService will translate
// these notifications into the appropriate operation on all known
// worker threads.
//
// In the failure case where GC/CC causes us to abort the installation,
// we will know something happened from the statechange event.
const statechangeHandler = evt => {
// Reject rather than resolving to avoid the possibility of us seeing
// an unrelated racing statechange somehow. Since in the success case we
// will still see a state change on termination, we do explicitly need to
// be removed on the success path.
ok(registration.installing, 'service worker is still installing?');
reject();
};
registration.installing.addEventListener('statechange', statechangeHandler);
// In the success case since the service worker installation is effectively
// hung, we instead depend on sending a 'ping' message to the service worker
// and hearing it 'pong' back. Since we issue our postMessage after we
// trigger the GC/CC, our 'ping' will only be processed after the GC/CC and
// therefore the pong will also strictly occur after the cycle collection.
navigator.serviceWorker.addEventListener('message', evt => {
if (evt.data.type === 'pong') {
registration.installing.removeEventListener(
'statechange', statechangeHandler);
resolve();
}
});
// At the current time, the service worker will exist in our same process
// and notifyObservers is synchronous. However, in the future, service
// workers may end up in a separate process and in that case it will be
// appropriate to use notifyObserversInParentProcess or something like it.
// (notifyObserversInParentProcess is a synchronous IPC call to the parent
// process's main thread. IPDL PContent::CycleCollect is an async message.
// Ordering will be maintained if the postMessage goes via PContent as well,
// but that seems unlikely.)
SpecialPowers.notifyObservers(null, 'child-gc-request', null);
SpecialPowers.notifyObservers(null, 'child-cc-request', null);
SpecialPowers.notifyObservers(null, 'child-gc-request', null);
// (Only send the ping after we set the gc/cc/gc in motion.)
registration.installing.postMessage({ type: 'ping' });
});
}
function terminateWorker() {
return SpecialPowers.pushPrefEnv({
set: [
["dom.serviceWorkers.idle_timeout", 0],
["dom.serviceWorkers.idle_extended_timeout", 0]
]
}).then(_ => {
registration.installing.postMessage({ type: 'RESET_TIMER' });
});
}
function runTest() {
Promise.all([
waitForInstallEvent(),
register()
]).then(_ => ok(registration.installing, 'service worker is installing'))
.then(gcWorker)
.then(_ => ok(registration.installing, 'service worker is still installing'))
.then(terminateWorker)
.catch(e => ok(false, e))
.then(unregister)
.then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -58,6 +58,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/ServoStyleSet.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -203,6 +204,10 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem
// (2) The children's parent back pointer should not be to this synthetic root
// but should instead point to the enclosing parent element.
nsIDocument* doc = aElement->GetUncomposedDoc();
ServoStyleSet* servoStyleSet = nullptr;
if (nsIPresShell* presShell = aElement->OwnerDoc()->GetShell()) {
servoStyleSet = presShell->StyleSet()->GetAsServo();
}
bool allowScripts = AllowScripts();
nsAutoScriptBlocker scriptBlocker;
@ -233,6 +238,10 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem
if (xuldoc)
xuldoc->AddSubtreeToDocument(child);
#endif
if (servoStyleSet) {
servoStyleSet->RestyleSubtree(child);
}
}
}

Просмотреть файл

@ -296,7 +296,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode,
NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
RefPtr<imgLoader> il = imgLoader::GetInstance();
imgLoader* il = imgLoader::NormalLoader();
NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
return il->LoadImage(bgUri, nullptr, nullptr,

Просмотреть файл

@ -1078,31 +1078,35 @@ nsFind::Find(const char16_t* aPatText, nsIDOMRange* aSearchRange,
c = ToLowerCase(c);
}
switch (c) {
if (c == CH_SHY) {
// ignore soft hyphens in the document
case CH_SHY:
continue;
// treat curly and straight quotes as identical
case CH_LEFT_SINGLE_QUOTE:
case CH_RIGHT_SINGLE_QUOTE:
c = CH_APOSTROPHE;
break;
case CH_LEFT_DOUBLE_QUOTE:
case CH_RIGHT_DOUBLE_QUOTE:
c = CH_QUOTE;
break;
continue;
}
switch (patc) {
// treat curly and straight quotes as identical
case CH_LEFT_SINGLE_QUOTE:
case CH_RIGHT_SINGLE_QUOTE:
patc = CH_APOSTROPHE;
break;
case CH_LEFT_DOUBLE_QUOTE:
case CH_RIGHT_DOUBLE_QUOTE:
patc = CH_QUOTE;
break;
if (!mCaseSensitive) {
switch (c) {
// treat curly and straight quotes as identical
case CH_LEFT_SINGLE_QUOTE:
case CH_RIGHT_SINGLE_QUOTE:
c = CH_APOSTROPHE;
break;
case CH_LEFT_DOUBLE_QUOTE:
case CH_RIGHT_DOUBLE_QUOTE:
c = CH_QUOTE;
break;
}
switch (patc) {
// treat curly and straight quotes as identical
case CH_LEFT_SINGLE_QUOTE:
case CH_RIGHT_SINGLE_QUOTE:
patc = CH_APOSTROPHE;
break;
case CH_LEFT_DOUBLE_QUOTE:
case CH_RIGHT_DOUBLE_QUOTE:
patc = CH_QUOTE;
break;
}
}
// a '\n' between CJ characters is ignored

Просмотреть файл

@ -1543,7 +1543,7 @@ nsWindowWatcher::URIfromURL(const char* aURL,
#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \
prefBranch->GetBoolPref(feature, &forceEnable); \
if (forceEnable && !(aDialog && !openedFromContentScript) && \
!(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \
!(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \
chromeFlags |= flag; \
} else { \
chromeFlags |= \
@ -1658,13 +1658,16 @@ nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
nsIWebBrowserChrome::CHROME_STATUSBAR);
NS_CALCULATE_CHROME_FLAG_FOR("menubar",
nsIWebBrowserChrome::CHROME_MENUBAR);
NS_CALCULATE_CHROME_FLAG_FOR("scrollbars",
nsIWebBrowserChrome::CHROME_SCROLLBARS);
NS_CALCULATE_CHROME_FLAG_FOR("resizable",
nsIWebBrowserChrome::CHROME_WINDOW_RESIZE);
NS_CALCULATE_CHROME_FLAG_FOR("minimizable",
nsIWebBrowserChrome::CHROME_WINDOW_MIN);
// default scrollbar to "on," unless explicitly turned off
if (WinHasOption(aFeatures, "scrollbars", 1, &presenceFlag) || !presenceFlag) {
chromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
}
chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag) ?
nsIWebBrowserChrome::CHROME_WINDOW_POPUP : 0;

Просмотреть файл

@ -219,6 +219,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450048
assertNotFound(quotes, "\"doesn't\"");
assertNotFound(quotes, "\u201Cdoesn't\u201D");
// Curly quotes and straight quotes should not match.
rf.caseSensitive = true;
assertFound(quotes, "\"straight\"");
assertNotFound(quotes, "\u201Cstraight\u201D");
assertNotFound(quotes, "\"curly\"");
assertFound(quotes, "\u201Ccurly\u201D");
assertFound(quotes, "\u2018didn't\u2019");
assertNotFound(quotes, "'didn't'");
assertFound(quotes, "'doesn\u2019t'");
assertNotFound(quotes, "'doesn\u2018t'");
assertNotFound(quotes, "'doesn't'");
</script>
</pre>
</body>

Просмотреть файл

@ -40,6 +40,10 @@
#include "mozilla/Snprintf.h"
#include "nsIChannel.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "nsIHttpAuthenticatorCallback.h"
#include "mozilla/Mutex.h"
#include "nsICancelable.h"
//-----------------------------------------------------------------------------
@ -51,6 +55,7 @@ static const char kNegotiateAuthAllowNonFqdn[] = "network.negotiate-auth.allow-n
static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
#define kNegotiateLen (sizeof(kNegotiate)-1)
#define DEFAULT_THREAD_TIMEOUT_MS 30000
//-----------------------------------------------------------------------------
@ -184,7 +189,237 @@ nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
}
NS_IMPL_ISUPPORTS(nsHttpNegotiateAuth, nsIHttpAuthenticator)
namespace {
//
// GetNextTokenCompleteEvent
//
// This event is fired on main thread when async call of
// nsHttpNegotiateAuth::GenerateCredentials is finished. During the Run()
// method the nsIHttpAuthenticatorCallback::OnCredsAvailable is called with
// obtained credentials, flags and NS_OK when successful, otherwise
// NS_ERROR_FAILURE is returned as a result of failed operation.
//
class GetNextTokenCompleteEvent final : public nsIRunnable,
public nsICancelable
{
virtual ~GetNextTokenCompleteEvent()
{
if (mCreds) {
free(mCreds);
}
};
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit GetNextTokenCompleteEvent(nsIHttpAuthenticatorCallback* aCallback)
: mCallback(aCallback)
, mCreds(nullptr)
, mCancelled(false)
{
}
NS_IMETHODIMP DispatchSuccess(char *aCreds,
uint32_t aFlags,
nsISupports *aSessionState,
nsISupports *aContinuationState)
{
// Called from worker thread
MOZ_ASSERT(!NS_IsMainThread());
mCreds = aCreds;
mFlags = aFlags;
mResult = NS_OK;
mSessionState = aSessionState;
mContinuationState = aContinuationState;
return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP DispatchError()
{
// Called from worker thread
MOZ_ASSERT(!NS_IsMainThread());
mResult = NS_ERROR_FAILURE;
return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP Run() override
{
// Runs on main thread
MOZ_ASSERT(NS_IsMainThread());
if (!mCancelled) {
nsCOMPtr<nsIHttpAuthenticatorCallback> callback;
callback.swap(mCallback);
callback->OnCredsGenerated(mCreds, mFlags, mResult, mSessionState, mContinuationState);
}
return NS_OK;
}
NS_IMETHODIMP Cancel(nsresult aReason) override
{
// Supposed to be called from main thread
MOZ_ASSERT(NS_IsMainThread());
mCancelled = true;
return NS_OK;
}
private:
nsCOMPtr<nsIHttpAuthenticatorCallback> mCallback;
char *mCreds; // This class owns it, freed in destructor
uint32_t mFlags;
nsresult mResult;
bool mCancelled;
nsCOMPtr<nsISupports> mSessionState;
nsCOMPtr<nsISupports> mContinuationState;
};
NS_IMPL_ISUPPORTS(GetNextTokenCompleteEvent, nsIRunnable, nsICancelable)
//
// GetNextTokenRunnable
//
// This runnable is created by GenerateCredentialsAsync and it runs
// in nsHttpNegotiateAuth::mNegotiateThread and calling GenerateCredentials.
//
class GetNextTokenRunnable final : public mozilla::Runnable
{
virtual ~GetNextTokenRunnable() {}
public:
GetNextTokenRunnable(nsIHttpAuthenticableChannel *authChannel,
const char *challenge,
bool isProxyAuth,
const char16_t *domain,
const char16_t *username,
const char16_t *password,
nsISupports *sessionState,
nsISupports *continuationState,
GetNextTokenCompleteEvent *aCompleteEvent
)
: mAuthChannel(authChannel)
, mChallenge(challenge)
, mIsProxyAuth(isProxyAuth)
, mDomain(domain)
, mUsername(username)
, mPassword(password)
, mSessionState(sessionState)
, mContinuationState(continuationState)
, mCompleteEvent(aCompleteEvent)
{
}
NS_IMETHODIMP Run() override
{
// Runs on worker thread
MOZ_ASSERT(!NS_IsMainThread());
char *creds;
uint32_t flags;
nsresult rv = ObtainCredentialsAndFlags(&creds, &flags);
if (NS_FAILED(rv)) {
return mCompleteEvent->DispatchError();
}
return mCompleteEvent->DispatchSuccess(creds, flags, mSessionState, mContinuationState);
}
NS_IMETHODIMP ObtainCredentialsAndFlags(char **aCreds, uint32_t *aFlags)
{
// Use negotiate service to call GenerateCredentials outside of main thread
nsAutoCString contractId;
contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
contractId.Append("negotiate");
nsresult rv;
nsCOMPtr<nsIHttpAuthenticator> authenticator = do_GetService(contractId.get(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsISupports *sessionState = mSessionState;
nsISupports *continuationState = mContinuationState;
// The continuationState is for the sake of completeness propagated
// to the caller (despite it is not changed in any GenerateCredentials
// implementation).
//
// The only implementation that use sessionState is the
// nsHttpDigestAuth::GenerateCredentials. Since there's no reason
// to implement nsHttpDigestAuth::GenerateCredentialsAsync
// because digest auth does not block the main thread, we won't
// propagate changes to sessionState to the caller because of
// the change is too complicated on the caller side.
rv = authenticator->GenerateCredentials(mAuthChannel,
mChallenge.get(),
mIsProxyAuth,
mDomain.get(),
mUsername.get(),
mPassword.get(),
&sessionState,
&continuationState,
aFlags,
aCreds);
mSessionState = sessionState;
mContinuationState = continuationState;
return rv;
}
private:
nsCOMPtr<nsIHttpAuthenticableChannel> mAuthChannel;
nsCString mChallenge;
bool mIsProxyAuth;
nsString mDomain;
nsString mUsername;
nsString mPassword;
nsCOMPtr<nsISupports> mSessionState;
nsCOMPtr<nsISupports> mContinuationState;
RefPtr<GetNextTokenCompleteEvent> mCompleteEvent;
};
} // anonymous namespace
NS_IMETHODIMP
nsHttpNegotiateAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel,
nsIHttpAuthenticatorCallback* aCallback,
const char *challenge,
bool isProxyAuth,
const char16_t *domain,
const char16_t *username,
const char16_t *password,
nsISupports *sessionState,
nsISupports *continuationState,
nsICancelable **aCancelable)
{
NS_ENSURE_ARG(aCallback);
NS_ENSURE_ARG_POINTER(aCancelable);
RefPtr<GetNextTokenCompleteEvent> cancelEvent =
new GetNextTokenCompleteEvent(aCallback);
nsCOMPtr<nsIRunnable> getNextTokenRunnable =
new GetNextTokenRunnable(authChannel,
challenge,
isProxyAuth,
domain,
username,
password,
sessionState,
continuationState,
cancelEvent);
cancelEvent.forget(aCancelable);
nsresult rv;
if (!mNegotiateThread) {
mNegotiateThread =
new mozilla::LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
NS_LITERAL_CSTRING("NegotiateAuth"));
NS_ENSURE_TRUE(mNegotiateThread, NS_ERROR_OUT_OF_MEMORY);
}
rv = mNegotiateThread->Dispatch(getNextTokenRunnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
//
// GenerateCredentials
//

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsIURI.h"
#include "nsSubstring.h"
#include "mozilla/Attributes.h"
#include "mozilla/LazyIdleThread.h"
// The nsHttpNegotiateAuth class provides responses for the GSS-API Negotiate method
// as specified by Microsoft in draft-brezak-spnego-http-04.txt
@ -17,7 +18,7 @@
class nsHttpNegotiateAuth final : public nsIHttpAuthenticator
{
public:
NS_DECL_ISUPPORTS
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIHTTPAUTHENTICATOR
private:
@ -37,5 +38,7 @@ private:
int32_t port,
const char *baseStart,
const char *baseEnd);
// Thread for GenerateCredentialsAsync
RefPtr<mozilla::LazyIdleThread> mNegotiateThread;
};
#endif /* nsHttpNegotiateAuth_h__ */

Просмотреть файл

@ -1018,9 +1018,13 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
#endif
ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
SkTypeface* typeface = skiaFont->GetSkTypeface();
if (!typeface) {
return;
}
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
paint.mPaint.setTypeface(skiaFont->GetSkTypeface());
paint.mPaint.setTypeface(typeface);
paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

Просмотреть файл

@ -115,31 +115,65 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget
#ifdef USE_SKIA
bool
ScaledFontDWrite::DefaultToArialFont(IDWriteFontCollection* aSystemFonts)
{
// If we can't find the same font face as we're given, fallback to arial
static const WCHAR fontFamilyName[] = L"Arial";
UINT32 fontIndex;
BOOL exists;
HRESULT hr = aSystemFonts->FindFamilyName(fontFamilyName, &fontIndex, &exists);
if (FAILED(hr)) {
gfxCriticalNote << "Failed to get backup arial font font from system fonts. Code: " << hexa(hr);
return false;
}
hr = aSystemFonts->GetFontFamily(fontIndex, getter_AddRefs(mFontFamily));
if (FAILED(hr)) {
gfxCriticalNote << "Failed to get font family for arial. Code: " << hexa(hr);
return false;
}
hr = mFontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
getter_AddRefs(mFont));
if (FAILED(hr)) {
gfxCriticalNote << "Failed to get a matching font for arial. Code: " << hexa(hr);
return false;
}
return true;
}
// This can happen if we have mixed backends which create DWrite
// fonts in a mixed environment. e.g. a cairo content backend
// but Skia canvas backend.
void
bool
ScaledFontDWrite::GetFontDataFromSystemFonts(IDWriteFactory* aFactory)
{
MOZ_ASSERT(mFontFace);
RefPtr<IDWriteFontCollection> systemFonts;
HRESULT hr = aFactory->GetSystemFontCollection(getter_AddRefs(systemFonts));
if (FAILED(hr)) {
gfxWarning() << "Failed to get system font collection from file data. Code: " << hexa(hr);
return;
gfxCriticalNote << "Failed to get system font collection from file data. Code: " << hexa(hr);
return false;
}
hr = systemFonts->GetFontFromFontFace(mFontFace, getter_AddRefs(mFont));
if (FAILED(hr)) {
gfxWarning() << "Failed to get system font from font face. Code: " << hexa(hr);
return;
gfxCriticalNote << "Failed to get system font from font face. Code: " << hexa(hr);
return DefaultToArialFont(systemFonts);
}
hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily));
if (FAILED(hr)) {
gfxWarning() << "Failed to get font family from font face. Code: " << hexa(hr);
return;
gfxCriticalNote << "Failed to get font family from font face. Code: " << hexa(hr);
return DefaultToArialFont(systemFonts);
}
return true;
}
SkTypeface*
@ -147,8 +181,14 @@ ScaledFontDWrite::GetSkTypeface()
{
if (!mTypeface) {
IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
if (!factory) {
return nullptr;
}
if (!mFont || !mFontFamily) {
GetFontDataFromSystemFonts(factory);
if (!GetFontDataFromSystemFonts(factory)) {
return nullptr;
}
}
mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);

Просмотреть файл

@ -46,7 +46,8 @@ public:
#ifdef USE_SKIA
virtual SkTypeface* GetSkTypeface();
void GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
bool GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
bool DefaultToArialFont(IDWriteFontCollection* aSystemFonts);
#endif
// The font and font family are only used with Skia

Просмотреть файл

@ -20,7 +20,7 @@ namespace gfx {
_(D3D11_COMPOSITING, Feature, "Direct3D11 Compositing") \
_(D3D9_COMPOSITING, Feature, "Direct3D9 Compositing") \
_(DIRECT2D, Feature, "Direct2D") \
_(D3D11_ANGLE, Feature, "Direct3D11 ANGLE") \
_(D3D11_HW_ANGLE, Feature, "Direct3D11 hardware ANGLE") \
/* Add new entries above this comment */
enum class Feature : uint32_t {

Просмотреть файл

@ -170,7 +170,7 @@ GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl)
{
EGLDisplay ret = 0;
FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_ANGLE);
FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
if (!gfxPrefs::WebGLANGLETryD3D11())
d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref");
@ -178,7 +178,7 @@ GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl)
if (gfxPrefs::WebGLANGLEForceD3D11())
d3d11ANGLE.UserForceEnable("User force-enabled D3D11 ANGLE on disabled hardware");
if (gfxConfig::IsForcedOnByUser(Feature::D3D11_ANGLE))
if (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE))
return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
if (d3d11ANGLE.IsEnabled()) {

Просмотреть файл

@ -219,10 +219,10 @@ LayerManager::LayerUserDataDestroy(void* data)
delete static_cast<LayerUserData*>(data);
}
nsAutoPtr<LayerUserData>
UniquePtr<LayerUserData>
LayerManager::RemoveUserData(void* aKey)
{
nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
return d;
}
@ -2148,10 +2148,10 @@ Layer::IsBackfaceHidden()
return false;
}
nsAutoPtr<LayerUserData>
UniquePtr<LayerUserData>
Layer::RemoveUserData(void* aKey)
{
nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
return d;
}

Просмотреть файл

@ -505,7 +505,7 @@ public:
/**
* This can be used anytime. Ownership passes to the caller!
*/
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey);
UniquePtr<LayerUserData> RemoveUserData(void* aKey);
/**
* This getter can be used anytime.
@ -1462,7 +1462,7 @@ public:
/**
* This can be used anytime. Ownership passes to the caller!
*/
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey);
UniquePtr<LayerUserData> RemoveUserData(void* aKey);
/**
* This getter can be used anytime.
*/

Просмотреть файл

@ -47,3 +47,5 @@ skip-if = (toolkit == 'windows') || (toolkit == 'cocoa')
[test_group_wheelevents.html]
skip-if = (toolkit == 'android') # wheel events not supported on mobile
[test_group_mouseevents.html]
[test_touch_listeners_impacting_wheel.html]
skip-if = (toolkit == 'android') || (toolkit == 'cocoa') # wheel events not supported on mobile, and synthesized wheel smooth-scrolling not supported on OS X

Просмотреть файл

@ -0,0 +1,159 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1203140
-->
<head>
<title>Test for Bug 1203140</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1203140">Mozilla Bug 1203140</a>
<p id="display"></p>
<div id="content" style="overflow-y:scroll; height: 400px">
<p>The box below has a touch listener and a passive wheel listener. With touch events disabled, APZ shouldn't wait for any listeners.</p>
<div id="box" style="width: 200px; height: 200px; background-color: blue"></div>
<div style="height: 1000px; width: 10px">Div to make 'content' scrollable</div>
</div>
<pre id="test">
<script type="application/javascript">
const kResponseTimeoutMs = 2 * 60 * 1000; // 2 minutes
function parentProcessSnapshot() {
addMessageListener('snapshot', function(rect) {
Components.utils.import('resource://gre/modules/Services.jsm');
var topWin = Services.wm.getMostRecentWindow('navigator:browser');
// reposition the rect relative to the top-level browser window
rect = JSON.parse(rect);
rect.x -= topWin.mozInnerScreenX;
rect.y -= topWin.mozInnerScreenY;
// take the snapshot
var canvas = topWin.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.width = rect.w;
canvas.height = rect.h;
var ctx = canvas.getContext("2d");
ctx.drawWindow(topWin, rect.x, rect.y, rect.w, rect.h, 'rgb(255,255,255)', ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_CARET);
return canvas.toDataURL();
});
}
function takeSnapshots(e) {
// Grab some snapshots, and make sure some of them are different (i.e. check
// the page is scrolling in the compositor, concurrently with this wheel
// listener running).
// Note that we want this function to take less time than the content response
// timeout, otherwise the scrolling will start even if we haven't returned,
// and that would invalidate purpose of the test.
var start = Date.now();
var lastSnapshot = null;
var success = false;
var chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
SimpleTest.registerCleanupFunction(function() { chromeHelper.destroy() });
// Get the position of the 'content' div relative to the screen
var contentDiv = document.getElementById('content');
var rect = coordinatesRelativeToWindow(0, 0, contentDiv);
rect.w = contentDiv.getBoundingClientRect().width * window.devicePixelRatio;
rect.h = contentDiv.getBoundingClientRect().height * window.devicePixelRatio;
for (var i = 0; i < 10; i++) {
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(16);
var snapshot = chromeHelper.sendSyncMessage('snapshot', JSON.stringify(rect)).toString();
//dump("Took snapshot " + snapshot + "\n"); // this might help with debugging
if (lastSnapshot && lastSnapshot != snapshot) {
ok(true, "Found some different pixels in snapshot " + i + " compared to previous");
success = true;
}
lastSnapshot = snapshot;
}
ok(success, "Found some snapshots that were different");
ok((Date.now() - start) < kResponseTimeoutMs, "Snapshotting ran quickly enough");
// Until now, no scroll events will have been dispatched to content. That's
// because scroll events are dispatched on the main thread, which we've been
// hogging with the code above. At this point we restore the normal refresh
// behaviour and let the main thread go back to C++ code, so the scroll events
// fire and we unwind from the main test continuation.
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
}
function* runTest() {
var box = document.getElementById('box');
box.addEventListener('touchstart', function(e) {
ok(false, "This should never be run");
}, false);
box.addEventListener('wheel', takeSnapshots, { capture: false, passive: true });
// Let the event regions propagate to the APZ
yield waitForAllPaints(function() {
flushApzRepaints(driveTest);
});
// Take over control of the refresh driver and compositor
var utils = SpecialPowers.DOMWindowUtils;
utils.advanceTimeAndRefresh(0);
// Trigger an APZ scroll using a wheel event. If APZ is waiting for a
// content response, it will wait for takeSnapshots to finish running before
// it starts scrolling, which will cause the checks in takeSnapshots to fail.
yield synthesizeNativeMouseMoveAndWaitForMoveEvent(box, 10, 10, driveTest);
yield synthesizeNativeWheelAndWaitForScrollEvent(box, 10, 10, 0, -50, driveTest);
}
var gTestContinuation = null;
function driveTest() {
if (!gTestContinuation) {
gTestContinuation = runTest();
}
var ret = gTestContinuation.next();
if (ret.done) {
SimpleTest.finish();
}
}
function startTest() {
// This test requires APZ - if it's not enabled, skip it.
var apzEnabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
if (!apzEnabled) {
ok(true, "APZ not enabled, skipping test");
SimpleTest.finish();
return;
}
waitForAllPaints(function() {
flushApzRepaints(driveTest);
})
}
SimpleTest.waitForExplicitFinish();
// Disable touch events, so that APZ knows not to wait for touch listeners.
// Also explicitly set the content response timeout, so we know how long it
// is (see comment in takeSnapshots).
// Finally, enable smooth scrolling, so that the wheel-scroll we do as part
// of the test triggers an APZ animation rather than doing an instant scroll.
// Note that this pref doesn't work for the synthesized wheel events on OS X,
// those are hard-coded to be instant scrolls.
SpecialPowers.pushPrefEnv({"set": [["dom.w3c_touch_events.enabled", 0],
["apz.content_response_timeout", kResponseTimeoutMs],
["general.smoothscroll", true]]},
function() {
SimpleTest.waitForFocus(startTest, window);
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -506,8 +506,9 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
BufferMode bufferMode = BufferMode::BUFFERED;
if (mTarget) {
// If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Use a dummy
// placeholder so that CreateRenderTarget() works.
mDrawTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
// placeholder so that CreateRenderTarget() works. This is only used to create a new buffered
// draw target that we composite into, then copy the results the destination.
mDrawTarget = mTarget;
} else {
// StartRemoteDrawingInRegion can mutate mInvalidRegion.
mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion, &bufferMode);

Просмотреть файл

@ -59,7 +59,7 @@
// The resizer background area in a status bar
// for the resizer widget in the corner of a window.
#define NS_THEME_RESIZER_PANEL 25
#define NS_THEME_RESIZERPANEL 25
// The resizer itself.
#define NS_THEME_RESIZER 26
@ -174,7 +174,7 @@
#define NS_THEME_TEXTFIELD 95
// The caret of a text area
#define NS_THEME_TEXTFIELD_CARET 96
#define NS_THEME_CARET 96
// A multiline text field
#define NS_THEME_TEXTFIELD_MULTILINE 97

Просмотреть файл

@ -150,9 +150,9 @@ TEST(Layers, UserData) {
layer.SetUserData(key3, data3);
// Also checking that the user data is returned but not free'd
UniquePtr<LayerUserData> d1(layer.RemoveUserData(key1).forget());
UniquePtr<LayerUserData> d2(layer.RemoveUserData(key2).forget());
UniquePtr<LayerUserData> d3(layer.RemoveUserData(key3).forget());
UniquePtr<LayerUserData> d1(layer.RemoveUserData(key1));
UniquePtr<LayerUserData> d2(layer.RemoveUserData(key2));
UniquePtr<LayerUserData> d3(layer.RemoveUserData(key3));
ASSERT_EQ(data1, d1.get());
ASSERT_EQ(data2, d2.get());
ASSERT_EQ(data3, d3.get());

Просмотреть файл

@ -2067,7 +2067,6 @@ gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
* and remember the values. Changing these preferences during the run will
* not have any effect until we restart.
*/
bool gANGLESupportsD3D11 = false;
static mozilla::Atomic<bool> sLayersSupportsHardwareVideoDecoding(false);
static bool sLayersHardwareVideoDecodingFailed = false;
static bool sBufferRotationCheckPref = true;
@ -2096,15 +2095,6 @@ gfxPlatform::InitAcceleration()
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
nsCString discardFailureId;
int32_t status;
#ifdef XP_WIN
if (!gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly() && gfxInfo) {
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, discardFailureId, &status))) {
if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
gANGLESupportsD3D11 = true;
}
}
}
#endif
if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
#ifdef XP_WIN

Просмотреть файл

@ -97,11 +97,11 @@ public:
// Public textrun API for general use
bool IsClusterStart(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].IsClusterStart();
}
bool IsLigatureGroupStart(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].IsLigatureGroupStart();
}
bool CanBreakLineBefore(uint32_t aPos) const {
@ -114,24 +114,24 @@ public:
// Returns a gfxShapedText::CompressedGlyph::FLAG_BREAK_TYPE_* value
// as defined in gfxFont.h (may be NONE, NORMAL or HYPHEN).
uint8_t CanBreakBefore(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].CanBreakBefore();
}
bool CharIsSpace(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].CharIsSpace();
}
bool CharIsTab(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].CharIsTab();
}
bool CharIsNewline(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].CharIsNewline();
}
bool CharMayHaveEmphasisMark(uint32_t aPos) const {
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
MOZ_ASSERT(aPos < GetLength());
return mCharacterGlyphs[aPos].CharMayHaveEmphasisMark();
}
@ -394,7 +394,7 @@ public:
* SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
*
* @param aCanWordWrap true if we can break between any two grapheme
* clusters. This is set by word-wrap: break-word
* clusters. This is set by overflow-wrap|word-wrap: break-word
*
* @param aBreakPriority in/out the priority of the break opportunity
* saved in the line. If we are prioritizing break opportunities, we will
@ -513,7 +513,7 @@ public:
void SanitizeGlyphRuns();
CompressedGlyph* GetCharacterGlyphs() final {
NS_ASSERTION(mCharacterGlyphs, "failed to initialize mCharacterGlyphs");
MOZ_ASSERT(mCharacterGlyphs, "failed to initialize mCharacterGlyphs");
return mCharacterGlyphs;
}

Просмотреть файл

@ -24,7 +24,7 @@ typedef double gfxFloat;
*
* eNoBreak The line has no break opportunities
* eWordWrapBreak The line has a break opportunity only within a word. With
* word-wrap: break-word we will break at this point only if
* overflow-wrap|word-wrap: break-word we will break at this point only if
* there are no other break opportunities in the line.
* eNormalBreak The line has a break opportunity determined by the standard
* line-breaking algorithm.

Просмотреть файл

@ -373,6 +373,14 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
CoUninitialize();
}
static void
UpdateANGLEConfig()
{
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
gfxConfig::Disable(Feature::D3D11_HW_ANGLE, FeatureStatus::Disabled, "D3D11 compositing is disabled");
}
}
void
gfxWindowsPlatform::InitAcceleration()
{
@ -389,6 +397,7 @@ gfxWindowsPlatform::InitAcceleration()
InitializeConfig();
InitializeDevices();
UpdateANGLEConfig();
UpdateRenderMode();
}
@ -455,11 +464,14 @@ gfxWindowsPlatform::HandleDeviceReset()
mCompositorD3D11TextureSharingWorks = false;
mDeviceResetReason = DeviceResetReason::OK;
imgLoader::Singleton()->ClearCache(true);
imgLoader::Singleton()->ClearCache(false);
imgLoader::NormalLoader()->ClearCache(true);
imgLoader::NormalLoader()->ClearCache(false);
imgLoader::PrivateBrowsingLoader()->ClearCache(true);
imgLoader::PrivateBrowsingLoader()->ClearCache(false);
gfxAlphaBoxBlur::ShutdownBlurCache();
InitializeDevices();
UpdateANGLEConfig();
BumpDeviceCounter();
return true;
}
@ -1920,6 +1932,25 @@ IsWARPStable()
return true;
}
static void
InitializeANGLEConfig()
{
FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
d3d11ANGLE.DisableByDefault(FeatureStatus::Unavailable, "D3D11 compositing is disabled");
return;
}
d3d11ANGLE.EnableByDefault();
nsCString message;
if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, &message)) {
d3d11ANGLE.Disable(FeatureStatus::Blacklisted, message.get());
}
}
void
gfxWindowsPlatform::InitializeConfig()
{
@ -1930,6 +1961,7 @@ gfxWindowsPlatform::InitializeConfig()
InitializeD3D9Config();
InitializeD3D11Config();
InitializeANGLEConfig();
InitializeD2DConfig();
}
@ -2033,6 +2065,9 @@ gfxWindowsPlatform::UpdateDeviceInitData()
FeatureStatus::Disabled,
"Disabled by parent process");
InitializeANGLEConfig();
return true;
}
@ -2097,13 +2132,13 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
if (!mCompositorD3D11TextureSharingWorks) {
gfxConfig::SetFailed(Feature::D3D11_ANGLE,
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
FeatureStatus::Broken,
"Texture sharing doesn't work");
}
if (DoesRenderTargetViewNeedsRecreating(mD3D11Device)) {
gfxConfig::SetFailed(Feature::D3D11_ANGLE,
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
FeatureStatus::Broken,
"RenderTargetViews need recreating");
}
@ -2352,12 +2387,6 @@ gfxWindowsPlatform::InitializeDevices()
InitializeD3D11();
InitializeD2D();
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
gfxConfig::DisableByDefault(Feature::D3D11_ANGLE, FeatureStatus::Disabled, "D3D11 compositing is disabled");
} else {
gfxConfig::EnableByDefault(Feature::D3D11_ANGLE);
}
if (!gfxConfig::IsEnabled(Feature::DIRECT2D)) {
if (XRE_IsContentProcess() && GetParentDevicePrefs().useD2D1()) {
RecordContentDeviceFailure(TelemetryDeviceCode::D2D1);

Просмотреть файл

@ -394,7 +394,7 @@ void NotifyScreenConfigurationChange(const hal::ScreenConfiguration& aScreenConf
* Lock the screen orientation to the specific orientation.
* @return Whether the lock has been accepted.
*/
bool LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation);
MOZ_MUST_USE bool LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation);
/**
* Unlock the screen orientation.
@ -438,7 +438,7 @@ void NotifySwitchStateFromInputDevice(hal::SwitchDevice aDevice,
*
* Currently, there can only be 0 or 1 alarm observers.
*/
bool RegisterTheOneAlarmObserver(hal::AlarmObserver* aObserver);
MOZ_MUST_USE bool RegisterTheOneAlarmObserver(hal::AlarmObserver* aObserver);
/**
* Unregister the alarm observer. Doing so will implicitly cancel any
@ -465,7 +465,7 @@ void NotifyAlarmFired();
* This API is currently only allowed to be used from non-sandboxed
* contexts.
*/
bool SetAlarm(int32_t aSeconds, int32_t aNanoseconds);
MOZ_MUST_USE bool SetAlarm(int32_t aSeconds, int32_t aNanoseconds);
/**
* Set the priority of the given process.
@ -585,7 +585,7 @@ hal::FMRadioSettings GetFMBandSettings(hal::FMRadioCountry aCountry);
/**
* Enable RDS data reception
*/
bool EnableRDS(uint32_t aMask);
MOZ_MUST_USE bool EnableRDS(uint32_t aMask);
/**
* Disable RDS data reception

Просмотреть файл

@ -67,7 +67,7 @@ void DisableSwitchNotifications(hal::SwitchDevice aDevice);
/**
* Enable alarm notifications from the backend.
*/
bool EnableAlarm();
MOZ_MUST_USE bool EnableAlarm();
/**
* Disable alarm notifications from the backend.

Просмотреть файл

@ -29,6 +29,8 @@
// objects that just require generic constructors
using namespace mozilla::image;
// XXX We would like to get rid of the imgLoader factory constructor. See the
// comment documenting the imgLoader constructor.
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(imgLoader, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgTools)
@ -85,9 +87,14 @@ static const mozilla::Module::CategoryEntry kImageCategories[] = {
static bool sInitialized = false;
nsresult
mozilla::image::InitModule()
mozilla::image::EnsureModuleInitialized()
{
MOZ_ASSERT(NS_IsMainThread());
if (sInitialized) {
return NS_OK;
}
// Make sure the preferences are initialized
gfxPrefs::GetSingleton();
@ -118,7 +125,7 @@ static const mozilla::Module kImageModule = {
kImageContracts,
kImageCategories,
nullptr,
mozilla::image::InitModule,
mozilla::image::EnsureModuleInitialized,
// We need to be careful about shutdown ordering to avoid intermittent crashes
// when hashtable enumeration decides to destroy modules in an unfortunate
// order. So our shutdown is invoked explicitly during layout module shutdown.

Просмотреть файл

@ -11,7 +11,7 @@
namespace mozilla {
namespace image {
nsresult InitModule();
nsresult EnsureModuleInitialized();
void ShutdownModule();
} /* namespace image */

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/ChaosMode.h"
#include "ImageLogging.h"
#include "nsImageModule.h"
#include "nsPrintfCString.h"
#include "imgLoader.h"
#include "imgRequestProxy.h"
@ -1133,26 +1134,40 @@ imgMemoryReporter* imgLoader::sMemReporter;
NS_IMPL_ISUPPORTS(imgLoader, imgILoader, nsIContentSniffer, imgICache,
nsISupportsWeakReference, nsIObserver)
static imgLoader* gSingleton = nullptr;
static imgLoader* gPBSingleton = nullptr;
static imgLoader* gNormalLoader = nullptr;
static imgLoader* gPrivateBrowsingLoader = nullptr;
imgLoader*
imgLoader::Singleton()
/* static */ already_AddRefed<imgLoader>
imgLoader::CreateImageLoader()
{
if (!gSingleton) {
gSingleton = imgLoader::Create().take();
}
return gSingleton;
// In some cases, such as xpctests, XPCOM modules are not automatically
// initialized. We need to make sure that our module is initialized before
// we hand out imgLoader instances and code starts using them.
mozilla::image::EnsureModuleInitialized();
RefPtr<imgLoader> loader = new imgLoader();
loader->Init();
return loader.forget();
}
imgLoader*
imgLoader::PBSingleton()
imgLoader::NormalLoader()
{
if (!gPBSingleton) {
gPBSingleton = imgLoader::Create().take();
gPBSingleton->RespectPrivacyNotifications();
if (!gNormalLoader) {
gNormalLoader = CreateImageLoader().take();
}
return gPBSingleton;
return gNormalLoader;
}
imgLoader*
imgLoader::PrivateBrowsingLoader()
{
if (!gPrivateBrowsingLoader) {
gPrivateBrowsingLoader = CreateImageLoader().take();
gPrivateBrowsingLoader->RespectPrivacyNotifications();
}
return gPrivateBrowsingLoader;
}
imgLoader::imgLoader()
@ -1162,21 +1177,6 @@ imgLoader::imgLoader()
sMemReporter->RegisterLoader(this);
}
already_AddRefed<imgLoader>
imgLoader::GetInstance()
{
static RefPtr<imgLoader> singleton;
if (!singleton) {
singleton = imgLoader::Create();
if (!singleton) {
return nullptr;
}
ClearOnShutdown(&singleton);
}
RefPtr<imgLoader> loader = singleton.get();
return loader.forget();
}
imgLoader::~imgLoader()
{
ClearChromeImageCache();
@ -1400,8 +1400,10 @@ imgLoader::ClearCacheForControlledDocument(nsIDocument* aDoc)
void
imgLoader::Shutdown()
{
NS_IF_RELEASE(gSingleton);
NS_IF_RELEASE(gPBSingleton);
NS_IF_RELEASE(gNormalLoader);
gNormalLoader = nullptr;
NS_IF_RELEASE(gPrivateBrowsingLoader);
gPrivateBrowsingLoader = nullptr;
}
nsresult

Просмотреть файл

@ -246,30 +246,50 @@ public:
NS_DECL_IMGICACHE
NS_DECL_NSIOBSERVER
static imgLoader* Singleton();
static imgLoader* PBSingleton();
/**
* Get the normal image loader instance that is used by gecko code, creating
* it if necessary.
*/
static imgLoader* NormalLoader();
/**
* Get the Private Browsing image loader instance that is used by gecko code,
* creating it if necessary.
*
* The nsIChannel objects that this instance creates are created with the
* nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING flag.
*/
static imgLoader* PrivateBrowsingLoader();
/**
* Gecko code should use NormalLoader() or PrivateBrowsingLoader() to get the
* appropriate image loader.
*
* This constructor is public because the XPCOM module code that creates
* instances of "@mozilla.org/image/loader;1" / "@mozilla.org/image/cache;1"
* for nsIComponentManager.createInstance()/nsIServiceManager.getService()
* calls (now only made by add-ons) needs access to it.
*
* XXX We would like to get rid of the nsIServiceManager.getService (and
* nsIComponentManager.createInstance) method of creating imgLoader objects,
* but there are add-ons that are still using it. These add-ons don't
* actually do anything useful with the loaders that they create since nobody
* who creates an imgLoader using this method actually QIs to imgILoader and
* loads images. They all just QI to imgICache and either call clearCache()
* or findEntryProperties(). Since they're doing this on an imgLoader that
* has never loaded images, these calls are useless. It seems likely that
* the code that is doing this is just legacy code left over from a time when
* there was only one imgLoader instance for the entire process. (Nowadays
* the correct method to get an imgILoader/imgICache is to call
* imgITools::getImgCacheForDocument/imgITools::getImgLoaderForDocument.)
* All the same, even though what these add-ons are doing is a no-op,
* removing the nsIServiceManager.getService method of creating/getting an
* imgLoader objects would cause an exception in these add-ons that could
* break things.
*/
imgLoader();
nsresult Init();
static already_AddRefed<imgLoader>
Create()
{
// Unfortunately, we rely on XPCOM module init happening
// before imgLoader creation. For now, it's easier
// to just call CallCreateInstance() which will init
// the image module instead of calling new imgLoader
// directly.
nsCOMPtr<imgILoader> loader = do_CreateInstance("@mozilla.org/image/loader;1");
// There's only one imgLoader implementation so we
// can safely cast to it.
return loader.forget().downcast<imgLoader>();
}
static already_AddRefed<imgLoader>
GetInstance();
nsresult LoadImage(nsIURI* aURI,
nsIURI* aInitialDocumentURI,
nsIURI* aReferrerURI,
@ -373,6 +393,8 @@ public:
private: // methods
static already_AddRefed<imgLoader> CreateImageLoader();
bool ValidateEntry(imgCacheEntry* aEntry, nsIURI* aKey,
nsIURI* aInitialDocumentURI, nsIURI* aReferrerURI,
ReferrerPolicy aReferrerPolicy,

Просмотреть файл

@ -26,6 +26,9 @@ extern "C" char* PrintJSStack();
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "nsDebug.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsISupportsImpl.h"
#include "nsXULAppAPI.h"
@ -158,7 +161,14 @@ ProcessLink::EchoMessage(Message *msg)
void
ProcessLink::SendMessage(Message *msg)
{
MOZ_RELEASE_ASSERT(msg->size() < IPC::Channel::kMaximumMessageSize);
if (msg->size() > IPC::Channel::kMaximumMessageSize) {
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCMessageName"), nsDependentCString(msg->name()));
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCMessageSize"), nsPrintfCString("%d", msg->size()));
#endif
MOZ_CRASH("IPC message size is too large");
}
mChan->AssertWorkerThread();
mChan->mMonitor->AssertCurrentThreadOwns();

Просмотреть файл

@ -1851,11 +1851,12 @@ class ValueOperations
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
gc::Cell* toGCThing() const { return value().toGCThing(); }
JS::TraceKind traceKind() const { return value().traceKind(); }
uint64_t asRawBits() const { return value().asRawBits(); }
JSValueType extractNonDoubleType() const { return value().extractNonDoubleType(); }
void* toPrivate() const { return value().toPrivate(); }
uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
uint64_t asRawBits() const { return value().asRawBits(); }
JSValueType extractNonDoubleType() const { return value().extractNonDoubleType(); }
JSWhyMagic whyMagic() const { return value().whyMagic(); }
uint32_t magicUint32() const { return value().magicUint32(); }
};
@ -1885,6 +1886,8 @@ class MutableValueOperations : public ValueOperations<Outer>
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
void setPrivate(void* ptr) { this->value().setPrivate(ptr); }
void setPrivateUint32(uint32_t ui) { this->value().setPrivateUint32(ui); }
void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
};

Просмотреть файл

@ -248,7 +248,6 @@ ifneq (,$(TAR))
source-package:
SRCDIR=$(srcdir) \
DIST=$(DIST) \
MAKE=$(MAKE) \
MKDIR=$(MKDIR) \
TAR=$(TAR) \
MOZJS_MAJOR_VERSION=$(MOZJS_MAJOR_VERSION) \

Просмотреть файл

@ -78,6 +78,8 @@ class AstDecodeContext
AstIndexVector funcSigs_;
AstDecodeExprIter *iter_;
const ValTypeVector* locals_;
AstNameVector blockLabels_;
uint32_t currentLabelIndex_;
public:
AstDecodeContext(JSContext* cx, LifoAlloc& lifo, Decoder& d, AstModule& module, bool generateNames)
@ -91,23 +93,31 @@ class AstDecodeContext
module_(module),
funcSigs_(lifo),
iter_(nullptr),
locals_(nullptr)
locals_(nullptr),
blockLabels_(lifo)
{}
AstModule& module() { return module_; }
AstIndexVector& funcSigs() { return funcSigs_; }
AstDecodeExprIter& iter() { return *iter_; }
const ValTypeVector& locals() { return *locals_; }
AstNameVector& blockLabels() { return blockLabels_; }
void startFunction(AstDecodeExprIter *iter, const ValTypeVector* locals)
{
iter_ = iter;
locals_ = locals;
currentLabelIndex_ = 0;
}
void endFunction()
{
iter_ = nullptr;
locals_ = nullptr;
MOZ_ASSERT(blockLabels_.length() == 0);
}
uint32_t nextLabelIndex()
{
return currentLabelIndex_++;
}
};
@ -232,11 +242,12 @@ AstDecodeCall(AstDecodeContext& c)
if (!AstDecodeCallReturn(c, *sig))
return false;
uint32_t argsLength = args.length();
AstCall* call = new(c.lifo) AstCall(Expr::Call, funcRef, Move(args));
if (!call)
return false;
c.iter().setResult(AstDecodeStackItem(call, args.length()));
c.iter().setResult(AstDecodeStackItem(call, argsLength));
return true;
}
@ -268,11 +279,12 @@ AstDecodeCallIndirect(AstDecodeContext& c)
if (!AstDecodeCallReturn(c, *sig))
return false;
uint32_t argsLength = args.length();
AstCallIndirect* call = new(c.lifo) AstCallIndirect(sigRef, index.expr, Move(args));
if (!call)
return false;
c.iter().setResult(AstDecodeStackItem(call, 1 + args.length()));
c.iter().setResult(AstDecodeStackItem(call, 1 + argsLength));
return true;
}
@ -300,11 +312,31 @@ AstDecodeCallImport(AstDecodeContext& c)
if (!AstDecodeCallReturn(c, *sig))
return false;
uint32_t argsLength = args.length();
AstCall* call = new(c.lifo) AstCall(Expr::CallImport, funcRef, Move(args));
if (!call)
return false;
c.iter().setResult(AstDecodeStackItem(call, args.length()));
c.iter().setResult(AstDecodeStackItem(call, argsLength));
return true;
}
static bool
AstDecodeGetBlockRef(AstDecodeContext& c, uint32_t depth, AstRef* ref)
{
if (!c.generateNames || depth >= c.blockLabels().length()) {
// Also ignoring if it's a function body label.
*ref = AstRef(AstName(), depth);
return true;
}
uint32_t index = c.blockLabels().length() - depth - 1;
if (c.blockLabels()[index].empty()) {
if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$label$"), 7), c.nextLabelIndex(), &c.blockLabels()[index]))
return false;
}
*ref = AstRef(c.blockLabels()[index], AstNoIndex);
ref->setIndex(depth);
return true;
}
@ -326,14 +358,18 @@ AstDecodeBrTable(AstDecodeContext& c)
for (size_t i = 0, e = tableLength; i < e; ++i) {
if (!c.iter().readBrTableEntry(type, &depth))
return false;
table[i] = AstRef(AstName(), depth);
if (!AstDecodeGetBlockRef(c, depth, &table[i]))
return false;
}
// Read the default label.
if (!c.iter().readBrTableEntry(type, &depth))
return false;
AstRef def(AstName(), depth);
AstRef def;
if (!AstDecodeGetBlockRef(c, depth, &def))
return false;
AstBranchTable* branchTable = new(c.lifo) AstBranchTable(*index.expr, def, Move(table), value.expr);
if (!branchTable)
return false;
@ -348,9 +384,13 @@ AstDecodeBlock(AstDecodeContext& c, Expr expr)
MOZ_ASSERT(expr == Expr::Block || expr == Expr::Loop);
if (expr == Expr::Loop) {
if (!c.blockLabels().append(AstName()) || !c.blockLabels().append(AstName()))
return false;
if (!c.iter().readLoop())
return false;
} else {
if (!c.blockLabels().append(AstName()))
return false;
if (!c.iter().readBlock())
return false;
}
@ -369,7 +409,11 @@ AstDecodeBlock(AstDecodeContext& c, Expr expr)
return false;
}
AstBlock* block = new(c.lifo) AstBlock(expr, AstName(), AstName(), Move(exprs));
AstName continueName;
if (expr == Expr::Loop)
continueName = c.blockLabels().popCopy();
AstName breakName = c.blockLabels().popCopy();
AstBlock* block = new(c.lifo) AstBlock(expr, breakName, continueName, Move(exprs));
if (!block)
return false;
@ -386,6 +430,8 @@ AstDecodeIf(AstDecodeContext& c)
bool hasElse = false;
if (!c.blockLabels().append(AstName()))
return false;
AstExprVector thenExprs(c.lifo);
while (true) {
if (!AstDecodeExpr(c))
@ -401,9 +447,13 @@ AstDecodeIf(AstDecodeContext& c)
if (!thenExprs.append(item.expr))
return false;
}
AstName thenName = c.blockLabels().popCopy();
AstName elseName;
AstExprVector elseExprs(c.lifo);
if (hasElse) {
if (!c.blockLabels().append(AstName()))
return false;
while (true) {
if (!AstDecodeExpr(c))
return false;
@ -416,9 +466,10 @@ AstDecodeIf(AstDecodeContext& c)
if (!elseExprs.append(item.expr))
return false;
}
elseName = c.blockLabels().popCopy();
}
AstIf* if_ = new(c.lifo) AstIf(cond.expr, AstName(), Move(thenExprs), AstName(), Move(elseExprs));
AstIf* if_ = new(c.lifo) AstIf(cond.expr, thenName, Move(thenExprs), elseName, Move(elseExprs));
if (!if_)
return false;
@ -590,7 +641,10 @@ AstDecodeBranch(AstDecodeContext& c, Expr expr)
popped = value.expr ? 2 : 1;
}
AstRef depthRef(AstName(), depth);
AstRef depthRef;
if (!AstDecodeGetBlockRef(c, depth, &depthRef))
return false;
AstBranch* branch = new(c.lifo) AstBranch(expr, cond.expr, depthRef, value.expr);
if (!branch)
return false;
@ -1187,7 +1241,7 @@ AstDecodeMemorySection(AstDecodeContext& c)
if (!c.d.readVarU32(&initialSizePages))
return AstDecodeFail(c, "expected initial memory size");
CheckedInt<int32_t> initialSize = initialSizePages;
CheckedInt<uint32_t> initialSize = initialSizePages;
initialSize *= PageSize;
if (!initialSize.isValid())
return AstDecodeFail(c, "initial memory size too big");
@ -1196,10 +1250,10 @@ AstDecodeMemorySection(AstDecodeContext& c)
if (!c.d.readVarU32(&maxSizePages))
return AstDecodeFail(c, "expected initial memory size");
CheckedInt<int32_t> maxSize = maxSizePages;
CheckedInt<uint32_t> maxSize = maxSizePages;
maxSize *= PageSize;
if (!maxSize.isValid())
return AstDecodeFail(c, "initial memory size too big");
return AstDecodeFail(c, "maximum memory size too big");
uint8_t exported;
if (!c.d.readFixedU8(&exported))
@ -1304,6 +1358,10 @@ AstDecodeFunctionBody(AstDecodeContext &c, uint32_t funcIndex, AstFunc** func)
c.startFunction(&iter, &locals);
AstName funcName;
if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$func$"), 6), funcIndex, &funcName))
return false;
uint32_t numParams = sig->args().length();
uint32_t numLocals = locals.length();
for (uint32_t i = numParams; i < numLocals; i++) {
@ -1339,10 +1397,6 @@ AstDecodeFunctionBody(AstDecodeContext &c, uint32_t funcIndex, AstFunc** func)
if (c.d.currentPosition() != bodyEnd)
return AstDecodeFail(c, "function body length mismatch");
AstName funcName;
if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$func$"), 6), funcIndex, &funcName))
return false;
AstRef sigRef;
if (!AstDecodeGenerateRef(c, AstName(MOZ_UTF16("$type$"), 6), sigIndex, &sigRef))
return false;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* Copyright 2015 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef wasm_binary_to_experimental_text_h
#define wasm_binary_to_experimental_text_h
#include "NamespaceImports.h"
#include "gc/Rooting.h"
#include "js/Class.h"
namespace js {
class StringBuffer;
namespace wasm {
struct ExperimentalTextFormatting
{
bool allowAsciiOperators:1;
bool reduceParens:1;
bool groupBlocks:1;
ExperimentalTextFormatting()
: allowAsciiOperators(true),
reduceParens(true),
groupBlocks(true)
{}
};
// Translate the given binary representation of a wasm module into the module's textual
// representation.
MOZ_MUST_USE bool
BinaryToExperimentalText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer,
const ExperimentalTextFormatting& formatting);
} // namespace wasm
} // namespace js
#endif // namespace wasm_binary_to_experimental_text_h

Просмотреть файл

@ -18,8 +18,6 @@
#include "asmjs/WasmBinaryToText.h"
#include "mozilla/CheckedInt.h"
#include "jsnum.h"
#include "jsprf.h"
@ -33,7 +31,6 @@
using namespace js;
using namespace js::wasm;
using mozilla::CheckedInt;
using mozilla::IsInfinite;
using mozilla::IsNaN;
using mozilla::IsNegativeZero;
@ -45,11 +42,6 @@ struct WasmRenderContext
StringBuffer& buffer;
uint32_t indent;
DeclaredSigVector signatures;
Uint32Vector funcSigs;
Uint32Vector funcLocals;
Uint32Vector importSigs;
uint32_t currentFuncIndex;
WasmRenderContext(JSContext* cx, AstModule* module, StringBuffer& buffer)
@ -298,6 +290,10 @@ RenderCallIndirect(WasmRenderContext& c, AstCallIndirect& call)
return false;
if (!RenderCallArgs(c, call.args()))
return false;
if (!c.buffer.append(")"))
return false;
return true;
}
@ -385,9 +381,25 @@ RenderBlock(WasmRenderContext& c, AstBlock& block)
if (block.expr() == Expr::Block) {
if (!c.buffer.append("(block "))
return false;
if (!RenderName(c, block.breakName()))
return false;
} else if (block.expr() == Expr::Loop) {
if (!c.buffer.append("(loop "))
return false;
if (block.breakName().empty() && !block.continueName().empty()) {
// Giving auto label if continue label is present.
if (!c.buffer.append("$exit$"))
return false;
} else {
if (!RenderName(c, block.breakName()))
return false;
}
if (!block.continueName().empty()) {
if (!c.buffer.append(" "))
return false;
if (!RenderName(c, block.continueName()))
return false;
}
} else
return false;
@ -655,6 +667,9 @@ RenderIf(WasmRenderContext& c, AstIf& if_)
if (!c.buffer.append(" (then "))
return false;
if (!RenderName(c, if_.thenName()))
return false;
c.indent++;
if (!RenderExprList(c, if_.thenExprs()))
return false;
@ -664,6 +679,9 @@ RenderIf(WasmRenderContext& c, AstIf& if_)
if (!c.buffer.append(") (else "))
return false;
if (!RenderName(c, if_.elseName()))
return false;
c.indent++;
if (!RenderExprList(c, if_.elseExprs()))
return false;
@ -1045,10 +1063,10 @@ RenderTypeSection(WasmRenderContext& c, const AstModule::SigVector& sigs)
if (!c.buffer.append("(type"))
return false;
if (!sig->name().empty()) {
if (!c.buffer.append(" "))
return false;
if (!RenderName(c, sig->name()))
return false;
if (!c.buffer.append(" "))
return false;
if (!RenderName(c, sig->name()))
return false;
}
if (!c.buffer.append(" (func"))
return false;
@ -1068,10 +1086,15 @@ RenderTableSection(WasmRenderContext& c, AstTable* maybeTable, const AstModule::
uint32_t numTableElems = maybeTable->elems().length();
if (!c.buffer.append("(table "))
if (!RenderIndent(c))
return false;
if (!c.buffer.append("(table"))
return false;
for (uint32_t i = 0; i < numTableElems; i++) {
if (!c.buffer.append(" "))
return false;
AstRef& elem = maybeTable->elems()[i];
AstFunc* func = funcs[elem.index()];
if (func->name().empty()) {
@ -1083,7 +1106,7 @@ RenderTableSection(WasmRenderContext& c, AstTable* maybeTable, const AstModule::
}
}
if (!c.buffer.append(")"))
if (!c.buffer.append(")\n"))
return false;
return true;

Просмотреть файл

@ -25,6 +25,7 @@
#include "jsprf.h"
#include "asmjs/WasmBinaryToExperimentalText.h"
#include "asmjs/WasmBinaryToText.h"
#include "asmjs/WasmSerialize.h"
#include "builtin/AtomicsObject.h"
@ -1673,7 +1674,7 @@ Module::createText(JSContext* cx)
if (!source_.empty()) {
if (!buffer.append(experimentalWarning))
return nullptr;
if (!BinaryToText(cx, source_.begin(), source_.length(), buffer))
if (!BinaryToExperimentalText(cx, source_.begin(), source_.length(), buffer, ExperimentalTextFormatting()))
return nullptr;
} else {
if (!buffer.append(enabledMessage))

Просмотреть файл

@ -467,8 +467,8 @@ class Module : public mozilla::LinkedListElement<Module>
struct ImportExit {
void* code;
jit::BaselineScript* baselineScript;
HeapPtrFunction fun;
static_assert(sizeof(HeapPtrFunction) == sizeof(void*), "for JIT access");
GCPtrFunction fun;
static_assert(sizeof(GCPtrFunction) == sizeof(void*), "for JIT access");
};
struct EntryArg {
uint64_t lo;
@ -485,8 +485,8 @@ class Module : public mozilla::LinkedListElement<Module>
};
typedef Vector<FuncPtrTable, 0, SystemAllocPolicy> FuncPtrTableVector;
typedef Vector<CacheableChars, 0, SystemAllocPolicy> FuncLabelVector;
typedef RelocatablePtrArrayBufferObjectMaybeShared BufferPtr;
typedef HeapPtr<WasmModuleObject*> ModuleObjectPtr;
typedef HeapPtr<ArrayBufferObjectMaybeShared*> BufferPtr;
typedef GCPtr<WasmModuleObject*> ModuleObjectPtr;
// Initialized when constructed:
const UniqueConstModuleData module_;
@ -538,7 +538,7 @@ class Module : public mozilla::LinkedListElement<Module>
virtual void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
void setOwner(WasmModuleObject* owner) { MOZ_ASSERT(!ownerObject_); ownerObject_ = owner; }
inline const HeapPtr<WasmModuleObject*>& owner() const;
inline const GCPtr<WasmModuleObject*>& owner() const;
void setSource(Bytes&& source) { source_ = Move(source); }
@ -688,7 +688,7 @@ class WasmModuleObject : public NativeObject
static const Class class_;
};
inline const HeapPtr<WasmModuleObject*>&
inline const GCPtr<WasmModuleObject*>&
wasm::Module::owner() const {
MOZ_ASSERT(&ownerObject_->module() == this);
return ownerObject_;

Просмотреть файл

@ -293,14 +293,20 @@ EvalKernel(JSContext* cx, HandleValue v, EvalType evalType, AbstractFramePtr cal
return false;
CompileOptions options(cx);
options.setFileAndLine(filename, 1)
.setIsRunOnce(true)
options.setIsRunOnce(true)
.setForEval(true)
.setNoScriptRval(false)
.setMutedErrors(mutedErrors)
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
.maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc));
if (introducerFilename) {
options.setFileAndLine(filename, 1);
options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
} else {
options.setFileAndLine("eval", 1);
options.setIntroductionType("eval");
}
AutoStableStringChars linearChars(cx);
if (!linearChars.initTwoByte(cx, linearStr))
return false;
@ -375,14 +381,20 @@ js::DirectEvalStringFromIon(JSContext* cx,
return false;
CompileOptions options(cx);
options.setFileAndLine(filename, 1)
.setIsRunOnce(true)
options.setIsRunOnce(true)
.setForEval(true)
.setNoScriptRval(false)
.setMutedErrors(mutedErrors)
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
.maybeMakeStrictMode(IsStrictEvalPC(pc));
if (introducerFilename) {
options.setFileAndLine(filename, 1);
options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
} else {
options.setFileAndLine("eval", 1);
options.setIntroductionType("eval");
}
AutoStableStringChars linearChars(cx);
if (!linearChars.initTwoByte(cx, linearStr))
return false;

Просмотреть файл

@ -438,7 +438,7 @@ MapObject::set(JSContext* cx, HandleObject obj, HandleValue k, HandleValue v)
if (!key.setValue(cx, k))
return false;
RelocatableValue rval(v);
HeapPtr<Value> rval(v);
if (!map->put(key, rval)) {
ReportOutOfMemory(cx);
return false;
@ -538,7 +538,7 @@ MapObject::construct(JSContext* cx, unsigned argc, Value* vp)
if (!hkey.setValue(cx, key))
return false;
RelocatableValue rval(val);
HeapPtr<Value> rval(val);
if (!map->put(hkey, rval)) {
ReportOutOfMemory(cx);
return false;
@ -688,7 +688,7 @@ MapObject::set_impl(JSContext* cx, const CallArgs& args)
ValueMap& map = extract(args);
ARG0_KEY(cx, args, key);
RelocatableValue rval(args.get(1));
HeapPtr<Value> rval(args.get(1));
if (!map.put(key, rval)) {
ReportOutOfMemory(cx);
return false;
@ -725,14 +725,14 @@ bool
MapObject::delete_impl(JSContext *cx, const CallArgs& args)
{
// MapObject::mark does not mark deleted entries. Incremental GC therefore
// requires that no RelocatableValue objects pointing to heap values be
// left alive in the ValueMap.
// requires that no HeapPtr<Value> objects pointing to heap values be left
// alive in the ValueMap.
//
// OrderedHashMap::remove() doesn't destroy the removed entry. It merely
// calls OrderedHashMap::MapOps::makeEmpty. But that is sufficient, because
// makeEmpty clears the value by doing e->value = Value(), and in the case
// of a ValueMap, Value() means RelocatableValue(), which is the same as
// RelocatableValue(UndefinedValue()).
// of a ValueMap, Value() means HeapPtr<Value>(), which is the same as
// HeapPtr<Value>(UndefinedValue()).
MOZ_ASSERT(MapObject::is(args.thisv()));
ValueMap& map = extract(args);

Просмотреть файл

@ -66,7 +66,7 @@ template <class T, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashSet;
typedef OrderedHashMap<HashableValue,
RelocatableValue,
HeapPtr<Value>,
HashableValue::Hasher,
RuntimeAllocPolicy> ValueMap;

Просмотреть файл

@ -118,8 +118,8 @@ class IndirectBindingMap
struct Binding
{
Binding(ModuleEnvironmentObject* environment, Shape* shape);
RelocatablePtr<ModuleEnvironmentObject*> environment;
RelocatablePtrShape shape;
HeapPtr<ModuleEnvironmentObject*> environment;
HeapPtr<Shape*> shape;
};
typedef HashMap<jsid, Binding, DefaultHasher<jsid>, ZoneAllocPolicy> Map;
@ -194,8 +194,8 @@ struct FunctionDeclaration
FunctionDeclaration(HandleAtom name, HandleFunction fun);
void trace(JSTracer* trc);
RelocatablePtrAtom name;
RelocatablePtrFunction fun;
HeapPtr<JSAtom*> name;
HeapPtr<JSFunction*> fun;
};
using FunctionDeclarationVector = GCVector<FunctionDeclaration, 0, ZoneAllocPolicy>;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше