Merge autoland to central, a=merge

MozReview-Commit-ID: Lf7ROINgvql
This commit is contained in:
Wes Kocher 2017-07-07 17:22:00 -07:00
Родитель 5f00a2d1ab d566bb2652
Коммит fd4857585c
197 изменённых файлов: 2959 добавлений и 1297 удалений

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

@ -8,60 +8,58 @@ obj*/**
# If you are enabling a directory, please add directory specific exclusions
# below.
addon-sdk/**
build/**
chrome/**
config/**
db/**
docshell/**
editor/**
embedding/**
extensions/**
extensions/cookie/**
extensions/spellcheck/**
extensions/universalchardet/**
gfx/**
gradle/**
hal/**
image/**
intl/**
ipc/**
layout/**
media/**
memory/**
mfbt/**
modules/**
mozglue/**
netwerk/**
nsprpub/**
other-licenses/**
parser/**
probes/**
python/**
rdf/**
servo/**
startupcache/**
tools/update-packaging/**
uriloader/**
view/**
widget/**
xpcom/**
xpfe/**
xulrunner/**
# b2g exclusions (pref files).
b2g/app/b2g.js
b2g/graphene/graphene.js
b2g/locales/en-US/b2g-l10n.js
# We currently have no js files in these directories, so we ignore them by
# default to aid ESLint's performance.
build/**
db/**
gradle/**
hal/**
mfbt/**
mozglue/**
nsprpub/**
other-licenses/**
probes/**
startupcache/**
xpfe/**
# browser/ exclusions
browser/app/**
browser/branding/**/firefox-branding.js
browser/base/content/test/general/file_csp_block_all_mixedcontent.html
# Gzipped test file.
browser/base/content/test/general/gZipOfflineChild.html
browser/base/content/test/urlbar/file_blank_but_not_blank.html
# New tab is likely to be replaced soon.
browser/base/content/newtab/**
# Test files that are really json not js, and don't need to be linted.
browser/components/sessionstore/test/unit/data/sessionstore_valid.js
browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
browser/components/tabview/**
# generated & special files in cld2
browser/components/translation/cld2/**
# Screenshots and Follow-on search are imported as a system add-on and have
@ -73,10 +71,11 @@ browser/extensions/pdfjs/content/web**
# generated or library files in pocket
browser/extensions/pocket/content/panels/js/tmpl.js
browser/extensions/pocket/content/panels/js/vendor/**
browser/locales/**
# generated or library files in activity-stream
browser/extensions/activity-stream/data/content/activity-stream.bundle.js
browser/extensions/activity-stream/vendor/**
# The only file in browser/locales/ is pre-processed.
browser/locales/**
# imported from chromium
browser/extensions/mortar/**
@ -268,7 +267,6 @@ js/src/Y.js
mobile/android/tests/browser/chrome/tp5/**
# Uses `#filter substitution`
mobile/android/b2gdroid/app/b2gdroid.js
mobile/android/app/mobile.js
mobile/android/chrome/content/healthreport-prefs.js
@ -283,13 +281,10 @@ mobile/android/locales/
mobile/android/chrome/content/browser.js
mobile/android/components/Snippets.js
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
mobile/android/modules/HomeProvider.jsm
# security/ exclusions (pref files).
security/manager/ssl/security-prefs.js
#NSS
# NSS / taskcluster only.
security/nss/**
# services/ exclusions
@ -342,6 +337,7 @@ toolkit/modules/tests/xpcshell/test_task.js
# Not yet updated
toolkit/components/osfile/**
toolkit/components/url-classifier/**
# External code:
toolkit/components/microformats/test/**
@ -352,13 +348,10 @@ toolkit/components/reader/JSDOMParser.js
# Uses preprocessing
toolkit/content/widgets/wizard.xml
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/url-classifier/**
toolkit/components/urlformatter/nsURLFormatter.js
toolkit/modules/AppConstants.jsm
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/internal/AddonConstants.jsm
toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
toolkit/webapps/**
# Third party
toolkit/modules/third_party/**

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

@ -377,11 +377,11 @@ this.AccessFu = { // jshint ignore:line
// We delay this for half a second so the awesomebar could close,
// and we could use the current coordinates for the content item.
// XXX TODO figure out how to avoid magic wait here.
this.autoMove({
delay: 500,
forcePresent: true,
noOpIfOnScreen: true,
moveMethod: 'moveFirst' });
this.autoMove({
delay: 500,
forcePresent: true,
noOpIfOnScreen: true,
moveMethod: 'moveFirst' });
}
break;
}

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

@ -660,7 +660,7 @@ this.Logger = { // jshint ignore:line
let pivot = aEvent.accessible.QueryInterface(
Ci.nsIAccessibleDocument).virtualCursor;
str += ' (' + this.accessibleToString(event.oldAccessible) + ' -> ' +
this.accessibleToString(pivot.position) + ')';
this.accessibleToString(pivot.position) + ')';
}
return str;

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

@ -19,31 +19,31 @@
<script>
function dumpAccessibleNode(aNode, level) {
var msg = "";
var msg = "";
try {
msg += "name=\"" + aNode.name + "\" ";
} catch (e) {
msg += " noName ";
}
try {
msg += "name=\"" + aNode.name + "\" ";
} catch (e) {
msg += " noName ";
}
dump(msg + '\n');
dump(msg + '\n');
}
function dumpAccessibleTree(aNode, level) {
level = level || 0;
level = level || 0;
dumpAccessibleNode(aNode, level);
try {
var child = aNode.firstChild;
while (child) {
dumpAccessibleTree(child, level + 1);
child = child.nextSibling;
}
} catch (e) {
dump("Error visiting child nodes: " + e + '\n');
}
dumpAccessibleNode(aNode, level);
try {
var child = aNode.firstChild;
while (child) {
dumpAccessibleTree(child, level + 1);
child = child.nextSibling;
}
} catch (e) {
dump("Error visiting child nodes: " + e + '\n');
}
}
function A(o) {

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

@ -20,7 +20,7 @@ Cu.import("resource://gre/modules/accessibility/OutputGenerator.jsm", this);
function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator) {
var accessible = getAccessible(aAccOrElmOrID);
var oldAccessible = aOldAccOrElmOrID !== null ?
getAccessible(aOldAccOrElmOrID || 'root') : null;
getAccessible(aOldAccOrElmOrID || 'root') : null;
var context = new PivotContext(accessible, oldAccessible);
var output = aGenerator.genForContext(context);

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

@ -33,7 +33,7 @@
{ SECTION: [
{ SECTION: [
{ TEXT_LEAF: [ ] }
] }
] }
] };
testAccessibleTree("table2", accTree);

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

@ -148,7 +148,7 @@
//////////////////////////////////////////////////////////////////////////
// area6 (CSS vertical-align property, refer to bug 445938 for details
// and sup and sub elements, refer to bug 735645 for details)
// and sup and sub elements, refer to bug 735645 for details)
ID = "area6";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
testDefaultTextAttrs(ID, defAttrs);

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

@ -5785,8 +5785,8 @@ function contentAreaClick(event, isPanelClick) {
title: linkNode.getAttribute("title"),
loadBookmarkInSidebar: true,
hiddenRows: [ "description",
"location",
"keyword" ]
"location",
"keyword" ]
}, window);
event.preventDefault();
return;

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

@ -300,7 +300,7 @@ function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
// Now go back in the opposite direction.
test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0,
-initialDelta, 0);
-initialDelta, 0);
cumulativeDelta += -initialDelta;
if (isIncreasing) {
expect.dec++;
@ -321,7 +321,7 @@ function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
// Go back to the original direction. The original command should trigger.
test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0,
initialDelta, 0);
initialDelta, 0);
cumulativeDelta += initialDelta;
if (isIncreasing) {
expect.inc++;

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

@ -1183,9 +1183,9 @@ const CustomizableWidgets = [
observe(aSubject, aTopic, aData) {
let {instances} = CustomizableUI.getWidget("containers-panelmenu");
for (let {node} of instances) {
if (node) {
this.updateVisibility(node);
}
if (node) {
this.updateVisibility(node);
}
}
},

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

@ -534,8 +534,9 @@ const PanelUI = {
CustomizableUI.removePanelCloseListeners(tempPanel);
tempPanel.removeEventListener("popuphidden", panelRemover);
let evt = new CustomEvent("ViewHiding", {detail: viewNode});
viewNode.dispatchEvent(evt);
let currentView = multiView.current || viewNode;
let evt = new CustomEvent("ViewHiding", {detail: currentView});
currentView.dispatchEvent(evt);
}
aAnchor.open = false;

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

@ -89,8 +89,8 @@ ESE.JET_COLTYP = ctypes.unsigned_long;
ESE.JET_DBID = ctypes.unsigned_long;
ESE.JET_COLUMNDEF = new ctypes.StructType("JET_COLUMNDEF", [
{"cbStruct": ctypes.unsigned_long},
{"columnid": ESE.JET_COLUMNID },
{"cbStruct": ctypes.unsigned_long },
{"columnid": ESE.JET_COLUMNID },
{"coltyp": ESE.JET_COLTYP },
{"wCountry": ctypes.unsigned_short }, // sepcifies the country/region for the column definition
{"langid": ctypes.unsigned_short },

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

@ -371,9 +371,9 @@ var BookmarkPropertiesPanel = {
}
},
// Hack for implementing batched-Undo around the editBookmarkOverlay
// instant-apply code. For all the details see the comment above beginBatch
// in browser-places.js
// Hack for implementing batched-Undo around the editBookmarkOverlay
// instant-apply code. For all the details see the comment above beginBatch
// in browser-places.js
_batchBlockingDeferred: null,
_beginBatch() {
if (this._batching)

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

@ -278,7 +278,7 @@ const CONFIRM_RESTART_PROMPT_CANCEL = 1;
const CONFIRM_RESTART_PROMPT_RESTART_LATER = 2;
function confirmRestartPrompt(aRestartToEnable, aDefaultButtonIndex,
aWantRevertAsCancelButton,
aWantRestartLaterButton) {
aWantRestartLaterButton) {
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
let bundle = document.getElementById("bundlePreferences");
let msg = bundle.getFormattedString(aRestartToEnable ?

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

@ -39,6 +39,7 @@ skip-if = true || !healthreport # Bug 1185403 for the "true"
[browser_layersacceleration.js]
[browser_masterpassword.js]
[browser_notifications_do_not_disturb.js]
[browser_password_management.js]
[browser_performance.js]
skip-if = !e10s
[browser_performance_non_e10s.js]

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

@ -0,0 +1,73 @@
"use strict";
const PM_URL = "chrome://passwordmgr/content/passwordManager.xul";
var passwordsDialog;
add_task(async function test_setup() {
let pwmgr = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager);
pwmgr.removeAllLogins();
// add login data
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
let login = new nsLoginInfo("http://example.com/", "http://example.com/", null,
"user", "password", "u1", "p1");
pwmgr.addLogin(login);
registerCleanupFunction(async function() {
pwmgr.removeAllLogins();
});
});
add_task(async function test_openPasswordSubDialog() {
// Undo the save password change.
registerCleanupFunction(async function() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
if (savePasswordCheckBox.checked) {
savePasswordCheckBox.click();
}
});
gBrowser.removeCurrentTab();
});
await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
let dialogOpened = promiseLoadSubDialog(PM_URL);
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
Assert.ok(!savePasswordCheckBox.checked,
"Save Password CheckBox should be unchecked by default");
savePasswordCheckBox.click();
let showPasswordsButton = doc.getElementById("showPasswords");
showPasswordsButton.click();
});
passwordsDialog = await dialogOpened;
});
add_task(async function test_deletePasswordWithKey() {
let doc = passwordsDialog.document;
let tree = doc.getElementById("signonsTree");
Assert.equal(tree.view.rowCount, 1, "Row count should initially be 1");
tree.focus();
tree.view.selection.select(0);
if (AppConstants.platform == "macosx") {
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
} else {
EventUtils.synthesizeKey("VK_DELETE", {});
}
await waitForCondition(() => tree.view.rowCount == 0);
is_element_visible(content.gSubDialog._dialogs[0]._box,
"Subdialog is visible after deleting an element");
});

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

@ -245,7 +245,7 @@ const CONFIRM_RESTART_PROMPT_CANCEL = 1;
const CONFIRM_RESTART_PROMPT_RESTART_LATER = 2;
function confirmRestartPrompt(aRestartToEnable, aDefaultButtonIndex,
aWantRevertAsCancelButton,
aWantRestartLaterButton) {
aWantRestartLaterButton) {
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
let bundle = document.getElementById("bundlePreferences");
let msg = bundle.getFormattedString(aRestartToEnable ?

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

@ -29,6 +29,7 @@ skip-if = os != "win" # This test tests the windows-specific app selection dialo
skip-if = true || !healthreport # Bug 1185403 for the "true"
[browser_homepages_filter_aboutpreferences.js]
[browser_notifications_do_not_disturb.js]
[browser_password_management.js]
[browser_performance.js]
skip-if = !e10s
[browser_performance_non_e10s.js]

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

@ -0,0 +1,71 @@
"use strict";
const PM_URL = "chrome://passwordmgr/content/passwordManager.xul";
var passwordsDialog;
add_task(async function setup() {
Services.logins.removeAllLogins();
// add login data
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
let login = new nsLoginInfo("http://example.com/", "http://example.com/", null,
"user", "password", "u1", "p1");
Services.logins.addLogin(login);
registerCleanupFunction(async function() {
Services.logins.removeAllLogins();
});
});
add_task(async function test_openPasswordSubDialog() {
// Undo the save password change.
registerCleanupFunction(async function() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
if (savePasswordCheckBox.checked) {
savePasswordCheckBox.click();
}
});
gBrowser.removeCurrentTab();
});
await openPreferencesViaOpenPreferencesAPI("security", null, {leaveOpen: true});
let dialogOpened = promiseLoadSubDialog(PM_URL);
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
Assert.ok(!savePasswordCheckBox.checked,
"Save Password CheckBox should be unchecked by default");
savePasswordCheckBox.click();
let showPasswordsButton = doc.getElementById("showPasswords");
showPasswordsButton.click();
});
passwordsDialog = await dialogOpened;
});
add_task(async function test_deletePasswordWithKey() {
let doc = passwordsDialog.document;
let tree = doc.getElementById("signonsTree");
Assert.equal(tree.view.rowCount, 1, "Row count should initially be 1");
tree.focus();
tree.view.selection.select(0);
if (AppConstants.platform == "macosx") {
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
} else {
EventUtils.synthesizeKey("VK_DELETE", {});
}
await waitForCondition(() => tree.view.rowCount == 0);
is_element_visible(content.gSubDialog._dialogs[0]._box,
"Subdialog is visible after deleting an element");
});

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

@ -3,24 +3,16 @@
"use strict";
const {classes: Cc, interfaces: Ci} = Components;
/**
* Make sure that tabs are restored on demand as otherwise the tab will start
* loading immediately and we can't check its icon and label.
*/
add_task(function setup() {
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
});
});
/**
* Ensure that a pending tab has label and icon correctly set.
*/
add_task(async function test_label_and_icon() {
// Make sure that tabs are restored on demand as otherwise the tab will start
// loading immediately and we can't check its icon and label.
await SpecialPowers.pushPrefEnv({
set: [["browser.sessionstore.restore_on_demand", true]],
});
// Create a new tab.
let tab = BrowserTestUtils.addTab(gBrowser, "about:robots");
let browser = tab.linkedBrowser;

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

@ -20,19 +20,17 @@ add_task(async function() {
const ABOUT_ROBOTS_URI = "about:robots";
const ABOUT_ROBOTS_TITLE = "Gort! Klaatu barada nikto!";
function observeLabelChanges(tab) {
info("observing tab label changes. initial label: " + tab.label);
let labelChangeCount = 0;
function observeLabelChanges(tab, expectedLabels) {
let seenLabels = [tab.label];
function TabAttrModifiedListener(event) {
if (event.detail.changed.some(attr => { return attr == "label" })) {
info("tab label change: " + tab.label);
labelChangeCount++;
if (event.detail.changed.some(attr => attr == "label")) {
seenLabels.push(tab.label);
}
}
tab.addEventListener("TabAttrModified", TabAttrModifiedListener);
return (expectedCount) => {
return () => {
tab.removeEventListener("TabAttrModified", TabAttrModifiedListener);
is(labelChangeCount, expectedCount, "observed tab label changes");
is(JSON.stringify(seenLabels), JSON.stringify(expectedLabels || []), "observed tab label changes");
}
}
@ -59,33 +57,29 @@ add_task(async function() {
is(firstTab.label, CONTENT_TITLE, "first tab displays content title");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
ok(secondTab.hasAttribute("pending"), "second tab is pending");
ok(thirdTab.hasAttribute("pending"), "third tab is pending");
info("selecting the second tab");
// The fix for bug 1364127 caused about: pages' initial tab titles to show
// their about: URIs until their actual page titles are known, e.g.
// "about:addons" -> "Add-ons Manager". This is bug 1371896. Previously,
// about: pages' initial tab titles were blank until the page title was known.
is(secondTab.label, ABOUT_ROBOTS_URI, "second tab displays URI as its initial title");
ok(thirdTab.hasAttribute("pending"), "third tab is pending");
is(thirdTab.label, "example.com", "third tab displays hostname without www as its initial title");
info("selecting the second tab");
let checkLabelChangeCount = observeLabelChanges(secondTab);
let finishObservingLabelChanges = observeLabelChanges(secondTab, [ABOUT_ROBOTS_URI, ABOUT_ROBOTS_TITLE]);
browserLoadedPromise = BrowserTestUtils.browserLoaded(secondTab.linkedBrowser, false, ABOUT_ROBOTS_URI);
gBrowser.selectedTab = secondTab;
await browserLoadedPromise;
ok(!secondTab.hasAttribute("pending"), "second tab isn't pending anymore");
is(secondTab.label, ABOUT_ROBOTS_TITLE, "second tab displays content title");
ok(document.title.startsWith(ABOUT_ROBOTS_TITLE), "title bar displays content title");
checkLabelChangeCount(1); // ABOUT_ROBOTS_URI -> ABOUT_ROBOTS_TITLE
finishObservingLabelChanges();
info("selecting the third tab");
checkLabelChangeCount = observeLabelChanges(thirdTab);
finishObservingLabelChanges = observeLabelChanges(thirdTab, ["example.com", CONTENT_TITLE]);
browserLoadedPromise = BrowserTestUtils.browserLoaded(thirdTab.linkedBrowser, false, TEST_URL);
gBrowser.selectedTab = thirdTab;
await browserLoadedPromise;
ok(!thirdTab.hasAttribute("pending"), "third tab isn't pending anymore");
is(thirdTab.label, CONTENT_TITLE, "third tab displays content title");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
checkLabelChangeCount(1); // TEST_URL -> CONTENT_TITLE
finishObservingLabelChanges();
info("restoring the modified browser state");
await TabStateFlusher.flushWindow(window);
@ -94,21 +88,19 @@ add_task(async function() {
is(thirdTab, gBrowser.selectedTab, "third tab is selected after restoring");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
ok(firstTab.hasAttribute("pending"), "first tab is pending after restoring");
is(firstTab.label, CONTENT_TITLE, "first tab displays content title in pending state");
ok(secondTab.hasAttribute("pending"), "second tab is pending after restoring");
is(secondTab.label, ABOUT_ROBOTS_TITLE, "second tab displays content title");
ok(!thirdTab.hasAttribute("pending"), "third tab is not pending after restoring");
is(thirdTab.label, CONTENT_TITLE, "third tab displays content title in pending state");
info("selecting the first tab");
checkLabelChangeCount = observeLabelChanges(firstTab);
finishObservingLabelChanges = observeLabelChanges(firstTab, [CONTENT_TITLE]);
let tabContentRestored = TestUtils.topicObserved("sessionstore-debug-tab-restored");
gBrowser.selectedTab = firstTab;
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
await tabContentRestored;
ok(!firstTab.hasAttribute("pending"), "first tab isn't pending anymore");
checkLabelChangeCount(0);
is(firstTab.label, CONTENT_TITLE, "first tab displays content title after restoring content");
finishObservingLabelChanges();
await promiseBrowserState(BACKUP_STATE);
});

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

@ -59,9 +59,9 @@ if (typeof Mozilla == "undefined") {
function listener(event) {
if (typeof event.detail != "object")
return;
return;
if (event.detail.callbackID != id)
return;
return;
document.removeEventListener("mozUITourResponse", listener);
callback(event.detail.data);
@ -266,12 +266,12 @@ if (typeof Mozilla == "undefined") {
var buttonData = [];
if (Array.isArray(buttons)) {
for (var i = 0; i < buttons.length; i++) {
buttonData.push({
label: buttons[i].label,
icon: buttons[i].icon,
style: buttons[i].style,
callbackID: _waitForCallback(buttons[i].callback)
});
buttonData.push({
label: buttons[i].label,
icon: buttons[i].icon,
style: buttons[i].style,
callbackID: _waitForCallback(buttons[i].callback)
});
}
}
@ -371,8 +371,8 @@ if (typeof Mozilla == "undefined") {
themes.push(theme);
_sendEvent("previewTheme", {
theme: JSON.stringify(theme),
state: true
theme: JSON.stringify(theme),
state: true
});
callback(theme);

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

@ -23,18 +23,18 @@ var pktPanelMessaging = (function() {
function addMessageListener(panelId, messageId, callback) {
document.addEventListener(panelPrefixedMessageId(panelId, messageId), function(e) {
callback(JSON.parse(e.target.getAttribute("payload"))[0]);
callback(JSON.parse(e.target.getAttribute("payload"))[0]);
// TODO: Figure out why e.target.parentNode is null
// e.target.parentNode.removeChild(e.target);
// TODO: Figure out why e.target.parentNode is null
// e.target.parentNode.removeChild(e.target);
});
});
}
}
function removeMessageListener(panelId, messageId, callback) {
function removeMessageListener(panelId, messageId, callback) {
document.removeEventListener(panelPrefixedMessageId(panelId, messageId), callback);
}
}
function sendMessage(panelId, messageId, payload, callback) {
// Payload needs to be an object in format:
@ -44,26 +44,26 @@ var pktPanelMessaging = (function() {
data: (payload || {})
};
// Create a callback to listen for a response
if (callback) {
var messageResponseId = messageId + "Response";
var responseListener = function(responsePayload) {
callback(responsePayload);
removeMessageListener(panelId, messageResponseId, responseListener);
}
// Create a callback to listen for a response
if (callback) {
var messageResponseId = messageId + "Response";
var responseListener = function(responsePayload) {
callback(responsePayload);
removeMessageListener(panelId, messageResponseId, responseListener);
}
addMessageListener(panelId, messageResponseId, responseListener);
}
addMessageListener(panelId, messageResponseId, responseListener);
}
// Send message
var element = document.createElement("PKTMessageFromPanelElement");
element.setAttribute("payload", JSON.stringify([messagePayload]));
document.documentElement.appendChild(element);
// Send message
var element = document.createElement("PKTMessageFromPanelElement");
element.setAttribute("payload", JSON.stringify([messagePayload]));
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent(prefixedMessageId(messageId), true, false);
element.dispatchEvent(evt);
}
var evt = document.createEvent("Events");
evt.initEvent(prefixedMessageId(messageId), true, false);
element.dispatchEvent(evt);
}
/**

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

@ -34,20 +34,20 @@ this.ContentWebRTC = {
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "getUserMedia:request":
handleGUMRequest(aSubject, aTopic, aData);
break;
handleGUMRequest(aSubject, aTopic, aData);
break;
case "recording-device-stopped":
handleGUMStop(aSubject, aTopic, aData);
break;
handleGUMStop(aSubject, aTopic, aData);
break;
case "PeerConnection:request":
handlePCRequest(aSubject, aTopic, aData);
break;
handlePCRequest(aSubject, aTopic, aData);
break;
case "recording-device-events":
updateIndicators(aSubject, aTopic, aData);
break;
updateIndicators(aSubject, aTopic, aData);
break;
case "recording-window-ended":
removeBrowserSpecificIndicator(aSubject, aTopic, aData);
break;
removeBrowserSpecificIndicator(aSubject, aTopic, aData);
break;
}
},

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

@ -263,9 +263,11 @@
background-image: url("chrome://browser/content/default-theme-icon.svg");
}
%ifdef MOZ_PHOTON_THEME
#customization-uidensity-button > .box-inherit > .box-inherit > .button-icon {
background-image: url("chrome://browser/skin/customizableui/density-normal.svg");
}
%endif
%ifndef MOZ_PHOTON_THEME
#main-window[customize-entered] #customization-panel-container {
@ -462,6 +464,7 @@ toolbarpaletteitem[place="toolbar"]:not([mousedown="true"]):-moz-focusring {
list-style-image: url(chrome://browser/content/default-theme-icon.svg);
}
%ifdef MOZ_PHOTON_THEME
#customization-uidensity-menu-button-normal {
list-style-image: url("chrome://browser/skin/customizableui/density-normal.svg");
}
@ -473,6 +476,7 @@ toolbarpaletteitem[place="toolbar"]:not([mousedown="true"]):-moz-focusring {
#customization-uidensity-menu-button-touch {
list-style-image: url("chrome://browser/skin/customizableui/density-touch.svg");
}
%endif
.customization-uidensity-menu-button[active="true"],
.customization-uidensity-menu-button:hover,

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

@ -664,8 +664,12 @@ menulist[indicator=true] > menupopup menuitem:not([image]) > .menu-iconic-left {
}
menulist[indicator=true] > menupopup menuitem[indicator=true]:not([image]) > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url(chrome://global/skin/icons/search-arrow-indicator.svg);
list-style-image: url(chrome://browser/skin/preferences/in-content-new/search-arrow-indicator.svg);
width: 8px;
height: 10px;
margin: 0;
}
menulist[indicator=true] > menupopup menuitem[indicator=true]:not([image]) > .menu-iconic-left > .menu-iconic-icon:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}

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

До

Ширина:  |  Высота:  |  Размер: 581 B

После

Ширина:  |  Высота:  |  Размер: 581 B

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

@ -94,6 +94,7 @@
skin/classic/browser/panel-icon-retry.svg (../shared/panel-icon-retry.svg)
skin/classic/browser/preferences/in-content-new/favicon.ico (../shared/incontentprefs/favicon.ico)
skin/classic/browser/preferences/in-content-new/icons.svg (../shared/incontentprefs/icons.svg)
skin/classic/browser/preferences/in-content-new/search-arrow-indicator.svg (../shared/incontentprefs/search-arrow-indicator.svg)
skin/classic/browser/preferences/in-content-new/search.css (../shared/incontentprefs/search.css)
skin/classic/browser/preferences/in-content-new/siteDataSettings.css (../shared/incontentprefs/siteDataSettings.css)
* skin/classic/browser/preferences/in-content-new/containers.css (../shared/incontentprefs/containers.css)

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

@ -4,12 +4,12 @@
--toolbarbutton-icon-fill-attention: #177ee5;
}
:-moz-any(@primaryToolbarButtons@) {
.toolbarbutton-1 {
-moz-context-properties: fill;
fill: var(--toolbarbutton-icon-fill);
}
toolbar[brighttext] :-moz-any(@primaryToolbarButtons@) {
toolbar[brighttext] .toolbarbutton-1 {
fill: var(--toolbarbutton-icon-fill-inverted);
}

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

@ -29,6 +29,9 @@ support-files =
doc_sourcemaps.css.map
doc_sourcemaps.html
doc_sourcemaps.scss
doc_sourcemaps2.css
doc_sourcemaps2.css^headers^
doc_sourcemaps2.html
doc_style_editor_link.css
doc_test_image.png
doc_urls_clickable.css
@ -192,6 +195,7 @@ skip-if = (os == "win" && debug) # bug 963492: win.
[browser_rules_multiple_properties_01.js]
[browser_rules_multiple_properties_02.js]
[browser_rules_original-source-link.js]
[browser_rules_original-source-link2.js]
[browser_rules_pseudo-element_01.js]
[browser_rules_pseudo-element_02.js]
[browser_rules_pseudo_lock_options.js]

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

@ -10,10 +10,10 @@
const TEST_URI = `
<style>
div {
background: #fff;
font-family: sans-serif;
url(display-table.min.htc);
}
background: #fff;
font-family: sans-serif;
url(display-table.min.htc);
}
</style>
<body>
<div id="testid" class="testclass">Styled Node</div>

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

@ -0,0 +1,85 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the stylesheet links in the rule view are correct when source maps
// are involved.
const TESTCASE_URI = URL_ROOT + "doc_sourcemaps2.html";
const PREF = "devtools.styleeditor.source-maps-enabled";
const SCSS_LOC = "doc_sourcemaps.scss:4";
const CSS_LOC = "doc_sourcemaps2.css:1";
add_task(function* () {
info("Setting the " + PREF + " pref to true");
Services.prefs.setBoolPref(PREF, true);
yield addTab(TESTCASE_URI);
let {toolbox, inspector, view} = yield openRuleView();
info("Selecting the test node");
yield selectNode("div", inspector);
yield verifyLinkText(SCSS_LOC, view);
info("Setting the " + PREF + " pref to false");
Services.prefs.setBoolPref(PREF, false);
yield verifyLinkText(CSS_LOC, view);
info("Setting the " + PREF + " pref to true again");
Services.prefs.setBoolPref(PREF, true);
yield testClickingLink(toolbox, view);
yield checkDisplayedStylesheet(toolbox);
info("Clearing the " + PREF + " pref");
Services.prefs.clearUserPref(PREF);
});
function* testClickingLink(toolbox, view) {
info("Listening for switch to the style editor");
let onStyleEditorReady = toolbox.once("styleeditor-ready");
info("Finding the stylesheet link and clicking it");
let link = getRuleViewLinkByIndex(view, 1);
link.scrollIntoView();
link.click();
yield onStyleEditorReady;
}
function checkDisplayedStylesheet(toolbox) {
let def = defer();
let panel = toolbox.getCurrentPanel();
panel.UI.on("editor-selected", (event, editor) => {
// The style editor selects the first sheet at first load before
// selecting the desired sheet.
if (editor.styleSheet.href.endsWith("scss")) {
info("Original source editor selected");
editor.getSourceEditor().then(editorSelected)
.then(def.resolve, def.reject);
}
});
return def.promise;
}
function editorSelected(editor) {
let href = editor.styleSheet.href;
ok(href.endsWith("doc_sourcemaps.scss"),
"selected stylesheet is correct one");
let {line} = editor.sourceEditor.getCursor();
is(line, 3, "cursor is at correct line number in original source");
}
function verifyLinkText(text, view) {
info("Verifying that the rule-view stylesheet link is " + text);
let label = getRuleViewLinkByIndex(view, 1)
.querySelector(".ruleview-rule-source-label");
return waitForSuccess(function* () {
return label.textContent == text;
}, "Link text changed to display correct location: " + text);
}

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

@ -0,0 +1,5 @@
div {
color: #ff0066; }
span {
background-color: #EEE; }

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

@ -0,0 +1 @@
X-SourceMap: doc_sourcemaps.css.map

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

@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<title>testcase for testing CSS source maps</title>
<link rel="stylesheet" type="text/css" href="simple.css"/>
<link rel="stylesheet" type="text/css" href="doc_sourcemaps2.css"/>
</head>
<body>
<div>source maps <span>testcase</span></div>
</body>
</html>

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

@ -622,6 +622,10 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
* Url of source map.
*/
_extractSourceMapUrl: function (content) {
// If a SourceMap response header was saved on the style sheet, use it.
if (this.rawSheet.sourceMapURL) {
return this.rawSheet.sourceMapURL;
}
let matches = /sourceMappingURL\=([^\s\*]*)/.exec(content);
if (matches) {
return matches[1];

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

@ -10610,6 +10610,16 @@ nsContentUtils::GetUserIsInteracting()
return UserInteractionObserver::sUserActive;
}
/* static */ bool
nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult)
{
nsresult rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), aResult);
if (NS_FAILED(rv)) {
rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), aResult);
}
return NS_SUCCEEDED(rv);
}
static const char* kUserInteractionInactive = "user-interaction-inactive";
static const char* kUserInteractionActive = "user-interaction-active";

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

@ -3082,6 +3082,16 @@ public:
*/
static bool IsOverridingWindowName(const nsAString& aName);
/**
* If there is a SourceMap (higher precedence) or X-SourceMap (lower
* precedence) response header in |aChannel|, set |aResult| to the
* header's value and return true. Otherwise, return false.
*
* @param aChannel The HTTP channel
* @param aResult The string result.
*/
static bool GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult);
private:
static bool InitializeEventTable();

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

@ -136,19 +136,32 @@ GetIMEStateSetOpenName(IMEState::Open aOpen)
}
}
static bool
IsSameProcess(const TabParent* aTabParent1, const TabParent* aTabParent2)
{
if (aTabParent1 == aTabParent2) {
return true;
}
if (!aTabParent1 != !aTabParent2) {
return false;
}
return aTabParent1->Manager() == aTabParent2->Manager();
}
StaticRefPtr<nsIContent> IMEStateManager::sContent;
StaticRefPtr<nsPresContext> IMEStateManager::sPresContext;
nsIWidget* IMEStateManager::sWidget = nullptr;
nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
StaticRefPtr<TabParent> IMEStateManager::sFocusedIMETabParent;
nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
InputContext::Origin IMEStateManager::sOrigin = InputContext::ORIGIN_MAIN;
bool IMEStateManager::sInstalledMenuKeyboardListener = false;
bool IMEStateManager::sIsGettingNewIMEState = false;
bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
bool IMEStateManager::sInputModeSupported = false;
bool IMEStateManager::sRemoteHasFocus = false;
// static
void
@ -163,6 +176,9 @@ IMEStateManager::Init()
&sInputModeSupported,
"dom.forms.inputmode",
false);
sOrigin = XRE_IsParentProcess() ? InputContext::ORIGIN_MAIN :
InputContext::ORIGIN_CONTENT;
}
// static
@ -222,7 +238,7 @@ IMEStateManager::StopIMEStateManagement()
// the rights to change input context.
if (sTextCompositions && sPresContext) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext);
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext, sActiveTabParent);
}
sActiveInputContextWidget = nullptr;
sPresContext = nullptr;
@ -304,7 +320,9 @@ IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
InputContext::Origin origin =
sActiveTabParent ? InputContext::ORIGIN_CONTENT : sOrigin;
SetIMEState(newState, nullptr, sWidget, action, origin);
}
sWidget = nullptr;
sContent = nullptr;
@ -359,7 +377,9 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
InputContext::Origin origin =
sActiveTabParent ? InputContext::ORIGIN_CONTENT : sOrigin;
SetIMEState(newState, nullptr, sWidget, action, origin);
}
sWidget = nullptr;
@ -436,14 +456,47 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
// If we're deactivating, we shouldn't commit composition forcibly because
// the user may want to continue the composition.
if (aPresContext) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget, sFocusedIMETabParent);
}
}
if (sActiveIMEContentObserver &&
(aPresContext || !sActiveIMEContentObserver->KeepAliveDuringDeactive()) &&
!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
DestroyIMEContentObserver();
if (sActiveIMEContentObserver) {
// If there is active IMEContentObserver, it means that focused content was
// in this process. So, if a tab parent gets focus, it means that the
// focused editor in this process is being blurred.
if (newTabParent) {
DestroyIMEContentObserver();
}
// If the process is being inactivated, then, IMEContentObserver should
// stop observing the contents unless native IME requests to keep
// composition even during deactivated.
else if (!aPresContext) {
if (!sActiveIMEContentObserver->KeepAliveDuringDeactive()) {
DestroyIMEContentObserver();
}
}
// Otherwise, i.e., new focused content is in this process, let's check
// whether the new focused content is already being managed by the
// active IME content observer.
else if (!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
DestroyIMEContentObserver();
}
} else {
// If there is no active IMEContentObserver, it means that focused content
// may be in another process.
// If focus is moving from current focused remote process to different
// process while the process has IME focus too, we need to notify IME of
// blur here because it may be too late the blur notification to reach
// this process especially when closing active window.
if (sFocusedIMETabParent &&
!IsSameProcess(sFocusedIMETabParent, newTabParent)) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" OnChangeFocusInternal(), notifying IME of blur of previous focused "
"remote process because it may be too late actual notification to "
"reach this process"));
NotifyIME(NOTIFY_IME_OF_BLUR, sFocusedIMEWidget, sFocusedIMETabParent);
}
}
if (!aPresContext) {
@ -453,11 +506,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
return NS_OK;
}
nsIContentParent* currentContentParent =
sActiveTabParent ? sActiveTabParent->Manager() : nullptr;
nsIContentParent* newContentParent =
newTabParent ? newTabParent->Manager() : nullptr;
if (sActiveTabParent && currentContentParent != newContentParent) {
if (sActiveTabParent && !IsSameProcess(sActiveTabParent, newTabParent)) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), notifying previous "
"focused child process of parent process or another child process "
@ -496,23 +545,26 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
setIMEState = sInstalledMenuKeyboardListener;
} else if (focusActuallyChanging) {
InputContext context = newWidget->GetInputContext();
if (context.mIMEState.mEnabled == IMEState::DISABLED) {
if (context.mIMEState.mEnabled == IMEState::DISABLED &&
context.mOrigin == InputContext::ORIGIN_CONTENT) {
setIMEState = false;
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), doesn't set IME "
"state because focused element (or document) is in a child process "
"and the IME state is already disabled"));
"and the IME state is already disabled by a remote process"));
} else {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), will disable IME "
"until new focused element (or document) in the child process "
"will get focus actually"));
}
} else {
// When focus is NOT changed actually, we shouldn't set IME state since
// that means that the window is being activated and the child process
// may have composition. Then, we shouldn't commit the composition with
// making IME state disabled.
} else if (newWidget->GetInputContext().mOrigin !=
InputContext::ORIGIN_CONTENT) {
// When focus is NOT changed actually, we shouldn't set IME state if
// current input context was set by a remote process since that means
// that the window is being activated and the child process may have
// composition. Then, we shouldn't commit the composition with making
// IME state disabled.
setIMEState = false;
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), doesn't set IME "
@ -537,7 +589,8 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
// Even if focus isn't changing actually, we should commit current
// composition here since the IME state is changing.
if (sPresContext && oldWidget && !focusActuallyChanging) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget,
sFocusedIMETabParent);
}
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
// If aContent isn't null or aContent is null but editable, somebody gets
@ -549,7 +602,8 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
}
// Update IME state for new focus widget
SetIMEState(newState, aContent, newWidget, aAction);
SetIMEState(newState, aContent, newWidget, aAction,
newTabParent ? InputContext::ORIGIN_CONTENT : sOrigin);
}
sActiveTabParent = newTabParent;
@ -700,7 +754,7 @@ IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
InputContextAction action(cause, InputContextAction::FOCUS_NOT_CHANGED);
IMEState newState = GetNewIMEState(aPresContext, aContent);
SetIMEState(newState, aContent, widget, action);
SetIMEState(newState, aContent, widget, action, sOrigin);
}
// static
@ -894,7 +948,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
if (updateIMEState) {
// commit current composition before modifying IME state.
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget, sFocusedIMETabParent);
if (NS_WARN_IF(widget->Destroyed())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during committing composition"));
@ -909,7 +963,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
if (updateIMEState) {
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::FOCUS_NOT_CHANGED);
SetIMEState(aNewIMEState, aContent, widget, action);
SetIMEState(aNewIMEState, aContent, widget, action, sOrigin);
if (NS_WARN_IF(widget->Destroyed())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during setting input context"));
@ -1069,22 +1123,25 @@ void
IMEStateManager::SetIMEState(const IMEState& aState,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction)
InputContextAction aAction,
InputContext::Origin aOrigin)
{
MOZ_LOG(sISMLog, LogLevel::Info,
("SetIMEState(aState={ mEnabled=%s, mOpen=%s }, "
"aContent=0x%p (TabParent=0x%p), aWidget=0x%p, aAction={ mCause=%s, "
"mFocusChange=%s })",
"mFocusChange=%s }, aOrigin=%s)",
GetIMEStateEnabledName(aState.mEnabled),
GetIMEStateSetOpenName(aState.mOpen), aContent,
TabParent::GetFrom(aContent), aWidget,
GetActionCauseName(aAction.mCause),
GetActionFocusChangeName(aAction.mFocusChange)));
GetActionFocusChangeName(aAction.mFocusChange),
ToChar(aOrigin)));
NS_ENSURE_TRUE_VOID(aWidget);
InputContext context;
context.mIMEState = aState;
context.mOrigin = aOrigin;
context.mMayBeIMEUnaware = context.mIMEState.IsEditable() &&
sCheckForIMEUnawareWebApps && MayBeIMEUnawareWebApp(aContent);
@ -1411,25 +1468,29 @@ IMEStateManager::OnCompositionEventDiscarded(
nsresult
IMEStateManager::NotifyIME(IMEMessage aMessage,
nsIWidget* aWidget,
bool aOriginIsRemote)
TabParent* aTabParent)
{
return IMEStateManager::NotifyIME(IMENotification(aMessage), aWidget,
aOriginIsRemote);
aTabParent);
}
// static
nsresult
IMEStateManager::NotifyIME(const IMENotification& aNotification,
nsIWidget* aWidget,
bool aOriginIsRemote)
TabParent* aTabParent)
{
MOZ_LOG(sISMLog, LogLevel::Info,
("NotifyIME(aNotification={ mMessage=%s }, "
"aWidget=0x%p, aOriginIsRemote=%s), sFocusedIMEWidget=0x%p, "
"sRemoteHasFocus=%s",
"aWidget=0x%p, aTabParent=0x%p), sFocusedIMEWidget=0x%p, "
"sActiveTabParent=0x%p, sFocusedIMETabParent=0x%p, "
"IsSameProcess(aTabParent, sActiveTabParent)=%s, "
"IsSameProcess(aTabParent, sFocusedIMETabParent)=%s",
ToChar(aNotification.mMessage), aWidget,
GetBoolName(aOriginIsRemote), sFocusedIMEWidget,
GetBoolName(sRemoteHasFocus)));
aTabParent, sFocusedIMEWidget, sActiveTabParent.get(),
sFocusedIMETabParent.get(),
GetBoolName(IsSameProcess(aTabParent, sActiveTabParent)),
GetBoolName(IsSameProcess(aTabParent, sFocusedIMETabParent))));
if (NS_WARN_IF(!aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
@ -1439,61 +1500,58 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
switch (aNotification.mMessage) {
case NOTIFY_IME_OF_FOCUS: {
// If focus notification comes from a remote process which already lost
// focus, we shouldn't accept the focus notification. Then, following
// notifications from the process will be ignored.
if (NS_WARN_IF(!IsSameProcess(aTabParent, sActiveTabParent))) {
MOZ_ASSERT(aTabParent,
"Why was the input context initialized for a remote process but "
"does this process get IME focus?");
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received focus notification is ignored "
"because input context was initialized for %s, perhaps, it came "
"from a busy remote process",
sActiveTabParent ? "another remote process" : "current process"));
return NS_OK;
}
// If there is pending blur notification for current focused IME,
// we should notify IME of blur by ourselves. Then, we should ignore
// following notifications coming from the process.
if (sFocusedIMEWidget) {
if (NS_WARN_IF(!sRemoteHasFocus && !aOriginIsRemote)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), although, this process is "
"getting IME focus but there was focused IME widget"));
} else {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), tries to notify IME of "
"blur first because remote process's blur notification hasn't "
"been received yet..."));
}
MOZ_ASSERT(sFocusedIMETabParent || aTabParent,
"This case shouldn't be caused by focus move in this process");
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
sFocusedIMEWidget = nullptr;
sRemoteHasFocus = false;
sFocusedIMETabParent = nullptr;
focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
}
sRemoteHasFocus = aOriginIsRemote;
sFocusedIMETabParent = aTabParent;
sFocusedIMEWidget = aWidget;
nsCOMPtr<nsIWidget> widget(aWidget);
return widget->NotifyIME(aNotification);
}
case NOTIFY_IME_OF_BLUR: {
if (!sRemoteHasFocus && aOriginIsRemote) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received blur notification "
"after another one has focus, nothing to do..."));
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received blur notification is ignored "
"because it's not from current focused IME process"));
return NS_OK;
}
if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
if (!sFocusedIMEWidget) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received blur "
"notification from this process but the remote has focus"));
return NS_OK;
}
if (!sFocusedIMEWidget && aOriginIsRemote) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received blur notification "
"but the remote has already lost focus"));
return NS_OK;
}
if (NS_WARN_IF(!sFocusedIMEWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received blur "
"notification but there is no focused IME widget"));
(" NotifyIME(), WARNING, received blur notification but there is "
"no focused IME widget"));
return NS_OK;
}
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received blur "
"notification but there is no focused IME widget"));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received blur notification is ignored "
"because it's not for current focused IME widget"));
return NS_OK;
}
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
sFocusedIMEWidget = nullptr;
sRemoteHasFocus = false;
sFocusedIMETabParent = nullptr;
return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
}
case NOTIFY_IME_OF_SELECTION_CHANGE:
@ -1501,30 +1559,22 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
case NOTIFY_IME_OF_POSITION_CHANGE:
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
if (!sRemoteHasFocus && aOriginIsRemote) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received content change "
"notification from the remote but it's already lost focus"));
return NS_OK;
}
if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received content "
"change notification from this process but the remote has already "
"gotten focus"));
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because it's not from current focused IME process"));
return NS_OK;
}
if (!sFocusedIMEWidget) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received content change "
"notification but there is no focused IME widget"));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because there is no focused IME widget"));
return NS_OK;
}
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received content "
"change notification for IME which has already lost focus, so, "
"nothing to do..."));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because it's not for current focused IME widget"));
return NS_OK;
}
nsCOMPtr<nsIWidget> widget(aWidget);
@ -1536,26 +1586,35 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
break;
}
RefPtr<TextComposition> composition;
if (sTextCompositions) {
composition = sTextCompositions->GetCompositionFor(aWidget);
if (!sTextCompositions) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), the request to IME is ignored because "
"there have been no compositions yet"));
return NS_OK;
}
bool isSynthesizedForTests =
composition && composition->IsSynthesizedForTests();
RefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(aWidget);
if (!composition) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), the request to IME is ignored because "
"there is no active composition"));
return NS_OK;
}
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), composition=0x%p, "
"composition->IsSynthesizedForTests()=%s",
composition.get(), GetBoolName(isSynthesizedForTests)));
if (!IsSameProcess(aTabParent, composition->GetTabParent())) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the request to IME is ignored because "
"it does not come from the remote process which has the composition "
"on aWidget"));
return NS_OK;
}
switch (aNotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:
return composition ?
composition->RequestToCommit(aWidget, false) : NS_OK;
return composition->RequestToCommit(aWidget, false);
case REQUEST_TO_CANCEL_COMPOSITION:
return composition ?
composition->RequestToCommit(aWidget, true) : NS_OK;
return composition->RequestToCommit(aWidget, true);
default:
MOZ_CRASH("Unsupported notification");
}
@ -1568,11 +1627,11 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
nsresult
IMEStateManager::NotifyIME(IMEMessage aMessage,
nsPresContext* aPresContext,
bool aOriginIsRemote)
TabParent* aTabParent)
{
MOZ_LOG(sISMLog, LogLevel::Info,
("NotifyIME(aMessage=%s, aPresContext=0x%p, aOriginIsRemote=%s)",
ToChar(aMessage), aPresContext, GetBoolName(aOriginIsRemote)));
("NotifyIME(aMessage=%s, aPresContext=0x%p, aTabParent=0x%p)",
ToChar(aMessage), aPresContext, aTabParent));
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
return NS_ERROR_INVALID_ARG;
@ -1585,7 +1644,7 @@ IMEStateManager::NotifyIME(IMEMessage aMessage,
"nsPresContext"));
return NS_ERROR_NOT_AVAILABLE;
}
return NotifyIME(aMessage, widget, aOriginIsRemote);
return NotifyIME(aMessage, widget, aTabParent);
}
// static

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

@ -58,6 +58,20 @@ public:
return sActiveTabParent.get();
}
/**
* DoesTabParentHaveIMEFocus() returns true when aTabParent has IME focus,
* i.e., the TabParent sent "focus" notification but not yet sends "blur".
* Note that this doesn't check if the remote processes are same because
* if another TabParent has focus, committing composition causes firing
* composition events in different TabParent. (Anyway, such case shouldn't
* occur.)
*/
static bool DoesTabParentHaveIMEFocus(const TabParent* aTabParent)
{
MOZ_ASSERT(aTabParent);
return sFocusedIMETabParent == aTabParent;
}
/**
* OnTabParentDestroying() is called when aTabParent is being destroyed.
*/
@ -224,13 +238,13 @@ public:
*/
static nsresult NotifyIME(const IMENotification& aNotification,
nsIWidget* aWidget,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsresult NotifyIME(IMEMessage aMessage,
nsIWidget* aWidget,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsresult NotifyIME(IMEMessage aMessage,
nsPresContext* aPresContext,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
nsIContent* aContent);
@ -248,7 +262,8 @@ protected:
static void SetIMEState(const IMEState &aState,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction);
InputContextAction aAction,
InputContext::Origin aOrigin);
static void SetInputContext(nsIWidget* aWidget,
const InputContext& aInputContext,
const InputContextAction& aAction);
@ -279,11 +294,10 @@ protected:
// sPresContext has gone, we need to clean up some IME state on the widget
// if the widget is available.
static nsIWidget* sWidget;
// sFocusedIMEWidget is, the widget which was sent to "focus" notification
// from IMEContentObserver and not yet sent "blur" notification.
// So, if this is not nullptr, the widget needs to receive "blur"
// notification.
// sFocusedIMETabParent is the tab parent, which send "focus" notification to
// sFocusedIMEWidget (and didn't yet sent "blur" notification).
static nsIWidget* sFocusedIMEWidget;
static StaticRefPtr<TabParent> sFocusedIMETabParent;
// sActiveInputContextWidget is the last widget whose SetInputContext() is
// called. This is important to reduce sync IPC cost with parent process.
// If IMEStateManager set input context to different widget, PuppetWidget can
@ -300,11 +314,13 @@ protected:
// something to cause committing or canceling the composition.
static TextCompositionArray* sTextCompositions;
// Origin type of current process.
static InputContext::Origin sOrigin;
static bool sInstalledMenuKeyboardListener;
static bool sIsGettingNewIMEState;
static bool sCheckForIMEUnawareWebApps;
static bool sInputModeSupported;
static bool sRemoteHasFocus;
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
{

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

@ -616,7 +616,7 @@ nsresult
TextComposition::NotifyIME(IMEMessage aMessage)
{
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
return IMEStateManager::NotifyIME(aMessage, mPresContext);
return IMEStateManager::NotifyIME(aMessage, mPresContext, mTabParent);
}
void

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

@ -75,6 +75,11 @@ public:
{
return mPresContext ? mPresContext->GetRootWidget() : nullptr;
}
// Returns the tab parent which has this composition in its remote process.
TabParent* GetTabParent() const
{
return mTabParent;
}
// Returns true if the composition is started with synthesized event which
// came from nsDOMWindowUtils.
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }

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

@ -3,7 +3,7 @@ var testGenerator = testSteps();
function* testSteps()
{
const name = this.window ? window.location.pathname :
"test_storage_manager_estimate.js";
"test_storage_manager_estimate.js";
const objectStoreName = "storagesManager";
const arraySize = 1e6;

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

@ -143,6 +143,7 @@ TabParent::TabParent(nsIContentParent* aManager,
uint32_t aChromeFlags)
: TabContext(aContext)
, mFrameElement(nullptr)
, mContentCache(*this)
, mRect(0, 0, 0, 0)
, mDimensions(0, 0)
, mOrientation(0)
@ -1745,7 +1746,7 @@ TabParent::RecvNotifyIMEFocus(const ContentCache& aContentCache,
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
IMEStateManager::NotifyIME(aIMENotification, widget, true);
IMEStateManager::NotifyIME(aIMENotification, widget, this);
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
*aRequests = widget->IMENotificationRequestsRef();
@ -1824,7 +1825,7 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
*aConsumedByIME = false;
return IPC_OK();
}
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, true);
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, this);
*aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
return IPC_OK();
}

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

@ -25,7 +25,8 @@ ADTSDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
ADTSDecoder::CreateStateMachine()
{
mReader = new MediaFormatReader(this, new ADTSDemuxer(mResource));
MediaDecoderReaderInit init(this);
mReader = new MediaFormatReader(init, new ADTSDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -339,45 +339,46 @@ DecoderTraits::CreateDecoder(MediaDecoderInit& aInit,
/* static */
MediaDecoderReader*
DecoderTraits::CreateReader(const MediaContainerType& aType,
AbstractMediaDecoder* aDecoder,
MediaResource* aResource)
const MediaDecoderReaderInit& aInit)
{
MOZ_ASSERT(NS_IsMainThread());
MediaDecoderReader* decoderReader = nullptr;
if (!aDecoder) {
if (!aInit.mDecoder) {
return decoderReader;
}
MediaResource* resource = aInit.mResource;
#ifdef MOZ_FMP4
if (MP4Decoder::IsSupportedType(aType,
/* DecoderDoctorDiagnostics* */ nullptr)) {
decoderReader = new MediaFormatReader(aDecoder, new MP4Demuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new MP4Demuxer(resource));
} else
#endif
if (MP3Decoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new MP3Demuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new MP3Demuxer(resource));
} else
if (ADTSDecoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new ADTSDemuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new ADTSDemuxer(resource));
} else
if (WaveDecoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new WAVDemuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new WAVDemuxer(resource));
} else
if (FlacDecoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new FlacDemuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new FlacDemuxer(resource));
} else
if (OggDecoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new OggDemuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new OggDemuxer(resource));
} else
#ifdef MOZ_ANDROID_OMX
if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
EnsureAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
decoderReader = new AndroidMediaReader(aDecoder, aType, aResource);
decoderReader = new AndroidMediaReader(aType, aInit);
} else
#endif
if (WebMDecoder::IsSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new WebMDemuxer(aResource));
decoderReader = new MediaFormatReader(aInit, new WebMDemuxer(resource));
}
return decoderReader;

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

@ -19,6 +19,7 @@ class ChannelMediaDecoder;
class DecoderDoctorDiagnostics;
class MediaContainerType;
struct MediaDecoderInit;
struct MediaDecoderReaderInit;
class MediaDecoderOwner;
class MediaDecoderReader;
class MediaResource;
@ -51,8 +52,7 @@ public:
// Create a reader for thew given MIME type aType. Returns null
// if we were unable to create the reader.
static MediaDecoderReader* CreateReader(const MediaContainerType& aType,
AbstractMediaDecoder* aDecoder,
MediaResource* aResource);
const MediaDecoderReaderInit& aInit);
// Returns true if MIME type aType is supported in video documents,
// or false otherwise. Not all platforms support all MIME types, and

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

@ -741,11 +741,63 @@ static int32_t GetMaxBlocks()
{
// We look up the cache size every time. This means dynamic changes
// to the pref are applied.
// Cache size is in KB
int32_t cacheSize = Preferences::GetInt("media.cache_size", 500*1024);
int64_t maxBlocks = static_cast<int64_t>(cacheSize)*1024/MediaCache::BLOCK_SIZE;
maxBlocks = std::max<int64_t>(maxBlocks, 1);
return int32_t(std::min<int64_t>(maxBlocks, INT32_MAX));
const uint32_t cacheSizeKb =
std::min(MediaPrefs::MediaCacheSizeKb(), uint32_t(INT32_MAX) * 2);
// Ensure we can divide BLOCK_SIZE by 1024.
static_assert(MediaCache::BLOCK_SIZE % 1024 == 0,
"BLOCK_SIZE should be a multiple of 1024");
// Ensure BLOCK_SIZE/1024 is at least 2.
static_assert(MediaCache::BLOCK_SIZE / 1024 >= 2,
"BLOCK_SIZE / 1024 should be at least 2");
// Ensure we can convert BLOCK_SIZE/1024 to a uint32_t without truncation.
static_assert(MediaCache::BLOCK_SIZE / 1024 <= int64_t(UINT32_MAX),
"BLOCK_SIZE / 1024 should be at most UINT32_MAX");
// Since BLOCK_SIZE is a strict multiple of 1024,
// cacheSizeKb * 1024 / BLOCK_SIZE == cacheSizeKb / (BLOCK_SIZE / 1024),
// but the latter formula avoids a potential overflow from `* 1024`.
// And because BLOCK_SIZE/1024 is at least 2, the maximum cache size
// INT32_MAX*2 will give a maxBlocks that can fit in an int32_t.
constexpr uint32_t blockSizeKb = uint32_t(MediaCache::BLOCK_SIZE / 1024);
const int32_t maxBlocks = int32_t(cacheSizeKb / blockSizeKb);
return std::max(maxBlocks, int32_t(1));
}
// Allowed range is whatever can be accessed with an int32_t block index.
static bool
IsOffsetAllowed(int64_t aOffset)
{
return aOffset < (int64_t(INT32_MAX) + 1) * MediaCache::BLOCK_SIZE &&
aOffset >= 0;
}
// Convert 64-bit offset to 32-bit block index.
// Assumes offset range-check was already done.
static int32_t
OffsetToBlockIndexUnchecked(int64_t aOffset)
{
// Still check for allowed range in debug builds, to catch out-of-range
// issues early during development.
MOZ_ASSERT(IsOffsetAllowed(aOffset));
return int32_t(aOffset / MediaCache::BLOCK_SIZE);
}
// Convert 64-bit offset to 32-bit block index. -1 if out of allowed range.
static int32_t
OffsetToBlockIndex(int64_t aOffset)
{
return IsOffsetAllowed(aOffset) ? OffsetToBlockIndexUnchecked(aOffset) : -1;
}
// Convert 64-bit offset to 32-bit offset inside a block.
// Will not fail (even if offset is outside allowed range), so there is no
// need to check for errors.
static int32_t
OffsetInBlock(int64_t aOffset)
{
// Still check for allowed range in debug builds, to catch out-of-range
// issues early during development.
MOZ_ASSERT(IsOffsetAllowed(aOffset));
return int32_t(aOffset % MediaCache::BLOCK_SIZE);
}
int32_t
@ -754,8 +806,11 @@ MediaCache::FindBlockForIncomingData(TimeStamp aNow,
{
mReentrantMonitor.AssertCurrentThreadIn();
int32_t blockIndex = FindReusableBlock(aNow, aStream,
aStream->mChannelOffset/BLOCK_SIZE, INT32_MAX);
int32_t blockIndex =
FindReusableBlock(aNow,
aStream,
OffsetToBlockIndexUnchecked(aStream->mChannelOffset),
INT32_MAX);
if (blockIndex < 0 || !IsBlockFree(blockIndex)) {
// The block returned is already allocated.
@ -784,7 +839,8 @@ MediaCache::BlockIsReusable(int32_t aBlockIndex)
for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
MediaCacheStream* stream = block->mOwners[i].mStream;
if (stream->mPinCount > 0 ||
stream->mStreamOffset/BLOCK_SIZE == block->mOwners[i].mStreamBlock) {
uint32_t(OffsetToBlockIndex(stream->mStreamOffset)) ==
block->mOwners[i].mStreamBlock) {
return false;
}
}
@ -1327,14 +1383,17 @@ MediaCache::Update()
if (enableReading) {
for (uint32_t j = 0; j < i; ++j) {
MediaCacheStream* other = mStreams[j];
if (other->mResourceID == stream->mResourceID &&
!other->mClosed && !other->mClient->IsSuspended() &&
other->mChannelOffset/BLOCK_SIZE == desiredOffset/BLOCK_SIZE) {
if (other->mResourceID == stream->mResourceID && !other->mClosed &&
!other->mClient->IsSuspended() &&
OffsetToBlockIndexUnchecked(other->mChannelOffset) ==
OffsetToBlockIndexUnchecked(desiredOffset)) {
// This block is already going to be read by the other stream.
// So don't try to read it from this stream as well.
enableReading = false;
LOG("Stream %p waiting on same block (%" PRId64 ") from stream %p",
stream, desiredOffset/BLOCK_SIZE, other);
LOG("Stream %p waiting on same block (%" PRId32 ") from stream %p",
stream,
OffsetToBlockIndexUnchecked(desiredOffset),
other);
break;
}
}
@ -1347,7 +1406,8 @@ MediaCache::Update()
// Round seek offset down to the start of the block. This is essential
// because we don't want to think we have part of a block already
// in mPartialBlockBuffer.
stream->mChannelOffset = (desiredOffset/BLOCK_SIZE)*BLOCK_SIZE;
stream->mChannelOffset =
OffsetToBlockIndexUnchecked(desiredOffset) * BLOCK_SIZE;
actions[i] = stream->mCacheSuspended ? SEEK_AND_RESUME : SEEK;
} else if (enableReading && stream->mCacheSuspended) {
actions[i] = RESUME;
@ -1550,7 +1610,8 @@ MediaCache::AllocateAndWriteBlock(
{
mReentrantMonitor.AssertCurrentThreadIn();
int32_t streamBlockIndex = aStream->mChannelOffset/BLOCK_SIZE;
int32_t streamBlockIndex =
OffsetToBlockIndexUnchecked(aStream->mChannelOffset);
// Remove all cached copies of this block
ResourceStreamIterator iter(this, aStream->mResourceID);
@ -1749,10 +1810,16 @@ MediaCache::NoteSeek(MediaCacheStream* aStream, int64_t aOldOffset)
// We seeked forward. Convert blocks from readahead to played.
// Any readahead block that intersects the seeked-over range must
// be converted.
int32_t blockIndex = aOldOffset/BLOCK_SIZE;
int32_t blockIndex = OffsetToBlockIndex(aOldOffset);
if (blockIndex < 0) {
return;
}
int32_t endIndex =
std::min<int64_t>((aStream->mStreamOffset + BLOCK_SIZE - 1)/BLOCK_SIZE,
aStream->mBlocks.Length());
std::min(OffsetToBlockIndex(aStream->mStreamOffset + (BLOCK_SIZE - 1)),
int32_t(aStream->mBlocks.Length()));
if (endIndex < 0) {
return;
}
TimeStamp now = TimeStamp::Now();
while (blockIndex < endIndex) {
int32_t cacheBlockIndex = aStream->mBlocks[blockIndex];
@ -1769,10 +1836,16 @@ MediaCache::NoteSeek(MediaCacheStream* aStream, int64_t aOldOffset)
// Any played block that is entirely after the start of the seeked-over
// range must be converted.
int32_t blockIndex =
(aStream->mStreamOffset + BLOCK_SIZE - 1)/BLOCK_SIZE;
OffsetToBlockIndex(aStream->mStreamOffset + (BLOCK_SIZE - 1));
if (blockIndex < 0) {
return;
}
int32_t endIndex =
std::min<int64_t>((aOldOffset + BLOCK_SIZE - 1)/BLOCK_SIZE,
aStream->mBlocks.Length());
std::min(OffsetToBlockIndex(aOldOffset + (BLOCK_SIZE - 1)),
int32_t(aStream->mBlocks.Length()));
if (endIndex < 0) {
return;
}
while (blockIndex < endIndex) {
MOZ_ASSERT(endIndex > 0);
int32_t cacheBlockIndex = aStream->mBlocks[endIndex - 1];
@ -1860,7 +1933,7 @@ MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData,
// We process the data one block (or part of a block) at a time
while (size > 0) {
uint32_t blockIndex = mChannelOffset/BLOCK_SIZE;
uint32_t blockIndex = OffsetToBlockIndexUnchecked(mChannelOffset);
int32_t blockOffset = int32_t(mChannelOffset - blockIndex*BLOCK_SIZE);
int32_t chunkSize = std::min<int64_t>(BLOCK_SIZE - blockOffset, size);
@ -1910,7 +1983,7 @@ MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll,
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
int32_t blockOffset = int32_t(mChannelOffset%BLOCK_SIZE);
int32_t blockOffset = OffsetInBlock(mChannelOffset);
if (blockOffset > 0) {
LOG("Stream %p writing partial block: [%d] bytes; "
"mStreamOffset [%" PRId64 "] mChannelOffset[%"
@ -2155,13 +2228,15 @@ int64_t
MediaCacheStream::GetCachedDataEndInternal(int64_t aOffset)
{
mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
uint32_t startBlockIndex = aOffset/BLOCK_SIZE;
uint32_t blockIndex = startBlockIndex;
while (blockIndex < mBlocks.Length() && mBlocks[blockIndex] != -1) {
int32_t blockIndex = OffsetToBlockIndex(aOffset);
if (blockIndex < 0) {
return aOffset;
}
while (size_t(blockIndex) < mBlocks.Length() && mBlocks[blockIndex] != -1) {
++blockIndex;
}
int64_t result = blockIndex*BLOCK_SIZE;
if (blockIndex == mChannelOffset/BLOCK_SIZE) {
if (blockIndex == OffsetToBlockIndexUnchecked(mChannelOffset)) {
// The block containing mChannelOffset may be partially read but not
// yet committed to the main cache
result = mChannelOffset;
@ -2181,8 +2256,11 @@ MediaCacheStream::GetNextCachedDataInternal(int64_t aOffset)
if (aOffset == mStreamLength)
return -1;
uint32_t startBlockIndex = aOffset/BLOCK_SIZE;
uint32_t channelBlockIndex = mChannelOffset/BLOCK_SIZE;
int32_t startBlockIndex = OffsetToBlockIndex(aOffset);
if (startBlockIndex < 0) {
return -1;
}
int32_t channelBlockIndex = OffsetToBlockIndexUnchecked(mChannelOffset);
if (startBlockIndex == channelBlockIndex &&
aOffset < mChannelOffset) {
@ -2192,7 +2270,7 @@ MediaCacheStream::GetNextCachedDataInternal(int64_t aOffset)
return aOffset;
}
if (startBlockIndex >= mBlocks.Length())
if (size_t(startBlockIndex) >= mBlocks.Length())
return -1;
// Is the current block cached?
@ -2200,18 +2278,18 @@ MediaCacheStream::GetNextCachedDataInternal(int64_t aOffset)
return aOffset;
// Count the number of uncached blocks
bool hasPartialBlock = (mChannelOffset % BLOCK_SIZE) != 0;
uint32_t blockIndex = startBlockIndex + 1;
bool hasPartialBlock = OffsetInBlock(mChannelOffset) != 0;
int32_t blockIndex = startBlockIndex + 1;
while (true) {
if ((hasPartialBlock && blockIndex == channelBlockIndex) ||
(blockIndex < mBlocks.Length() && mBlocks[blockIndex] != -1)) {
(size_t(blockIndex) < mBlocks.Length() && mBlocks[blockIndex] != -1)) {
// We at the incoming channel block, which has has data in it,
// or are we at a cached block. Return index of block start.
return blockIndex * BLOCK_SIZE;
}
// No more cached blocks?
if (blockIndex >= mBlocks.Length())
if (size_t(blockIndex) >= mBlocks.Length())
return -1;
++blockIndex;
@ -2270,8 +2348,9 @@ MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset)
return NS_ERROR_FAILURE;
}
if (newOffset < 0)
if (!IsOffsetAllowed(newOffset)) {
return NS_ERROR_FAILURE;
}
mStreamOffset = newOffset;
LOG("Stream %p Seek to %" PRId64, this, mStreamOffset);
@ -2316,7 +2395,10 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
uint32_t count = 0;
// Read one block (or part of a block) at a time
while (count < aCount) {
uint32_t streamBlock = uint32_t(streamOffset/BLOCK_SIZE);
int32_t streamBlock = OffsetToBlockIndex(streamOffset);
if (streamBlock < 0) {
break;
}
uint32_t offsetInStreamBlock = uint32_t(streamOffset - streamBlock*BLOCK_SIZE);
int64_t size = std::min<int64_t>(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
@ -2332,7 +2414,8 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
size = std::min(size, int64_t(INT32_MAX));
}
int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1;
int32_t cacheBlock =
size_t(streamBlock) < mBlocks.Length() ? mBlocks[streamBlock] : -1;
if (cacheBlock < 0) {
// We don't have a complete cached block here.
@ -2349,7 +2432,8 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
MediaCacheStream* streamWithPartialBlock = nullptr;
MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
if (uint32_t(stream->mChannelOffset/BLOCK_SIZE) == streamBlock &&
if (OffsetToBlockIndexUnchecked(stream->mChannelOffset) ==
streamBlock &&
streamOffset < stream->mChannelOffset) {
streamWithPartialBlock = stream;
break;
@ -2438,7 +2522,10 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
// after calling |mMediaCache->ReadCacheFile|.
return NS_ERROR_FAILURE;
}
uint32_t streamBlock = uint32_t(streamOffset/BLOCK_SIZE);
int32_t streamBlock = OffsetToBlockIndex(streamOffset);
if (streamBlock < 0) {
break;
}
uint32_t offsetInStreamBlock =
uint32_t(streamOffset - streamBlock*BLOCK_SIZE);
int64_t size = std::min<int64_t>(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
@ -2455,8 +2542,9 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
}
int32_t bytes;
uint32_t channelBlock = uint32_t(mChannelOffset/BLOCK_SIZE);
int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1;
int32_t channelBlock = OffsetToBlockIndexUnchecked(mChannelOffset);
int32_t cacheBlock =
size_t(streamBlock) < mBlocks.Length() ? mBlocks[streamBlock] : -1;
if (channelBlock == streamBlock && streamOffset < mChannelOffset) {
// We can just use the data in mPartialBlockBuffer. In fact we should
// use it rather than waiting for the block to fill and land in

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

@ -68,10 +68,9 @@ public:
size_t mSize;
};
MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder,
MediaResource* aResource)
MediaDecoderReader::MediaDecoderReader(const MediaDecoderReaderInit& aInit)
: mAudioCompactor(mAudioQueue)
, mDecoder(aDecoder)
, mDecoder(aInit.mDecoder)
, mTaskQueue(new TaskQueue(
GetMediaThreadPool(MediaThreadType::PLAYBACK),
"MediaDecoderReader::mTaskQueue",
@ -82,7 +81,7 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder,
, mIgnoreAudioOutputFormat(false)
, mHitAudioDecodeError(false)
, mShutdown(false)
, mResource(aResource)
, mResource(aInit.mResource)
{
MOZ_COUNT_CTOR(MediaDecoderReader);
MOZ_ASSERT(NS_IsMainThread());

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

@ -26,6 +26,7 @@ namespace mozilla {
class CDMProxy;
class MediaDecoderReader;
class TaskQueue;
class VideoFrameContainer;
struct WaitForDataRejectValue
{
@ -61,6 +62,18 @@ struct MetadataHolder
UniquePtr<MetadataTags> mTags;
};
struct MOZ_STACK_CLASS MediaDecoderReaderInit
{
AbstractMediaDecoder* const mDecoder;
MediaResource* mResource = nullptr;
VideoFrameContainer* mVideoFrameContainer = nullptr;
explicit MediaDecoderReaderInit(AbstractMediaDecoder* aDecoder)
: mDecoder(aDecoder)
{
}
};
// Encapsulates the decoding and reading of media data. Reading can either
// synchronous and done on the calling "decode" thread, or asynchronous and
// performed on a background thread, with the result being returned by
@ -97,8 +110,7 @@ public:
// The caller must ensure that Shutdown() is called before aDecoder is
// destroyed.
explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder,
MediaResource* aResource = nullptr);
explicit MediaDecoderReader(const MediaDecoderReaderInit& aInit);
// Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
// on failure.

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

@ -1094,10 +1094,9 @@ MediaFormatReader::DemuxerProxy::NotifyDataArrived()
});
}
MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
MediaDataDemuxer* aDemuxer,
VideoFrameContainer* aVideoFrameContainer)
: MediaDecoderReader(aDecoder)
MediaFormatReader::MediaFormatReader(const MediaDecoderReaderInit& aInit,
MediaDataDemuxer* aDemuxer)
: MediaDecoderReader(aInit)
, mAudio(this, MediaData::AUDIO_DATA,
MediaPrefs::MaxAudioDecodeError())
, mVideo(this, MediaData::VIDEO_DATA,
@ -1110,17 +1109,17 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
, mInitDone(false)
, mTrackDemuxersMayBlock(false)
, mSeekScheduled(false)
, mVideoFrameContainer(aVideoFrameContainer)
, mVideoFrameContainer(aInit.mVideoFrameContainer)
, mDecoderFactory(new DecoderFactory(this))
, mShutdownPromisePool(new ShutdownPromisePool())
{
MOZ_ASSERT(aDemuxer);
MOZ_COUNT_CTOR(MediaFormatReader);
if (aDecoder && aDecoder->CompositorUpdatedEvent()) {
mCompositorUpdatedListener =
aDecoder->CompositorUpdatedEvent()->Connect(
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
AbstractMediaDecoder* decoder = aInit.mDecoder;
if (decoder && decoder->CompositorUpdatedEvent()) {
mCompositorUpdatedListener = decoder->CompositorUpdatedEvent()->Connect(
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
}
mOnTrackWaitingForKeyListener = OnTrackWaitingForKey().Connect(
mTaskQueue, this, &MediaFormatReader::NotifyWaitingForKey);

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

@ -29,9 +29,7 @@ class MediaFormatReader final : public MediaDecoderReader
typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> NotifyDataArrivedPromise;
public:
MediaFormatReader(AbstractMediaDecoder* aDecoder,
MediaDataDemuxer* aDemuxer,
VideoFrameContainer* aVideoFrameContainer = nullptr);
MediaFormatReader(const MediaDecoderReaderInit& aInit, MediaDataDemuxer* aDemuxer);
virtual ~MediaFormatReader();

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

@ -87,6 +87,7 @@ private:
// This is where DECL_MEDIA_PREF for each of the preferences should go.
// Cache sizes.
DECL_MEDIA_PREF("media.cache_size", MediaCacheSizeKb, uint32_t, 512000);
DECL_MEDIA_PREF("media.memory_cache_max_size", MediaMemoryCacheMaxSize, uint32_t, 8192);
DECL_MEDIA_PREF("media.memory_caches_combined_limit_kb", MediaMemoryCachesCombinedLimitKb, uint32_t, 524288);
DECL_MEDIA_PREF("media.memory_caches_combined_limit_pc_sysmem",

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

@ -19,7 +19,9 @@ AndroidMediaDecoder::AndroidMediaDecoder(MediaDecoderInit& aInit,
MediaDecoderStateMachine* AndroidMediaDecoder::CreateStateMachine()
{
mReader = new AndroidMediaReader(this, mType, mResource);
MediaDecoderReaderInit init(this);
init.mResource = mResource;
mReader = new AndroidMediaReader(mType, init);
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -25,10 +25,9 @@ using namespace mozilla::media;
typedef mozilla::layers::Image Image;
typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage;
AndroidMediaReader::AndroidMediaReader(AbstractMediaDecoder *aDecoder,
const MediaContainerType& aContainerType,
MediaResource* aResource) :
MediaDecoderReader(aDecoder, aResource),
AndroidMediaReader::AndroidMediaReader(const MediaContainerType& aContainerType,
const MediaDecoderReaderInit& aInit) :
MediaDecoderReader(aInit),
mType(aContainerType),
mPlugin(nullptr),
mHasAudio(false),

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

@ -37,9 +37,8 @@ class AndroidMediaReader : public MediaDecoderReader
MozPromiseHolder<MediaDecoderReader::SeekPromise> mSeekPromise;
MozPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mSeekRequest;
public:
AndroidMediaReader(AbstractMediaDecoder* aDecoder,
const MediaContainerType& aContainerType,
MediaResource* aResource);
AndroidMediaReader(const MediaContainerType& aContainerType,
const MediaDecoderReaderInit& aInit);
nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
TrackInfo::kVideoTrack)) override;

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

@ -26,7 +26,8 @@ FlacDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
FlacDecoder::CreateStateMachine()
{
mReader = new MediaFormatReader(this, new FlacDemuxer(mResource));
MediaDecoderReaderInit init(this);
mReader = new MediaFormatReader(init, new FlacDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -32,9 +32,9 @@ MP4Decoder::MP4Decoder(MediaDecoderInit& aInit)
MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
{
mReader = new MediaFormatReader(
this, new MP4Demuxer(mResource), GetVideoFrameContainer());
MediaDecoderReaderInit init(this);
init.mVideoFrameContainer = GetVideoFrameContainer();
mReader = new MediaFormatReader(init, new MP4Demuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -520,7 +520,8 @@ MP4TrackDemuxer::GetSamples(int32_t aNumSamples)
}
for (const auto& sample : samples->mSamples) {
// Collect telemetry from h264 Annex B SPS.
if (mNeedSPSForTelemetry) {
if (mNeedSPSForTelemetry && mIsH264 &&
mp4_demuxer::AnnexB::IsAVCC(sample)) {
RefPtr<MediaByteBuffer> extradata =
mp4_demuxer::H264::ExtractExtraData(sample);
if (mp4_demuxer::H264::HasSPS(extradata)) {

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

@ -28,10 +28,10 @@ HLSDecoder::CreateStateMachine()
MOZ_ASSERT(resource);
auto resourceWrapper = static_cast<HLSResource*>(resource)->GetResourceWrapper();
MOZ_ASSERT(resourceWrapper);
MediaDecoderReaderInit init(this);
init.mVideoFrameContainer = GetVideoFrameContainer();
mReader =
new MediaFormatReader(this,
new HLSDemuxer(resourceWrapper->GetPlayerId()),
GetVideoFrameContainer());
new MediaFormatReader(init, new HLSDemuxer(resourceWrapper->GetPlayerId()));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -39,7 +39,9 @@ MediaSourceDecoder::CreateStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
mDemuxer = new MediaSourceDemuxer(AbstractMainThread());
mReader = new MediaFormatReader(this, mDemuxer, GetVideoFrameContainer());
MediaDecoderReaderInit init(this);
init.mVideoFrameContainer = GetVideoFrameContainer();
mReader = new MediaFormatReader(init, mDemuxer);
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -26,7 +26,8 @@ MP3Decoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
MP3Decoder::CreateStateMachine() {
mReader = new MediaFormatReader(this, new MP3Demuxer(mResource));
MediaDecoderReaderInit init(this);
mReader = new MediaFormatReader(init, new MP3Demuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -16,7 +16,9 @@ namespace mozilla {
MediaDecoderStateMachine* OggDecoder::CreateStateMachine()
{
RefPtr<OggDemuxer> demuxer = new OggDemuxer(mResource);
mReader = new MediaFormatReader(this, demuxer, GetVideoFrameContainer());
MediaDecoderReaderInit init(this);
init.mVideoFrameContainer = GetVideoFrameContainer();
mReader = new MediaFormatReader(init, demuxer);
demuxer->SetChainingEvents(&mReader->TimedMetadataProducer(),
&mReader->MediaNotSeekableProducer());
return new MediaDecoderStateMachine(this, mReader);

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

@ -22,7 +22,8 @@ WaveDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
WaveDecoder::CreateStateMachine()
{
mReader = new MediaFormatReader(this, new WAVDemuxer(mResource));
MediaDecoderReaderInit init(this);
mReader = new MediaFormatReader(init, new WAVDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -193,8 +193,9 @@ MediaDecodeTask::CreateReader()
// If you change this list to add support for new decoders, please consider
// updating HTMLMediaElement::CreateDecoder as well.
mDecoderReader =
DecoderTraits::CreateReader(mContainerType, mBufferDecoder, resource);
MediaDecoderReaderInit init(mBufferDecoder);
init.mResource = resource;
mDecoderReader = DecoderTraits::CreateReader(mContainerType, init);
if (!mDecoderReader) {
return false;

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

@ -18,8 +18,9 @@ namespace mozilla {
MediaDecoderStateMachine* WebMDecoder::CreateStateMachine()
{
mReader = new MediaFormatReader(
this, new WebMDemuxer(mResource), GetVideoFrameContainer());
MediaDecoderReaderInit init(this);
init.mVideoFrameContainer = GetVideoFrameContainer();
mReader = new MediaFormatReader(init, new WebMDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -2881,11 +2881,7 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
}
nsAutoCString sourceMapURL;
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), sourceMapURL);
if (NS_FAILED(rv)) {
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL);
}
if (NS_SUCCEEDED(rv)) {
if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
aRequest->mHasSourceMapURL = true;
aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL);
}

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

@ -24,4 +24,11 @@ interface StyleSheet {
readonly attribute MediaList media;
[Pure]
attribute boolean disabled;
// If a SourceMap or X-SourceMap response header is seen, this is
// the value. If both are seen, SourceMap is preferred. If neither
// is seen, this will be an empty string. Because this relies on
// the HTTP response, it can change if checked before the response
// is available -- which is why it is not [Constant].
[ChromeOnly, Pure]
readonly attribute DOMString sourceMapURL;
};

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

@ -1,3 +1,4 @@
/* global processLDAPValues */
/* -*- tab-width: 4; indent-tabs-mode: nil; js-indent-level: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@ -14,15 +15,15 @@ var gVersion;
var gIsUTF8;
function getPrefBranch() {
var prefService = Components.classes[PrefServiceContractID]
.getService(nsIPrefService);
.getService(nsIPrefService);
return prefService.getBranch(null);
}
function pref(prefName, value) {
try {
try {
var prefBranch = getPrefBranch();
if (typeof value == "string") {
@ -31,24 +32,21 @@ function pref(prefName, value) {
return;
}
prefBranch.setCharPref(prefName, value);
}
else if (typeof value == "number") {
} else if (typeof value == "number") {
prefBranch.setIntPref(prefName, value);
}
else if (typeof value == "boolean") {
} else if (typeof value == "boolean") {
prefBranch.setBoolPref(prefName, value);
}
}
catch(e) {
} catch (e) {
displayError("pref", e);
}
}
function defaultPref(prefName, value) {
try {
var prefService = Components.classes[PrefServiceContractID]
.getService(nsIPrefService);
.getService(nsIPrefService);
var prefBranch = prefService.getDefaultBranch(null);
if (typeof value == "string") {
if (gIsUTF8) {
@ -56,32 +54,28 @@ function defaultPref(prefName, value) {
return;
}
prefBranch.setCharPref(prefName, value);
}
else if (typeof value == "number") {
} else if (typeof value == "number") {
prefBranch.setIntPref(prefName, value);
}
else if (typeof value == "boolean") {
} else if (typeof value == "boolean") {
prefBranch.setBoolPref(prefName, value);
}
}
catch(e) {
} catch (e) {
displayError("defaultPref", e);
}
}
function lockPref(prefName, value) {
try {
var prefBranch = getPrefBranch();
if (prefBranch.prefIsLocked(prefName))
prefBranch.unlockPref(prefName);
defaultPref(prefName, value);
prefBranch.lockPref(prefName);
}
catch(e) {
} catch (e) {
displayError("lockPref", e);
}
}
@ -92,37 +86,36 @@ function unlockPref(prefName) {
var prefBranch = getPrefBranch();
prefBranch.unlockPref(prefName);
}
catch(e) {
} catch (e) {
displayError("unlockPref", e);
}
}
function getPref(prefName) {
try {
var prefBranch = getPrefBranch();
switch (prefBranch.getPrefType(prefName)) {
case prefBranch.PREF_STRING:
if (gIsUTF8) {
return prefBranch.getStringPref(prefName);
}
return prefBranch.getCharPref(prefName);
case prefBranch.PREF_INT:
return prefBranch.getIntPref(prefName);
case prefBranch.PREF_BOOL:
return prefBranch.getBoolPref(prefName);
default:
return null;
}
}
catch(e) {
} catch (e) {
displayError("getPref", e);
}
return undefined;
}
function clearPref(prefName) {
@ -130,10 +123,9 @@ function clearPref(prefName) {
try {
var prefBranch = getPrefBranch();
prefBranch.clearUserPref(prefName);
} catch (e) {
}
catch(e) {
}
}
function setLDAPVersion(version) {
@ -142,7 +134,7 @@ function setLDAPVersion(version) {
function getLDAPAttributes(host, base, filter, attribs, isSecure) {
try {
var urlSpec = "ldap" + (isSecure ? "s" : "") + "://" + host + (isSecure ? ":636" : "") + "/" + base + "?" + attribs + "?sub?" +
filter;
@ -157,10 +149,9 @@ function getLDAPAttributes(host, base, filter, attribs, isSecure) {
// default to LDAP v3
if (!gVersion)
gVersion = Components.interfaces.nsILDAPConnection.VERSION3
// user supplied method
// user supplied method
processLDAPValues(ldapquery.getQueryResults(url, gVersion));
}
catch(e) {
} catch (e) {
displayError("getLDAPAttibutes", e);
}
}
@ -170,24 +161,24 @@ function getLDAPValue(str, key) {
try {
if (str == null || key == null)
return null;
var search_key = "\n" + key + "=";
var start_pos = str.indexOf(search_key);
if (start_pos == -1)
return null;
start_pos += search_key.length;
var end_pos = str.indexOf("\n", start_pos);
if (end_pos == -1)
end_pos = str.length;
return str.substring(start_pos, end_pos);
}
catch(e) {
} catch (e) {
displayError("getLDAPValue", e);
}
return undefined;
}
function displayError(funcname, message) {
@ -202,8 +193,7 @@ function displayError(funcname, message) {
var title = bundle.GetStringFromName("autoConfigTitle");
var msg = bundle.formatStringFromName("autoConfigMsg", [funcname], 1);
promptService.alert(null, title, msg + " " + message);
}
catch(e) { }
} catch (e) { }
}
function getenv(name) {
@ -211,9 +201,8 @@ function getenv(name) {
var environment = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
return environment.get(name);
}
catch(e) {
} catch (e) {
displayError("getEnvironment", e);
}
return undefined;
}

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"plugin:mozilla/xpcshell-test"
]
};

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

@ -1,3 +1,4 @@
/* global pref */
pref("general.config.filename", "autoconfig.cfg");
pref("general.config.vendor", "autoconfig");
pref("general.config.obscure_value", 0);

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

@ -3,14 +3,16 @@
var {classes: Cc, interfaces: Ci, results: Cr} = Components;
/* eslint no-unsafe-finally: "off"*/
/* Turning off this rule to allow control flow operations in finally block
* http://eslint.org/docs/rules/no-unsafe-finally */
function run_test() {
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
let obsvc = Cc['@mozilla.org/observer-service;1'].
let obsvc = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let ps = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
let defaultPrefs = ps.getDefaultBranch(null);
let prefs = ps.getBranch(null);
let greD = dirSvc.get("GreD", Ci.nsIFile);
@ -53,14 +55,14 @@ function run_test() {
let autoConfigCfg = testDir.clone();
autoConfigCfg.append(test.filename);
autoConfigCfg.copyTo(greD, "autoconfig.cfg");
obsvc.notifyObservers(ps, "prefservice:before-read-userprefs");
for (let prefName in test.prefs) {
do_check_eq(test.prefs[prefName],
prefs.getStringPref(prefName));
}
ps.resetPrefs();
// Make sure pref values are reset.
for (let prefName in test.prefs) {
@ -94,4 +96,3 @@ function run_test() {
ps.resetPrefs();
}
}

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

@ -27,7 +27,7 @@ class GPUChild;
// GPUProcessHosts are allocated and managed by GPUProcessManager. For all
// intents and purposes it is a singleton, though more than one may be allocated
// at a time due to its shutdown being asynchronous.
class GPUProcessHost final : public ipc::GeckoChildProcessHost
class GPUProcessHost final : public mozilla::ipc::GeckoChildProcessHost
{
friend class GPUChild;
@ -121,7 +121,7 @@ private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
Listener* mListener;
ipc::TaskFactory<GPUProcessHost> mTaskFactory;
mozilla::ipc::TaskFactory<GPUProcessHost> mTaskFactory;
enum class LaunchPhase {
Unlaunched,

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

@ -99,10 +99,10 @@ public:
bool CreateContentBridges(
base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
mozilla::ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
nsTArray<uint32_t>* aNamespaces);
// This returns a reference to the APZCTreeManager to which
@ -185,13 +185,13 @@ private:
void OnXPCOMShutdown();
bool CreateContentCompositorManager(base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
bool CreateContentImageBridge(base::ProcessId aOtherProcess,
ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
bool CreateContentVRManager(base::ProcessId aOtherProcess,
ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
void CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndPoint);
mozilla::ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndPoint);
// Called from RemoteCompositorSession. We track remote sessions so we can
// notify their owning widgets that the session must be restarted.
@ -258,7 +258,7 @@ private:
bool mDecodeVideoOnGpuProcess = true;
RefPtr<Observer> mObserver;
ipc::TaskFactory<GPUProcessManager> mTaskFactory;
mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory;
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
uint32_t mNextNamespace;
uint32_t mIdNamespace;

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

@ -72,13 +72,6 @@ UTCToLocalStandardOffsetSeconds()
using js::SecondsPerHour;
using js::SecondsPerMinute;
#if defined(XP_WIN)
// Windows doesn't follow POSIX: updates to the TZ environment variable are
// not reflected immediately on that platform as they are on other systems
// without this call.
_tzset();
#endif
// Get the current time.
time_t currentMaybeWithDST = time(nullptr);
if (currentMaybeWithDST == time_t(-1))
@ -180,13 +173,6 @@ js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds)
MOZ_ASSERT(utcSeconds >= 0);
MOZ_ASSERT(utcSeconds <= MaxUnixTimeT);
#if defined(XP_WIN)
// Windows does not follow POSIX. Updates to the TZ environment variable
// are not reflected immediately on that platform as they are on UNIX
// systems without this call.
_tzset();
#endif
struct tm tm;
if (!ComputeLocalTime(static_cast<time_t>(utcSeconds), &tm))
return 0;

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

@ -4278,7 +4278,8 @@ ConnectAnonymousTreeDescendants(nsIContent* aParent,
}
}
void SetNativeAnonymousBitOnDescendants(nsIContent *aRoot)
static void
SetNativeAnonymousBitOnDescendants(nsIContent* aRoot)
{
for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
@ -5898,7 +5899,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
}
}
bool isGeneratedContent = ((aFlags & ITEM_IS_GENERATED_CONTENT) != 0);
const bool isGeneratedContent = !!(aFlags & ITEM_IS_GENERATED_CONTENT);
// Pre-check for display "none" - if we find that, don't create
// any frame at all
@ -7342,7 +7343,8 @@ nsCSSFrameConstructor::CreateNeededFrames(
}
}
void nsCSSFrameConstructor::CreateNeededFrames()
void
nsCSSFrameConstructor::CreateNeededFrames()
{
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Someone forgot a script blocker");
@ -7352,7 +7354,8 @@ void nsCSSFrameConstructor::CreateNeededFrames()
"root element should not have frame created lazily");
if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
BeginUpdate();
TreeMatchContext treeMatchContext(mDocument, TreeMatchContext::ForFrameConstruction);
TreeMatchContext treeMatchContext(
mDocument, TreeMatchContext::ForFrameConstruction);
treeMatchContext.InitAncestors(rootElement);
CreateNeededFrames(rootElement, treeMatchContext);
EndUpdate();
@ -7949,8 +7952,6 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
NS_PRECONDITION(aStartChild, "must always pass a child");
// XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
// the :empty pseudo-class?
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
@ -7966,9 +7967,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
}
}
}
#endif
#ifdef DEBUG
for (nsIContent* child = aStartChild;
child != aEndChild;
child = child->GetNextSibling()) {
@ -8010,45 +8009,39 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
// If we have a null parent, then this must be the document element being
// inserted, or some other child of the document in the DOM (might be a PI,
// say).
if (! aContainer) {
if (!aContainer) {
NS_ASSERTION(isSingleInsert,
"root node insertion should be a single insertion");
Element *docElement = mDocument->GetRootElement();
Element* docElement = mDocument->GetRootElement();
if (aStartChild != docElement) {
// Not the root element; just bail out
return;
}
NS_PRECONDITION(nullptr == mRootElementFrame,
"root element frame already created");
NS_PRECONDITION(!mRootElementFrame, "root element frame already created");
// Create frames for the document element and its child elements
nsIFrame* docElementFrame =
ConstructDocElementFrame(docElement, aFrameState);
if (docElementFrame) {
if (ConstructDocElementFrame(docElement, aFrameState)) {
InvalidateCanvasIfNeeded(mPresShell, aStartChild);
#ifdef DEBUG
if (gReallyNoisyContentUpdates) {
printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
"model:\n");
docElementFrame->List(stdout, 0);
mRootElementFrame->List(stdout, 0);
}
#endif
}
if (aFrameState) {
// Restore frame state for the root scroll frame if there is one
nsIFrame* rootScrollFrame = mPresShell->GetRootScrollFrame();
if (rootScrollFrame) {
if (nsIFrame* rootScrollFrame = mPresShell->GetRootScrollFrame()) {
RestoreFrameStateFor(rootScrollFrame, aFrameState);
}
}
#ifdef ACCESSIBILITY
nsAccessibilityService* accService = nsIPresShell::AccService();
if (accService) {
if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
accService->ContentRangeInserted(mPresShell, aContainer,
aStartChild, aEndChild);
}
@ -8549,27 +8542,32 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
*aDestroyedFramesFor = aChild;
}
// We're destroying our frame(s). This normally happens either when the content
// is being removed from the DOM (in which case we'll drop all Servo data in
// UnbindFromTree), or when we're recreating frames (usually in response to
// having retrieved a ReconstructFrame change hint after restyling). In both of
// those cases, there are no pending restyles we need to worry about.
// We're destroying our frame(s). This normally happens either when the
// content is being removed from the DOM (in which case we'll drop all Servo
// data in UnbindFromTree), or when we're recreating frames (usually in
// response to having retrieved a ReconstructFrame change hint after
// restyling). In both of those cases, there are no pending restyles we need
// to worry about.
//
// However, there is also the (rare) DestroyFramesFor path, in which we tear
// down (and usually recreate) the frames for a subtree. In this case, leaving
// the style data on the elements is problematic for our invariants, because
// there might be pending restyles in the subtree. If we simply leave them as-is,
// the subsequent traversal when recreating frames will generate a bunch of bogus
// change hints to update frames that no longer exist.
// there might be pending restyles in the subtree. If we simply leave them
// as-is, the subsequent traversal when recreating frames will generate a
// bunch of bogus change hints to update frames that no longer exist.
//
// So the two obvious options are to (1) process all pending restyles and take all
// the change hints before destroying the frames, or (2) drop all the style data.
// We chose the latter, since that matches the performance characteristics of the
// old Gecko style system.
// So the two obvious options are to (1) process all pending restyles and take
// all the change hints before destroying the frames, or (2) drop all the
// style data. We chose the latter, since that matches the performance
// characteristics of the old Gecko style system.
//
// That said, it's almost certainly possible to optimize this if it turns out to be
// hot. It's just not a priority at the moment.
if (aFlags == REMOVE_DESTROY_FRAMES && aChild->IsElement() && aChild->IsStyledByServo()) {
// That said, it's almost certainly possible to optimize this if it turns out
// to be hot. It's just not a priority at the moment.
//
// FIXME(emilio): This really really feels like a hack, and it's only for the
// XBL/Shadow DOM path, so we should do this there instead.
if (aFlags == REMOVE_DESTROY_FRAMES && aChild->IsElement() &&
aChild->IsStyledByServo()) {
ServoRestyleManager::ClearServoDataFromSubtree(aChild->AsElement());
}
@ -8588,9 +8586,6 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
presContext->UpdateViewportScrollbarStylesOverride();
}
// XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
// the :empty pseudo-class?
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
@ -8655,7 +8650,6 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
}
return;
}
#endif // MOZ_XUL
// If we're removing the root, then make sure to remove things starting at
@ -8684,10 +8678,10 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
!aContainer->IsInNativeAnonymousSubtree() &&
!aChild->IsInNativeAnonymousSubtree()) {
// Recreate frames if content is removed from a ShadowRoot
// because it may contain an insertion point which can change
// how the host is rendered.
//XXXsmaug This is super unefficient!
// Recreate frames if content is removed from a ShadowRoot because it may
// contain an insertion point which can change how the host is rendered.
//
// XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
@ -9102,23 +9096,28 @@ nsCSSFrameConstructor::WillDestroyFrameTree()
// XXXbz I'd really like this method to go away. Once we have inline-block and
// I can just use that for sized broken images, that can happen, maybe.
void nsCSSFrameConstructor::GetAlternateTextFor(nsIContent* aContent,
nsIAtom* aTag, // content object's tag
nsXPIDLString& aAltText)
void
nsCSSFrameConstructor::GetAlternateTextFor(nsIContent* aContent,
nsIAtom* aTag,
nsXPIDLString& aAltText)
{
// The "alt" attribute specifies alternate text that is rendered
// when the image can not be displayed
// when the image can not be displayed.
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText)) {
return;
}
// If there's no "alt" attribute, and aContent is an input
// element, then use the value of the "value" attribute
if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText) &&
nsGkAtoms::input == aTag) {
// If there's no "value" attribute either, then use the localized string
// for "Submit" as the alternate text.
if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"Submit", aAltText);
if (nsGkAtoms::input == aTag) {
// If there's no "alt" attribute, and aContent is an input element, then use
// the value of the "value" attribute
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
return;
}
// If there's no "value" attribute either, then use the localized string for
// "Submit" as the alternate text.
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"Submit", aAltText);
}
}
@ -10854,7 +10853,8 @@ nsCSSFrameConstructor::WrapItemsInPseudoParent(nsIContent* aParentContent,
aIter.InsertItem(newItem);
}
void nsCSSFrameConstructor::CreateNeededPseudoSiblings(
void
nsCSSFrameConstructor::CreateNeededPseudoSiblings(
nsFrameConstructorState& aState,
FrameConstructionItemList& aItems,
nsIFrame* aParentFrame)

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

@ -60,7 +60,7 @@ public:
friend class mozilla::ServoRestyleManager;
nsCSSFrameConstructor(nsIDocument* aDocument, nsIPresShell* aPresShell);
~nsCSSFrameConstructor(void) {
~nsCSSFrameConstructor() {
MOZ_ASSERT(mUpdateCount == 0, "Dying in the middle of our own update?");
}

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

@ -891,6 +891,11 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
return NS_OK;
}
nsAutoCString sourceMapURL;
if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
mSheet->SetSourceMapURL(NS_ConvertUTF8toUTF16(sourceMapURL));
}
}
nsAutoCString contentType;

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

@ -259,6 +259,7 @@ StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy,
, mComplete(aCopy.mComplete)
, mFirstChild() // We don't rebuild the child because we're making a copy
// without children.
, mSourceMapURL(aCopy.mSourceMapURL)
#ifdef DEBUG
, mPrincipalSet(aCopy.mPrincipalSet)
#endif
@ -506,6 +507,18 @@ StyleSheet::GetCssRules(nsIPrincipal& aSubjectPrincipal,
FORWARD_INTERNAL(GetCssRulesInternal, ())
}
void
StyleSheet::GetSourceMapURL(nsAString& aSourceMapURL)
{
aSourceMapURL = mInner->mSourceMapURL;
}
void
StyleSheet::SetSourceMapURL(const nsAString& aSourceMapURL)
{
mInner->mSourceMapURL = aSourceMapURL;
}
css::Rule*
StyleSheet::GetDOMOwnerRule() const
{

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

@ -213,6 +213,8 @@ public:
dom::MediaList* Media();
bool Disabled() const { return mDisabled; }
// The XPCOM SetDisabled is fine for WebIDL.
void GetSourceMapURL(nsAString& aTitle);
void SetSourceMapURL(const nsAString& aSourceMapURL);
// WebIDL CSSStyleSheet API
// Can't be inline because we can't include ImportRule here. And can't be

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

@ -61,6 +61,11 @@ struct StyleSheetInfo
RefPtr<StyleSheet> mFirstChild;
AutoTArray<StyleSheet*, 8> mSheets;
// If a SourceMap or X-SourceMap response header is seen, this is
// the value. If both are seen, SourceMap is preferred. If neither
// is seen, this will be an empty string.
nsString mSourceMapURL;
#ifdef DEBUG
bool mPrincipalSet;
#endif

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

@ -3,6 +3,12 @@ support-files =
bug453896_iframe.html
media_queries_iframe.html
newtab_share_rule_processors.html
mapped.css
mapped.css^headers^
mapped2.css
mapped2.css^headers^
sourcemap_css.html
[browser_bug453896.js]
[browser_newtab_share_rule_processors.js]
[browser_sourcemap.js]

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

@ -0,0 +1,30 @@
add_task(async function() {
let uri = "http://example.com/browser/layout/style/test/sourcemap_css.html";
info(`URI is ${uri}`);
await BrowserTestUtils.withNewTab({
gBrowser,
url: uri
}, async function(browser) {
await ContentTask.spawn(browser, null, function* () {
let seenSheets = 0;
for (let i = 0; i < content.document.styleSheets.length; ++i) {
let sheet = content.document.styleSheets[i];
info(`Checking ${sheet.href}`);
if (/mapped\.css/.test(sheet.href)) {
is(sheet.sourceMapURL, "mapped.css.map", "X-SourceMap header took effect");
seenSheets |= 1;
} else if (/mapped2\.css/.test(sheet.href)) {
is(sheet.sourceMapURL, "mapped2.css.map", "SourceMap header took effect");
seenSheets |= 2;
} else {
ok(false, "sheet does not have source map URL");
}
}
is(seenSheets, 3, "seen all source-mapped sheets");
});
});
});

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

@ -0,0 +1,3 @@
div {
color: #f06;
}

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

@ -0,0 +1 @@
X-SourceMap: mapped.css.map

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

@ -0,0 +1,3 @@
span {
color: #f06;
}

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

@ -0,0 +1,2 @@
SourceMap: mapped2.css.map
X-SourceMap: ignored.css.map

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 1306887</title>
<link rel="stylesheet" type="text/css" href="mapped.css"/>
<link rel="stylesheet" type="text/css" href="mapped2.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1306887">Mozilla Bug 1306887</a>
</body>
</html>

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

@ -49,7 +49,7 @@ to mochitest command.
* test_grid_container_shorthands.html [65]
* test_grid_item_shorthands.html [23]
* test_grid_shorthand_serialization.html [28]
* test_value_storage.html `'grid` [41]
* test_value_storage.html `'grid` [21]
* Unsupported values
* SVG-in-OpenType values not supported servo/servo#15211 bug 1355412
* test_value_storage.html `context-` [7]

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

@ -830,7 +830,8 @@ MP4MetadataRust::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
continue;
}
// JPEG 'video' decoder is not supported in media stack yet.
if (track_info.codec == mp4parse_codec::mp4parse_codec_JPEG) {
if (track_info.codec == mp4parse_codec::mp4parse_codec_JPEG ||
track_info.codec == mp4parse_codec::mp4parse_codec_UNKNOWN) {
continue;
}
if (TrackTypeEqual(aType, track_info.track_type)) {

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

@ -1675,7 +1675,10 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
BoxType::VP9SampleEntry => CodecType::VP9,
BoxType::ProtectedVisualSampleEntry => CodecType::EncryptedVideo,
BoxType::JPEGAtom => CodecType::JPEG,
_ => CodecType::Unknown,
_ => {
log!("Unsupported video codec, box {:?} found", name);
CodecType::Unknown
}
};
// Skip uninteresting fields.
@ -1747,20 +1750,23 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
log!("{:?} (sinf)", sinf);
protection_info.push(sinf);
}
_ => skip_box_content(&mut b)?,
_ => {
log!("Unsupported video codec, box {:?} found", b.head.name);
skip_box_content(&mut b)?;
}
}
check_parser_state!(b.content);
}
codec_specific
.map(|codec_specific| (codec_type, SampleEntry::Video(VideoSampleEntry {
Ok(codec_specific.map_or((CodecType::Unknown, SampleEntry::Unknown),
|codec_specific| (codec_type, SampleEntry::Video(VideoSampleEntry {
data_reference_index: data_reference_index,
width: width,
height: height,
codec_specific: codec_specific,
protection_info: protection_info,
})))
.ok_or_else(|| Error::InvalidData("malformed video sample entry"))
)
}
fn read_qt_wave_atom<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> {
@ -1889,13 +1895,16 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
codec_type = CodecType::EC3;
codec_specific = Some(AudioCodecSpecific::EC3SpecificBox);
}
_ => skip_box_content(&mut b)?,
_ => {
log!("Unsupported audio codec, box {:?} found", b.head.name);
skip_box_content(&mut b)?;
}
}
check_parser_state!(b.content);
}
codec_specific
.map(|codec_specific| (codec_type, SampleEntry::Audio(AudioSampleEntry {
Ok(codec_specific.map_or((CodecType::Unknown, SampleEntry::Unknown),
|codec_specific| (codec_type, SampleEntry::Audio(AudioSampleEntry {
data_reference_index: data_reference_index,
channelcount: channelcount,
samplesize: samplesize,
@ -1903,7 +1912,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
codec_specific: codec_specific,
protection_info: protection_info,
})))
.ok_or_else(|| Error::InvalidData("malformed audio sample entry"))
)
}
/// Parse a stsd box.

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

@ -1071,3 +1071,52 @@ fn jpeg_video_sample_entry() {
_ => panic!("failed to parse a jpeg atom"),
}
}
#[test]
fn unknown_video_sample_entry() {
let unknown_codec = make_box(BoxSize::Auto, b"yyyy", |s| {
s.append_repeated(0, 16)
}).into_inner();
let mut stream = make_box(BoxSize::Auto, b"xxxx", |s| {
s.append_repeated(0, 6)
.B16(1)
.append_repeated(0, 16)
.B16(0)
.B16(0)
.append_repeated(0, 14)
.append_repeated(0, 32)
.append_repeated(0, 4)
.append_bytes(unknown_codec.as_slice())
});
let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap();
match super::read_video_sample_entry(&mut stream) {
Ok((super::CodecType::Unknown, super::SampleEntry::Unknown)) => (),
_ => panic!("expected a different error result"),
}
}
#[test]
fn unknown_audio_sample_entry() {
let unknown_codec = make_box(BoxSize::Auto, b"yyyy", |s| {
s.append_repeated(0, 16)
}).into_inner();
let mut stream = make_box(BoxSize::Auto, b"xxxx", |s| {
s.append_repeated(0, 6)
.B16(1)
.B32(0)
.B32(0)
.B16(2)
.B16(16)
.B16(0)
.B16(0)
.B32(48000 << 16)
.append_bytes(unknown_codec.as_slice())
});
let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap();
match super::read_audio_sample_entry(&mut stream) {
Ok((super::CodecType::Unknown, super::SampleEntry::Unknown)) => (),
_ => panic!("expected a different error result"),
}
}

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

@ -2,7 +2,7 @@
# Script to update mp4parse-rust sources to latest upstream
# Default version.
VER=ae58bb5063cde8018d51c1778a52392777ddb0d4
VER=ce7e2e66613009d56aea2588c4d11a23d4dd8056
# Accept version or commit from the command line.
if test -n "$1"; then

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