зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2ginbound, a=merge
--HG-- extra : commitid : 7YFKL9gqXNj
This commit is contained in:
Коммит
fc06478918
|
@ -936,8 +936,8 @@ chatbox[customSize] {
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbox[customSize="loopChatEnabled"] {
|
chatbox[customSize="loopChatEnabled"] {
|
||||||
/* 325px as defined per UX */
|
/* 430px as defined per UX */
|
||||||
height: 325px;
|
height: 430px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat-window[customSize="loopChatEnabled"] {
|
#chat-window[customSize="loopChatEnabled"] {
|
||||||
|
@ -946,8 +946,13 @@ chatbox[customSize="loopChatEnabled"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbox[customSize="loopChatMessageAppended"] {
|
chatbox[customSize="loopChatMessageAppended"] {
|
||||||
/* 400px as defined per UX */
|
/* 430px as defined per UX */
|
||||||
height: 400px;
|
height: 430px;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatbox[customSize="loopChatDisabledMessageAppended"] {
|
||||||
|
/* 388px as defined per UX */
|
||||||
|
height: 388px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat-window[customSize="loopChatMessageAppended"] {
|
#chat-window[customSize="loopChatMessageAppended"] {
|
||||||
|
@ -971,8 +976,8 @@ chatbar {
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbar[customSize] > .chatbar-innerbox {
|
chatbar[customSize] > .chatbar-innerbox {
|
||||||
/* 425px to make room for the maximum custom-size chatbox; currently 'loopChatMessageAppended'. */
|
/* 450px to make room for the maximum custom-size chatbox; currently 'loopChatMessageAppended'. */
|
||||||
margin-top: -425px;
|
margin-top: -450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
||||||
|
|
|
@ -5136,11 +5136,10 @@
|
||||||
|
|
||||||
<method name="_getDragTargetTab">
|
<method name="_getDragTargetTab">
|
||||||
<parameter name="event"/>
|
<parameter name="event"/>
|
||||||
|
<parameter name="isLink"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
let tab = event.target.localName == "tab" ? event.target : null;
|
let tab = event.target.localName == "tab" ? event.target : null;
|
||||||
if (tab &&
|
if (tab && isLink) {
|
||||||
(event.type == "drop" || event.type == "dragover") &&
|
|
||||||
event.dataTransfer.dropEffect == "link") {
|
|
||||||
let boxObject = tab.boxObject;
|
let boxObject = tab.boxObject;
|
||||||
if (event.screenX < boxObject.screenX + boxObject.width * .25 ||
|
if (event.screenX < boxObject.screenX + boxObject.width * .25 ||
|
||||||
event.screenX > boxObject.screenX + boxObject.width * .75)
|
event.screenX > boxObject.screenX + boxObject.width * .75)
|
||||||
|
@ -5152,9 +5151,10 @@
|
||||||
|
|
||||||
<method name="_getDropIndex">
|
<method name="_getDropIndex">
|
||||||
<parameter name="event"/>
|
<parameter name="event"/>
|
||||||
|
<parameter name="isLink"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
var tabs = this.childNodes;
|
var tabs = this.childNodes;
|
||||||
var tab = this._getDragTargetTab(event);
|
var tab = this._getDragTargetTab(event, isLink);
|
||||||
if (window.getComputedStyle(this, null).direction == "ltr") {
|
if (window.getComputedStyle(this, null).direction == "ltr") {
|
||||||
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
|
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
|
||||||
if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
|
if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
|
||||||
|
@ -5168,13 +5168,13 @@
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="_setEffectAllowedForDataTransfer">
|
<method name="_getDropEffectForTabDrag">
|
||||||
<parameter name="event"/>
|
<parameter name="event"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
var dt = event.dataTransfer;
|
var dt = event.dataTransfer;
|
||||||
// Disallow dropping multiple items
|
// Disallow dropping multiple items
|
||||||
if (dt.mozItemCount > 1)
|
if (dt.mozItemCount > 1)
|
||||||
return dt.effectAllowed = "none";
|
return "none";
|
||||||
|
|
||||||
var types = dt.mozTypesAt(0);
|
var types = dt.mozTypesAt(0);
|
||||||
var sourceNode = null;
|
var sourceNode = null;
|
||||||
|
@ -5190,22 +5190,20 @@
|
||||||
// and vice versa.
|
// and vice versa.
|
||||||
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
|
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
|
||||||
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerDocument.defaultView))
|
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerDocument.defaultView))
|
||||||
return dt.effectAllowed = "none";
|
return "none";
|
||||||
|
|
||||||
if (window.gMultiProcessBrowser !=
|
if (window.gMultiProcessBrowser !=
|
||||||
sourceNode.ownerDocument.defaultView.gMultiProcessBrowser)
|
sourceNode.ownerDocument.defaultView.gMultiProcessBrowser)
|
||||||
return dt.effectAllowed = "none";
|
return "none";
|
||||||
|
|
||||||
let copyModifier = this.tabbrowser.AppConstants.platform == "macosx" ? event.altKey : event.ctrlKey;
|
return dt.dropEffect == "copy" ? "copy" : "move";
|
||||||
return dt.effectAllowed = copyModifier ? "copy" : "move";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browserDragAndDrop.canDropLink(event)) {
|
if (browserDragAndDrop.canDropLink(event)) {
|
||||||
// Here we need to do this manually
|
return "link";
|
||||||
return dt.effectAllowed = dt.dropEffect = "link";
|
|
||||||
}
|
}
|
||||||
return dt.effectAllowed = "none";
|
return "none";
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
@ -5482,7 +5480,7 @@
|
||||||
]]></handler>
|
]]></handler>
|
||||||
|
|
||||||
<handler event="dragstart"><![CDATA[
|
<handler event="dragstart"><![CDATA[
|
||||||
var tab = this._getDragTargetTab(event);
|
var tab = this._getDragTargetTab(event, false);
|
||||||
if (!tab || this._isCustomizing)
|
if (!tab || this._isCustomizing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -5556,7 +5554,7 @@
|
||||||
]]></handler>
|
]]></handler>
|
||||||
|
|
||||||
<handler event="dragover"><![CDATA[
|
<handler event="dragover"><![CDATA[
|
||||||
var effects = this._setEffectAllowedForDataTransfer(event);
|
var effects = this._getDropEffectForTabDrag(event);
|
||||||
|
|
||||||
var ind = this._tabDropIndicator;
|
var ind = this._tabDropIndicator;
|
||||||
if (effects == "" || effects == "none") {
|
if (effects == "" || effects == "none") {
|
||||||
|
@ -5597,7 +5595,7 @@
|
||||||
this._finishAnimateTabMove();
|
this._finishAnimateTabMove();
|
||||||
|
|
||||||
if (effects == "link") {
|
if (effects == "link") {
|
||||||
let tab = this._getDragTargetTab(event);
|
let tab = this._getDragTargetTab(event, true);
|
||||||
if (tab) {
|
if (tab) {
|
||||||
if (!this._dragTime)
|
if (!this._dragTime)
|
||||||
this._dragTime = Date.now();
|
this._dragTime = Date.now();
|
||||||
|
@ -5623,7 +5621,7 @@
|
||||||
newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
|
newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let newIndex = this._getDropIndex(event);
|
let newIndex = this._getDropIndex(event, effects == "link");
|
||||||
if (newIndex == this.childNodes.length) {
|
if (newIndex == this.childNodes.length) {
|
||||||
let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
|
let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
|
||||||
if (ltr)
|
if (ltr)
|
||||||
|
@ -5654,7 +5652,7 @@
|
||||||
var dt = event.dataTransfer;
|
var dt = event.dataTransfer;
|
||||||
var dropEffect = dt.dropEffect;
|
var dropEffect = dt.dropEffect;
|
||||||
var draggedTab;
|
var draggedTab;
|
||||||
if (dropEffect != "link") { // copy or move
|
if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) { // tab copy or move
|
||||||
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||||
// not our drop then
|
// not our drop then
|
||||||
if (!draggedTab)
|
if (!draggedTab)
|
||||||
|
@ -5665,7 +5663,7 @@
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (draggedTab && dropEffect == "copy") {
|
if (draggedTab && dropEffect == "copy") {
|
||||||
// copy the dropped tab (wherever it's from)
|
// copy the dropped tab (wherever it's from)
|
||||||
let newIndex = this._getDropIndex(event);
|
let newIndex = this._getDropIndex(event, false);
|
||||||
let newTab = this.tabbrowser.duplicateTab(draggedTab);
|
let newTab = this.tabbrowser.duplicateTab(draggedTab);
|
||||||
this.tabbrowser.moveTabTo(newTab, newIndex);
|
this.tabbrowser.moveTabTo(newTab, newIndex);
|
||||||
if (draggedTab.parentNode != this || event.shiftKey)
|
if (draggedTab.parentNode != this || event.shiftKey)
|
||||||
|
@ -5684,7 +5682,7 @@
|
||||||
// swap the dropped tab with a new one we create and then close
|
// swap the dropped tab with a new one we create and then close
|
||||||
// it in the other window (making it seem to have moved between
|
// it in the other window (making it seem to have moved between
|
||||||
// windows)
|
// windows)
|
||||||
let newIndex = this._getDropIndex(event);
|
let newIndex = this._getDropIndex(event, false);
|
||||||
let newTab = this.tabbrowser.addTab("about:blank");
|
let newTab = this.tabbrowser.addTab("about:blank");
|
||||||
let newBrowser = this.tabbrowser.getBrowserForTab(newTab);
|
let newBrowser = this.tabbrowser.getBrowserForTab(newTab);
|
||||||
let draggedBrowserURL = draggedTab.linkedBrowser.currentURI.spec;
|
let draggedBrowserURL = draggedTab.linkedBrowser.currentURI.spec;
|
||||||
|
@ -5732,10 +5730,10 @@
|
||||||
if (event.shiftKey)
|
if (event.shiftKey)
|
||||||
bgLoad = !bgLoad;
|
bgLoad = !bgLoad;
|
||||||
|
|
||||||
let tab = this._getDragTargetTab(event);
|
let tab = this._getDragTargetTab(event, true);
|
||||||
if (!tab || dropEffect == "copy") {
|
if (!tab || dropEffect == "copy") {
|
||||||
// We're adding a new tab.
|
// We're adding a new tab.
|
||||||
let newIndex = this._getDropIndex(event);
|
let newIndex = this._getDropIndex(event, true);
|
||||||
let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true});
|
let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true});
|
||||||
this.tabbrowser.moveTabTo(newTab, newIndex);
|
this.tabbrowser.moveTabTo(newTab, newIndex);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
support-files =
|
support-files =
|
||||||
file_dom_notifications.html
|
file_dom_notifications.html
|
||||||
|
|
||||||
|
[browser_notification_close.js]
|
||||||
[browser_notification_do_not_disturb.js]
|
[browser_notification_do_not_disturb.js]
|
||||||
[browser_notification_open_settings.js]
|
[browser_notification_open_settings.js]
|
||||||
[browser_notification_remove_permission.js]
|
[browser_notification_remove_permission.js]
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let tab;
|
||||||
|
let notification;
|
||||||
|
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
|
||||||
|
|
||||||
|
add_task(function* test_notificationClose() {
|
||||||
|
let pm = Services.perms;
|
||||||
|
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
|
||||||
|
|
||||||
|
yield BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: notificationURL
|
||||||
|
}, function* dummyTabTask(aBrowser) {
|
||||||
|
let win = aBrowser.contentWindow.wrappedJSObject;
|
||||||
|
notification = win.showNotification2();
|
||||||
|
yield BrowserTestUtils.waitForEvent(notification, "show");
|
||||||
|
|
||||||
|
info("Notification alert showing");
|
||||||
|
|
||||||
|
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
|
||||||
|
if (!alertWindow) {
|
||||||
|
ok(true, "Notifications don't use XUL windows on all platforms.");
|
||||||
|
notification.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let alertCloseButton = alertWindow.document.querySelector(".alertCloseButton");
|
||||||
|
is(alertCloseButton.localName, "toolbarbutton", "close button found");
|
||||||
|
let promiseBeforeUnloadEvent =
|
||||||
|
BrowserTestUtils.waitForEvent(alertWindow, "beforeunload");
|
||||||
|
let closedTime = alertWindow.Date.now();
|
||||||
|
alertCloseButton.click();
|
||||||
|
info("Clicked on close button");
|
||||||
|
let beforeUnloadEvent = yield promiseBeforeUnloadEvent;
|
||||||
|
|
||||||
|
ok(true, "Alert should close when the close button is clicked");
|
||||||
|
let currentTime = alertWindow.Date.now();
|
||||||
|
// The notification will self-close at 12 seconds, so this checks
|
||||||
|
// that the notification closed before the timeout.
|
||||||
|
ok(currentTime - closedTime < 5000,
|
||||||
|
"Close requested at " + closedTime + ", actually closed at " + currentTime);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* cleanup() {
|
||||||
|
Services.perms.remove(makeURI(notificationURL), "desktop-notification");
|
||||||
|
});
|
|
@ -64,7 +64,7 @@ function onAlertShowing() {
|
||||||
is(doNotDisturbMenuItem.localName, "menuitem", "menuitem found");
|
is(doNotDisturbMenuItem.localName, "menuitem", "menuitem found");
|
||||||
alertWindow.addEventListener("beforeunload", onAlertClosing);
|
alertWindow.addEventListener("beforeunload", onAlertClosing);
|
||||||
doNotDisturbMenuItem.click();
|
doNotDisturbMenuItem.click();
|
||||||
info("Clicked on do-not-disturb menuitem")
|
info("Clicked on do-not-disturb menuitem");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAlertClosing(event) {
|
function onAlertClosing(event) {
|
||||||
|
|
|
@ -199,10 +199,16 @@ extensions.registerAPI((extension, context) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
onLocationChange(browser, webProgress, request, locationURI, flags) {
|
onLocationChange(browser, webProgress, request, locationURI, flags) {
|
||||||
|
if (!webProgress.isTopLevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
|
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let tab = gBrowser.getTabForBrowser(browser);
|
||||||
let tabId = TabManager.getId(tab);
|
let tabId = TabManager.getId(tab);
|
||||||
let [needed, changeInfo] = sanitize(extension, {url: locationURI.spec});
|
let [needed, changeInfo] = sanitize(extension, {
|
||||||
|
status: webProgress.isLoadingDocument ? "loading" : "complete",
|
||||||
|
url: locationURI.spec
|
||||||
|
});
|
||||||
if (needed) {
|
if (needed) {
|
||||||
fire(tabId, changeInfo, TabManager.convert(extension, tab));
|
fire(tabId, changeInfo, TabManager.convert(extension, tab));
|
||||||
}
|
}
|
||||||
|
@ -213,11 +219,12 @@ extensions.registerAPI((extension, context) => {
|
||||||
AllWindowEvents.addListener("TabAttrModified", listener);
|
AllWindowEvents.addListener("TabAttrModified", listener);
|
||||||
AllWindowEvents.addListener("TabPinned", listener);
|
AllWindowEvents.addListener("TabPinned", listener);
|
||||||
AllWindowEvents.addListener("TabUnpinned", listener);
|
AllWindowEvents.addListener("TabUnpinned", listener);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
AllWindowEvents.removeListener("progress", progressListener);
|
AllWindowEvents.removeListener("progress", progressListener);
|
||||||
AllWindowEvents.addListener("TabAttrModified", listener);
|
AllWindowEvents.removeListener("TabAttrModified", listener);
|
||||||
AllWindowEvents.addListener("TabPinned", listener);
|
AllWindowEvents.removeListener("TabPinned", listener);
|
||||||
AllWindowEvents.addListener("TabUnpinned", listener);
|
AllWindowEvents.removeListener("TabUnpinned", listener);
|
||||||
};
|
};
|
||||||
}).api(),
|
}).api(),
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,7 @@ global.AllWindowEvents = {
|
||||||
|
|
||||||
let listeners = this._listeners.get(type);
|
let listeners = this._listeners.get(type);
|
||||||
listeners.delete(listener);
|
listeners.delete(listener);
|
||||||
if (listeners.length == 0) {
|
if (listeners.size == 0) {
|
||||||
this._listeners.delete(type);
|
this._listeners.delete(type);
|
||||||
if (this._listeners.size == 0) {
|
if (this._listeners.size == 0) {
|
||||||
WindowListManager.removeOpenListener(this.openListener);
|
WindowListManager.removeOpenListener(this.openListener);
|
||||||
|
|
|
@ -3,6 +3,8 @@ support-files =
|
||||||
head.js
|
head.js
|
||||||
context.html
|
context.html
|
||||||
ctxmenu-image.png
|
ctxmenu-image.png
|
||||||
|
context_tabs_onUpdated_page.html
|
||||||
|
context_tabs_onUpdated_iframe.html
|
||||||
|
|
||||||
[browser_ext_simple.js]
|
[browser_ext_simple.js]
|
||||||
[browser_ext_currentWindow.js]
|
[browser_ext_currentWindow.js]
|
||||||
|
@ -16,6 +18,7 @@ support-files =
|
||||||
[browser_ext_tabs_executeScript.js]
|
[browser_ext_tabs_executeScript.js]
|
||||||
[browser_ext_tabs_query.js]
|
[browser_ext_tabs_query.js]
|
||||||
[browser_ext_tabs_update.js]
|
[browser_ext_tabs_update.js]
|
||||||
|
[browser_ext_tabs_onUpdated.js]
|
||||||
[browser_ext_tabs_sendMessage.js]
|
[browser_ext_tabs_sendMessage.js]
|
||||||
[browser_ext_windows_update.js]
|
[browser_ext_windows_update.js]
|
||||||
[browser_ext_contentscript_connect.js]
|
[browser_ext_contentscript_connect.js]
|
||||||
|
|
|
@ -1,21 +1,3 @@
|
||||||
function* focusWindow(win)
|
|
||||||
{
|
|
||||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
|
||||||
if (fm.activeWindow == win) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise = new Promise(resolve => {
|
|
||||||
win.addEventListener("focus", function listener() {
|
|
||||||
win.removeEventListener("focus", listener, true);
|
|
||||||
resolve();
|
|
||||||
}, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
win.focus();
|
|
||||||
yield promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genericChecker()
|
function genericChecker()
|
||||||
{
|
{
|
||||||
var kind = "background";
|
var kind = "background";
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
add_task(function* () {
|
||||||
|
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||||
|
|
||||||
|
yield focusWindow(win1);
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
|
manifest: {
|
||||||
|
"permissions": ["tabs"],
|
||||||
|
"content_scripts": [{
|
||||||
|
"matches": ["http://mochi.test/*/context_tabs_onUpdated_page.html"],
|
||||||
|
"js": ["content-script.js"],
|
||||||
|
"run_at": "document_start"
|
||||||
|
},],
|
||||||
|
},
|
||||||
|
|
||||||
|
background: function() {
|
||||||
|
var pageURL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context_tabs_onUpdated_page.html";
|
||||||
|
|
||||||
|
var expectedSequence = [
|
||||||
|
{ status: "loading" },
|
||||||
|
{ status: "loading", url: pageURL },
|
||||||
|
{ status: "complete" }
|
||||||
|
];
|
||||||
|
var collectedSequence = [];
|
||||||
|
|
||||||
|
browser.tabs.onUpdated.addListener(function (tabId, updatedInfo) {
|
||||||
|
collectedSequence.push(updatedInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener(function () {
|
||||||
|
if (collectedSequence.length !== expectedSequence.length) {
|
||||||
|
browser.test.assertEq(
|
||||||
|
JSON.stringify(expectedSequence),
|
||||||
|
JSON.stringify(collectedSequence),
|
||||||
|
"got unexpected number of updateInfo data"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < expectedSequence.length; i++) {
|
||||||
|
browser.test.assertEq(
|
||||||
|
expectedSequence[i].status,
|
||||||
|
collectedSequence[i].status,
|
||||||
|
"check updatedInfo status"
|
||||||
|
);
|
||||||
|
if (expectedSequence[i].url || collectedSequence[i].url) {
|
||||||
|
browser.test.assertEq(
|
||||||
|
expectedSequence[i].url,
|
||||||
|
collectedSequence[i].url,
|
||||||
|
"check updatedInfo url"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.test.notifyPass("tabs.onUpdated");
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.tabs.create({ url: pageURL });
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
"content-script.js": `
|
||||||
|
window.addEventListener("message", function(evt) {
|
||||||
|
if (evt.data == "frame-updated") {
|
||||||
|
browser.runtime.sendMessage("load-completed");
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
yield Promise.all([
|
||||||
|
extension.startup(),
|
||||||
|
extension.awaitFinish("tabs.onUpdated")
|
||||||
|
]);
|
||||||
|
|
||||||
|
yield extension.unload();
|
||||||
|
|
||||||
|
yield BrowserTestUtils.closeWindow(win1);
|
||||||
|
});
|
|
@ -0,0 +1,17 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h3>test iframe</h3>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
window.onhashchange = function() {
|
||||||
|
window.parent.postMessage("updated-iframe-url", "*");
|
||||||
|
}
|
||||||
|
// NOTE: without the this setTimeout the location change is not fired
|
||||||
|
// even without the "fire only for top level windows" fix
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.hash="updated-iframe-url";
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h3>test page</h3>
|
||||||
|
<iframe src="about:blank"></iframe>
|
||||||
|
<script>
|
||||||
|
window.onmessage = function(evt) {
|
||||||
|
if (evt.data === "updated-iframe-url") {
|
||||||
|
window.postMessage("frame-updated", "*");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.onload = function() {
|
||||||
|
document.querySelector('iframe').setAttribute("src", "context_tabs_onUpdated_iframe.html");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -5,3 +5,21 @@ function makeWidgetId(id)
|
||||||
id = id.toLowerCase();
|
id = id.toLowerCase();
|
||||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* focusWindow(win)
|
||||||
|
{
|
||||||
|
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||||
|
if (fm.activeWindow == win) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise = new Promise(resolve => {
|
||||||
|
win.addEventListener("focus", function listener() {
|
||||||
|
win.removeEventListener("focus", listener, true);
|
||||||
|
resolve();
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
win.focus();
|
||||||
|
yield promise;
|
||||||
|
}
|
||||||
|
|
|
@ -530,13 +530,13 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
}
|
}
|
||||||
|
|
||||||
.context-url-view-wrapper {
|
.context-url-view-wrapper {
|
||||||
padding: 12px;
|
padding: 14px 15px;
|
||||||
margin-bottom: 0.5em;
|
|
||||||
background-color: #dbf7ff;
|
background-color: #dbf7ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.showing-room-name > .text-chat-entries > .text-chat-scroller > .context-url-view-wrapper {
|
.showing-room-name > .text-chat-entries > .text-chat-scroller > .context-url-view-wrapper {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.room-context {
|
.room-context {
|
||||||
|
@ -755,7 +755,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
.media-wrapper > .focus-stream {
|
.media-wrapper > .focus-stream {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* A reasonable height */
|
/* A reasonable height */
|
||||||
height: 70%;
|
height: 55%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-wrapper.receiving-screen-share > .focus-stream {
|
.media-wrapper.receiving-screen-share > .focus-stream {
|
||||||
|
@ -831,7 +831,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
|
|
||||||
.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view {
|
.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view {
|
||||||
/* This is temp, to echo the .media-wrapper > .text-chat-view above */
|
/* This is temp, to echo the .media-wrapper > .text-chat-view above */
|
||||||
height: 30%;
|
height: 45%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-wrapper.receiving-screen-share > .screen {
|
.media-wrapper.receiving-screen-share > .screen {
|
||||||
|
@ -930,7 +930,12 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
|
|
||||||
.media-wrapper > .focus-stream {
|
.media-wrapper > .focus-stream {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
height: auto;
|
/* To keep the aspect ratio of video. Update accordingly with chatbox[customSize] width */
|
||||||
|
height: 263px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view {
|
||||||
|
height: calc(100% - 263px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,6 +965,10 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
text-align: start;
|
text-align: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-chat-scroller div:nth-child(2) {
|
||||||
|
margin-top: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sent text chat entries should be on the right */
|
/* Sent text chat entries should be on the right */
|
||||||
.text-chat-entry.sent {
|
.text-chat-entry.sent {
|
||||||
/* aligns paragraph to right side */
|
/* aligns paragraph to right side */
|
||||||
|
@ -1208,8 +1217,6 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||||
.text-chat-view {
|
.text-chat-view {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
/* 120px max-height of .text-chat-entries plus 40px of .text-chat-box */
|
|
||||||
max-height: 160px;
|
|
||||||
/* 60px min-height of .text-chat-entries plus 40px of .text-chat-box */
|
/* 60px min-height of .text-chat-entries plus 40px of .text-chat-box */
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
@ -1220,7 +1227,6 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||||
|
|
||||||
.text-chat-entries {
|
.text-chat-entries {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
max-height: 120px;
|
|
||||||
min-height: 60px;
|
min-height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,11 @@ loop.store.TextChatStore = (function() {
|
||||||
// Notify MozLoopService if appropriate that a message has been appended
|
// Notify MozLoopService if appropriate that a message has been appended
|
||||||
// and it should therefore check if we need a different sized window or not.
|
// and it should therefore check if we need a different sized window or not.
|
||||||
if (message.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME) {
|
if (message.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME) {
|
||||||
|
if (this._storeState.textChatEnabled) {
|
||||||
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
|
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
|
||||||
|
} else {
|
||||||
|
window.dispatchEvent(new CustomEvent("LoopChatDisabledMessageAppended"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -963,6 +963,7 @@ var MozLoopServiceInternal = {
|
||||||
|
|
||||||
const kSizeMap = {
|
const kSizeMap = {
|
||||||
LoopChatEnabled: "loopChatEnabled",
|
LoopChatEnabled: "loopChatEnabled",
|
||||||
|
LoopChatDisabledMessageAppended: "loopChatDisabledMessageAppended",
|
||||||
LoopChatMessageAppended: "loopChatMessageAppended"
|
LoopChatMessageAppended: "loopChatMessageAppended"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -981,6 +982,7 @@ var MozLoopServiceInternal = {
|
||||||
|
|
||||||
window.addEventListener("LoopChatEnabled", onChatEvent);
|
window.addEventListener("LoopChatEnabled", onChatEvent);
|
||||||
window.addEventListener("LoopChatMessageAppended", onChatEvent);
|
window.addEventListener("LoopChatMessageAppended", onChatEvent);
|
||||||
|
window.addEventListener("LoopChatDisabledMessageAppended", onChatEvent);
|
||||||
|
|
||||||
injectLoopAPI(window);
|
injectLoopAPI(window);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ describe("loop.store.TextChatStore", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should dispatch a LoopChatMessageAppended event", function() {
|
it("should dispatch a LoopChatMessageAppended event", function() {
|
||||||
|
store.setStoreState({ textChatEnabled: true });
|
||||||
store.receivedTextChatMessage({
|
store.receivedTextChatMessage({
|
||||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
message: "Hello!"
|
message: "Hello!"
|
||||||
|
@ -141,6 +142,7 @@ describe("loop.store.TextChatStore", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should dipatch a LoopChatMessageAppended event", function() {
|
it("should dipatch a LoopChatMessageAppended event", function() {
|
||||||
|
store.setStoreState({ textChatEnabled: true });
|
||||||
store.sendTextChatMessage({
|
store.sendTextChatMessage({
|
||||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
message: "Hello!"
|
message: "Hello!"
|
||||||
|
@ -246,6 +248,23 @@ describe("loop.store.TextChatStore", function() {
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should dispatch a LoopChatDisabledMessageAppended event", function() {
|
||||||
|
store.setStoreState({ textChatEnabled: false });
|
||||||
|
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||||
|
roomName: "Let's share!",
|
||||||
|
roomUrl: "fake",
|
||||||
|
roomContextUrls: [{
|
||||||
|
description: "A wonderful event2",
|
||||||
|
location: "http://wonderful.invalid2",
|
||||||
|
thumbnail: "fake2"
|
||||||
|
}]
|
||||||
|
}));
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(window.dispatchEvent);
|
||||||
|
sinon.assert.calledWithExactly(window.dispatchEvent,
|
||||||
|
new CustomEvent("LoopChatDisabledMessageAppended"));
|
||||||
|
});
|
||||||
|
|
||||||
it("should not dispatch a LoopChatMessageAppended event", function() {
|
it("should not dispatch a LoopChatMessageAppended event", function() {
|
||||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||||
roomName: "Let's share!",
|
roomName: "Let's share!",
|
||||||
|
|
|
@ -898,7 +898,7 @@
|
||||||
),
|
),
|
||||||
|
|
||||||
React.createElement(Section, {name: "DesktopRoomConversationView"},
|
React.createElement(Section, {name: "DesktopRoomConversationView"},
|
||||||
React.createElement(FramedExample, {height: 398,
|
React.createElement(FramedExample, {height: 448,
|
||||||
onContentsRendered: invitationRoomStore.activeRoomStore.forcedUpdate,
|
onContentsRendered: invitationRoomStore.activeRoomStore.forcedUpdate,
|
||||||
summary: "Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)",
|
summary: "Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)",
|
||||||
width: 348},
|
width: 348},
|
||||||
|
@ -932,7 +932,7 @@
|
||||||
),
|
),
|
||||||
|
|
||||||
React.createElement(FramedExample, {dashed: true,
|
React.createElement(FramedExample, {dashed: true,
|
||||||
height: 398,
|
height: 448,
|
||||||
onContentsRendered: desktopRoomStoreLoading.activeRoomStore.forcedUpdate,
|
onContentsRendered: desktopRoomStoreLoading.activeRoomStore.forcedUpdate,
|
||||||
summary: "Desktop room conversation (loading)",
|
summary: "Desktop room conversation (loading)",
|
||||||
width: 348},
|
width: 348},
|
||||||
|
@ -952,7 +952,7 @@
|
||||||
),
|
),
|
||||||
|
|
||||||
React.createElement(FramedExample, {dashed: true,
|
React.createElement(FramedExample, {dashed: true,
|
||||||
height: 398,
|
height: 448,
|
||||||
onContentsRendered: roomStore.activeRoomStore.forcedUpdate,
|
onContentsRendered: roomStore.activeRoomStore.forcedUpdate,
|
||||||
summary: "Desktop room conversation",
|
summary: "Desktop room conversation",
|
||||||
width: 348},
|
width: 348},
|
||||||
|
@ -1006,7 +1006,7 @@
|
||||||
),
|
),
|
||||||
|
|
||||||
React.createElement(FramedExample, {dashed: true,
|
React.createElement(FramedExample, {dashed: true,
|
||||||
height: 398,
|
height: 448,
|
||||||
onContentsRendered: desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate,
|
onContentsRendered: desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate,
|
||||||
summary: "Desktop room conversation local face-mute",
|
summary: "Desktop room conversation local face-mute",
|
||||||
width: 348},
|
width: 348},
|
||||||
|
@ -1022,7 +1022,7 @@
|
||||||
),
|
),
|
||||||
|
|
||||||
React.createElement(FramedExample, {dashed: true,
|
React.createElement(FramedExample, {dashed: true,
|
||||||
height: 398,
|
height: 448,
|
||||||
onContentsRendered: desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate,
|
onContentsRendered: desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate,
|
||||||
summary: "Desktop room conversation remote face-mute",
|
summary: "Desktop room conversation remote face-mute",
|
||||||
width: 348},
|
width: 348},
|
||||||
|
|
|
@ -898,7 +898,7 @@
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<Section name="DesktopRoomConversationView">
|
<Section name="DesktopRoomConversationView">
|
||||||
<FramedExample height={398}
|
<FramedExample height={448}
|
||||||
onContentsRendered={invitationRoomStore.activeRoomStore.forcedUpdate}
|
onContentsRendered={invitationRoomStore.activeRoomStore.forcedUpdate}
|
||||||
summary="Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)"
|
summary="Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)"
|
||||||
width={348}>
|
width={348}>
|
||||||
|
@ -932,7 +932,7 @@
|
||||||
</FramedExample>
|
</FramedExample>
|
||||||
|
|
||||||
<FramedExample dashed={true}
|
<FramedExample dashed={true}
|
||||||
height={398}
|
height={448}
|
||||||
onContentsRendered={desktopRoomStoreLoading.activeRoomStore.forcedUpdate}
|
onContentsRendered={desktopRoomStoreLoading.activeRoomStore.forcedUpdate}
|
||||||
summary="Desktop room conversation (loading)"
|
summary="Desktop room conversation (loading)"
|
||||||
width={348}>
|
width={348}>
|
||||||
|
@ -952,7 +952,7 @@
|
||||||
</FramedExample>
|
</FramedExample>
|
||||||
|
|
||||||
<FramedExample dashed={true}
|
<FramedExample dashed={true}
|
||||||
height={398}
|
height={448}
|
||||||
onContentsRendered={roomStore.activeRoomStore.forcedUpdate}
|
onContentsRendered={roomStore.activeRoomStore.forcedUpdate}
|
||||||
summary="Desktop room conversation"
|
summary="Desktop room conversation"
|
||||||
width={348}>
|
width={348}>
|
||||||
|
@ -1006,7 +1006,7 @@
|
||||||
</FramedExample>
|
</FramedExample>
|
||||||
|
|
||||||
<FramedExample dashed={true}
|
<FramedExample dashed={true}
|
||||||
height={398}
|
height={448}
|
||||||
onContentsRendered={desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate}
|
onContentsRendered={desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate}
|
||||||
summary="Desktop room conversation local face-mute"
|
summary="Desktop room conversation local face-mute"
|
||||||
width={348}>
|
width={348}>
|
||||||
|
@ -1022,7 +1022,7 @@
|
||||||
</FramedExample>
|
</FramedExample>
|
||||||
|
|
||||||
<FramedExample dashed={true}
|
<FramedExample dashed={true}
|
||||||
height={398}
|
height={448}
|
||||||
onContentsRendered={desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate}
|
onContentsRendered={desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate}
|
||||||
summary="Desktop room conversation remote face-mute"
|
summary="Desktop room conversation remote face-mute"
|
||||||
width={348} >
|
width={348} >
|
||||||
|
|
|
@ -2669,7 +2669,22 @@ ContentPermissionPrompt.prototype = {
|
||||||
_promptWebNotifications : function(aRequest) {
|
_promptWebNotifications : function(aRequest) {
|
||||||
var message = gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
|
var message = gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
|
||||||
|
|
||||||
var actions = [
|
var actions;
|
||||||
|
|
||||||
|
var browser = this._getBrowserForRequest(aRequest);
|
||||||
|
// Only show "allow for session" in PB mode, we don't
|
||||||
|
// support "allow for session" in non-PB mode.
|
||||||
|
if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
||||||
|
actions = [
|
||||||
|
{
|
||||||
|
stringId: "webNotifications.receiveForSession",
|
||||||
|
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||||
|
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||||
|
callback: function() {},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
actions = [
|
||||||
{
|
{
|
||||||
stringId: "webNotifications.alwaysReceive",
|
stringId: "webNotifications.alwaysReceive",
|
||||||
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||||
|
@ -2683,6 +2698,7 @@ ContentPermissionPrompt.prototype = {
|
||||||
callback: function() {},
|
callback: function() {},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
|
learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
|
||||||
|
|
|
@ -375,6 +375,8 @@ geolocation.neverShareLocation.accesskey=N
|
||||||
geolocation.shareWithSite2=Would you like to share your location with this site?
|
geolocation.shareWithSite2=Would you like to share your location with this site?
|
||||||
geolocation.shareWithFile2=Would you like to share your location with this file?
|
geolocation.shareWithFile2=Would you like to share your location with this file?
|
||||||
|
|
||||||
|
webNotifications.receiveForSession=Receive for this session
|
||||||
|
webNotifications.receiveForSession.accesskey=s
|
||||||
webNotifications.alwaysReceive=Always Receive Notifications
|
webNotifications.alwaysReceive=Always Receive Notifications
|
||||||
webNotifications.alwaysReceive.accesskey=A
|
webNotifications.alwaysReceive.accesskey=A
|
||||||
webNotifications.neverShow=Always Block Notifications
|
webNotifications.neverShow=Always Block Notifications
|
||||||
|
|
|
@ -48,9 +48,8 @@ mozstdName=Disconnect.me basic protection (Recommended).
|
||||||
mozstdDesc=Allows some trackers so websites function properly.
|
mozstdDesc=Allows some trackers so websites function properly.
|
||||||
mozfullName=Disconnect.me strict protection.
|
mozfullName=Disconnect.me strict protection.
|
||||||
mozfullDesc=Blocks known trackers. Some sites may not function properly.
|
mozfullDesc=Blocks known trackers. Some sites may not function properly.
|
||||||
# LOCALIZATION NOTE (blocklistChangeRequiresRestart, restartTitle): %S = brandShortName
|
# LOCALIZATION NOTE (blocklistChangeRequiresRestart): %S = brandShortName
|
||||||
blocklistChangeRequiresRestart=%S must restart to change block lists.
|
blocklistChangeRequiresRestart=%S must restart to change block lists.
|
||||||
shouldRestartTitle=Restart %S
|
|
||||||
|
|
||||||
#### Master Password
|
#### Master Password
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
"mozilla/components-imports": 1,
|
"mozilla/components-imports": 1,
|
||||||
"mozilla/import-headjs-globals": 1,
|
"mozilla/import-headjs-globals": 1,
|
||||||
"mozilla/mark-test-function-used": 1,
|
"mozilla/mark-test-function-used": 1,
|
||||||
|
"mozilla/var-only-at-top-level": 1,
|
||||||
|
|
||||||
// Disallow using variables outside the blocks they are defined (especially
|
// Disallow using variables outside the blocks they are defined (especially
|
||||||
// since only let and const are used, see "no-var").
|
// since only let and const are used, see "no-var").
|
||||||
|
@ -270,8 +271,9 @@
|
||||||
"no-unused-vars": 2,
|
"no-unused-vars": 2,
|
||||||
// Allow using variables before they are defined.
|
// Allow using variables before they are defined.
|
||||||
"no-use-before-define": 0,
|
"no-use-before-define": 0,
|
||||||
// Require let or const instead of var.
|
// We use var-only-at-top-level instead of no-var as we allow top level
|
||||||
"no-var": 2,
|
// vars.
|
||||||
|
"no-var": 0,
|
||||||
// Allow using TODO/FIXME comments.
|
// Allow using TODO/FIXME comments.
|
||||||
"no-warning-comments": 0,
|
"no-warning-comments": 0,
|
||||||
// Disallow use of the with statement.
|
// Disallow use of the with statement.
|
||||||
|
|
|
@ -9,7 +9,9 @@ const { getSnapshotStatusText } = require("../utils");
|
||||||
const { snapshotState: states } = require("../constants");
|
const { snapshotState: states } = require("../constants");
|
||||||
const { snapshot: snapshotModel } = require("../models");
|
const { snapshot: snapshotModel } = require("../models");
|
||||||
const TAKE_SNAPSHOT_TEXT = "Take snapshot";
|
const TAKE_SNAPSHOT_TEXT = "Take snapshot";
|
||||||
const TREE_ROW_HEIGHT = 10;
|
// If HEAP_TREE_ROW_HEIGHT changes, be sure to change `var(--heap-tree-row-height)`
|
||||||
|
// in `devtools/client/themes/memory.css`
|
||||||
|
const HEAP_TREE_ROW_HEIGHT = 14;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a hash map mapping node IDs to its parent node.
|
* Creates a hash map mapping node IDs to its parent node.
|
||||||
|
@ -45,7 +47,7 @@ function createTreeProperties (census) {
|
||||||
renderItem: (item, depth, focused, arrow) => new TreeItem({ item, depth, focused, arrow }),
|
renderItem: (item, depth, focused, arrow) => new TreeItem({ item, depth, focused, arrow }),
|
||||||
getRoots: () => census.children,
|
getRoots: () => census.children,
|
||||||
getKey: node => node.id,
|
getKey: node => node.id,
|
||||||
itemHeight: TREE_ROW_HEIGHT,
|
itemHeight: HEAP_TREE_ROW_HEIGHT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +87,13 @@ const Heap = module.exports = createClass({
|
||||||
break;
|
break;
|
||||||
case states.SAVED_CENSUS:
|
case states.SAVED_CENSUS:
|
||||||
pane = dom.div({ className: "heap-view-panel", "data-state": "loaded" },
|
pane = dom.div({ className: "heap-view-panel", "data-state": "loaded" },
|
||||||
|
dom.div({ className: "header" },
|
||||||
|
dom.span({ className: "heap-tree-item-bytes" }, "Bytes"),
|
||||||
|
dom.span({ className: "heap-tree-item-count" }, "Count"),
|
||||||
|
dom.span({ className: "heap-tree-item-total-bytes" }, "Total Bytes"),
|
||||||
|
dom.span({ className: "heap-tree-item-total-count" }, "Total Count"),
|
||||||
|
dom.span({ className: "heap-tree-item-name" }, "Name")
|
||||||
|
),
|
||||||
Tree(createTreeProperties(snapshot.census))
|
Tree(createTreeProperties(snapshot.census))
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -15,13 +15,15 @@ const TreeItem = module.exports = createClass({
|
||||||
render() {
|
render() {
|
||||||
let { item, depth, arrow, focused } = this.props;
|
let { item, depth, arrow, focused } = this.props;
|
||||||
|
|
||||||
return dom.div({ className: "heap-tree-item", style: { marginLeft: depth * INDENT }},
|
return dom.div({ className: "heap-tree-item" },
|
||||||
arrow,
|
|
||||||
dom.span({ className: "heap-tree-item-name" }, item.name),
|
|
||||||
dom.span({ className: "heap-tree-item-bytes" }, item.bytes),
|
dom.span({ className: "heap-tree-item-bytes" }, item.bytes),
|
||||||
dom.span({ className: "heap-tree-item-count" }, item.count),
|
dom.span({ className: "heap-tree-item-count" }, item.count),
|
||||||
dom.span({ className: "heap-tree-item-total-bytes" }, item.totalBytes),
|
dom.span({ className: "heap-tree-item-total-bytes" }, item.totalBytes),
|
||||||
dom.span({ className: "heap-tree-item-total-count" }, item.totalCount)
|
dom.span({ className: "heap-tree-item-total-count" }, item.totalCount),
|
||||||
|
dom.span({ className: "heap-tree-item-name", style: { marginLeft: depth * INDENT }},
|
||||||
|
arrow,
|
||||||
|
item.name
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -141,6 +141,14 @@ A marker generated via `console.timeStamp(label)`.
|
||||||
* DOMString causeName - the label passed into `console.timeStamp(label)`
|
* DOMString causeName - the label passed into `console.timeStamp(label)`
|
||||||
if passed in.
|
if passed in.
|
||||||
|
|
||||||
|
## document::DOMContentLoaded
|
||||||
|
|
||||||
|
A marker generated when the DOMContentLoaded event is fired.
|
||||||
|
|
||||||
|
## document::Load
|
||||||
|
|
||||||
|
A marker generated when the document's "load" event is fired.
|
||||||
|
|
||||||
## Parse HTML
|
## Parse HTML
|
||||||
|
|
||||||
## Parse XML
|
## Parse XML
|
||||||
|
|
|
@ -91,6 +91,16 @@ const TIMELINE_BLUEPRINT = {
|
||||||
label: L10N.getStr("marker.label.domevent"),
|
label: L10N.getStr("marker.label.domevent"),
|
||||||
fields: Formatters.DOMEventFields,
|
fields: Formatters.DOMEventFields,
|
||||||
},
|
},
|
||||||
|
"document::DOMContentLoaded": {
|
||||||
|
group: 1,
|
||||||
|
colorName: "graphs-full-red",
|
||||||
|
label: "DOMContentLoaded"
|
||||||
|
},
|
||||||
|
"document::Load": {
|
||||||
|
group: 1,
|
||||||
|
colorName: "graphs-full-blue",
|
||||||
|
label: "Load"
|
||||||
|
},
|
||||||
"Javascript": {
|
"Javascript": {
|
||||||
group: 1,
|
group: 1,
|
||||||
colorName: "graphs-yellow",
|
colorName: "graphs-yellow",
|
||||||
|
|
|
@ -56,6 +56,7 @@ skip-if = true # Bug 1161817
|
||||||
[browser_perf-loading-02.js]
|
[browser_perf-loading-02.js]
|
||||||
[browser_perf-marker-details-01.js]
|
[browser_perf-marker-details-01.js]
|
||||||
skip-if = os == 'linux' # Bug 1172120
|
skip-if = os == 'linux' # Bug 1172120
|
||||||
|
[browser_perf-markers-docload.js]
|
||||||
[browser_perf-options-01.js]
|
[browser_perf-options-01.js]
|
||||||
[browser_perf-options-02.js]
|
[browser_perf-options-02.js]
|
||||||
[browser_perf-options-03.js]
|
[browser_perf-options-03.js]
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the sidebar is updated with "DOMContentLoaded" and "load" markers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function* spawnTest() {
|
||||||
|
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||||
|
let { PerformanceController } = panel.panelWin;
|
||||||
|
|
||||||
|
loadFrameScripts();
|
||||||
|
|
||||||
|
yield startRecording(panel);
|
||||||
|
ok(true, "Recording has started.");
|
||||||
|
|
||||||
|
evalInDebuggee("document.location.reload()");
|
||||||
|
|
||||||
|
yield waitUntil(() => {
|
||||||
|
// Wait until we get the necessary markers.
|
||||||
|
let markers = PerformanceController.getCurrentRecording().getMarkers();
|
||||||
|
if (!markers.some(m => m.name == "document::DOMContentLoaded") ||
|
||||||
|
!markers.some(m => m.name == "document::Load")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(markers.filter(m => m.name == "document::DOMContentLoaded").length == 1,
|
||||||
|
"There should only be one `DOMContentLoaded` marker.");
|
||||||
|
ok(markers.filter(m => m.name == "document::Load").length == 1,
|
||||||
|
"There should only be one `load` marker.");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
yield stopRecording(panel);
|
||||||
|
ok(true, "Recording has ended.");
|
||||||
|
|
||||||
|
yield teardown(panel);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a string `script` and evaluates it directly in the content
|
||||||
|
* in potentially a different process.
|
||||||
|
*/
|
||||||
|
function evalInDebuggee (script) {
|
||||||
|
let { generateUUID } = Cc['@mozilla.org/uuid-generator;1'].getService(Ci.nsIUUIDGenerator);
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
if (!mm) {
|
||||||
|
throw new Error("`loadFrameScripts()` must be called when using MessageManager.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = generateUUID().toString();
|
||||||
|
mm.sendAsyncMessage("devtools:test:eval", { script: script, id: id });
|
||||||
|
mm.addMessageListener("devtools:test:eval:response", handler);
|
||||||
|
|
||||||
|
function handler ({ data }) {
|
||||||
|
if (id !== data.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.removeMessageListener("devtools:test:eval:response", handler);
|
||||||
|
deferred.resolve(data.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
|
@ -33,4 +33,30 @@ add_task(function *() {
|
||||||
is(widget.getCssValue(),
|
is(widget.getCssValue(),
|
||||||
"drop-shadow(2px 1px 5px black) url(example.svg#filter)",
|
"drop-shadow(2px 1px 5px black) url(example.svg#filter)",
|
||||||
"setCssValue should work for string-typed values");
|
"setCssValue should work for string-typed values");
|
||||||
|
|
||||||
|
info("Test parsing of mixed-case function names");
|
||||||
|
widget.setCssValue("BLUR(2px) Contrast(200%) Drop-Shadow(2px 1px 5px Black)");
|
||||||
|
is(widget.getCssValue(),
|
||||||
|
"BLUR(2px) Contrast(200%) Drop-Shadow(2px 1px 5px Black)",
|
||||||
|
"setCssValue should work for mixed-case function names");
|
||||||
|
|
||||||
|
info("Test parsing of invalid filter value");
|
||||||
|
widget.setCssValue("totallyinvalid");
|
||||||
|
is(widget.getCssValue(), "none",
|
||||||
|
"setCssValue should turn completely invalid value to 'none'");
|
||||||
|
|
||||||
|
info("Test parsing of invalid function argument");
|
||||||
|
widget.setCssValue("blur('hello')");
|
||||||
|
is(widget.getCssValue(), "blur(0px)",
|
||||||
|
"setCssValue should replace invalid function argument with default");
|
||||||
|
|
||||||
|
info("Test parsing of invalid function argument #2");
|
||||||
|
widget.setCssValue("drop-shadow(whatever)");
|
||||||
|
is(widget.getCssValue(), "drop-shadow()",
|
||||||
|
"setCssValue should replace invalid drop-shadow argument with empty string");
|
||||||
|
|
||||||
|
info("Test parsing of mixed invalid argument");
|
||||||
|
widget.setCssValue("contrast(5%) whatever invert('xxx')");
|
||||||
|
is(widget.getCssValue(), "contrast(5%) invert(0%)",
|
||||||
|
"setCssValue should handle multiple errors");
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,7 @@ function* performTest() {
|
||||||
testParseCssProperty(doc, parser);
|
testParseCssProperty(doc, parser);
|
||||||
testParseCssVar(doc, parser);
|
testParseCssVar(doc, parser);
|
||||||
testParseURL(doc, parser);
|
testParseURL(doc, parser);
|
||||||
|
testParseFilter(doc, parser);
|
||||||
|
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
@ -249,3 +250,13 @@ function testParseURL(doc, parser) {
|
||||||
target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testParseFilter(doc, parser) {
|
||||||
|
let frag = parser.parseCssProperty("filter", "something invalid", {
|
||||||
|
filterSwatchClass: "test-filterswatch"
|
||||||
|
});
|
||||||
|
|
||||||
|
let swatchCount = frag.querySelectorAll(".test-filterswatch").length;
|
||||||
|
is(swatchCount, 1, "filter swatch was created");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const { Cu } = require("chrome");
|
const { Cu, Cc, Ci } = require("chrome");
|
||||||
const { ViewHelpers } = Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm", {});
|
const { ViewHelpers } =
|
||||||
|
Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm",
|
||||||
|
{});
|
||||||
const STRINGS_URI = "chrome://browser/locale/devtools/filterwidget.properties";
|
const STRINGS_URI = "chrome://browser/locale/devtools/filterwidget.properties";
|
||||||
const L10N = new ViewHelpers.L10N(STRINGS_URI);
|
const L10N = new ViewHelpers.L10N(STRINGS_URI);
|
||||||
const {cssTokenizer} = require("devtools/client/shared/css-parsing-utils");
|
const {cssTokenizer} = require("devtools/client/shared/css-parsing-utils");
|
||||||
|
@ -19,6 +21,10 @@ const {cssTokenizer} = require("devtools/client/shared/css-parsing-utils");
|
||||||
loader.lazyGetter(this, "asyncStorage",
|
loader.lazyGetter(this, "asyncStorage",
|
||||||
() => require("devtools/shared/async-storage"));
|
() => require("devtools/shared/async-storage"));
|
||||||
|
|
||||||
|
loader.lazyGetter(this, "DOMUtils", () => {
|
||||||
|
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||||
|
});
|
||||||
|
|
||||||
const DEFAULT_FILTER_TYPE = "length";
|
const DEFAULT_FILTER_TYPE = "length";
|
||||||
const UNIT_MAPPING = {
|
const UNIT_MAPPING = {
|
||||||
percentage: "%",
|
percentage: "%",
|
||||||
|
@ -307,8 +313,11 @@ CSSFilterEditorWidget.prototype = {
|
||||||
let value = startValue + direction * multiplier;
|
let value = startValue + direction * multiplier;
|
||||||
|
|
||||||
const [min, max] = this._definition(filter.name).range;
|
const [min, max] = this._definition(filter.name).range;
|
||||||
value = value < min ? min :
|
if (value < min) {
|
||||||
value > max ? max : value;
|
value = min;
|
||||||
|
} else if (value > max) {
|
||||||
|
value = max;
|
||||||
|
}
|
||||||
|
|
||||||
input.value = fixFloat(value);
|
input.value = fixFloat(value);
|
||||||
|
|
||||||
|
@ -323,8 +332,8 @@ CSSFilterEditorWidget.prototype = {
|
||||||
let {start, end, value} = num;
|
let {start, end, value} = num;
|
||||||
|
|
||||||
let split = input.value.split("");
|
let split = input.value.split("");
|
||||||
let computed = fixFloat(value + direction * multiplier),
|
let computed = fixFloat(value + direction * multiplier);
|
||||||
dotIndex = computed.indexOf(".0");
|
let dotIndex = computed.indexOf(".0");
|
||||||
if (dotIndex > -1) {
|
if (dotIndex > -1) {
|
||||||
computed = computed.slice(0, -2);
|
computed = computed.slice(0, -2);
|
||||||
|
|
||||||
|
@ -343,10 +352,10 @@ CSSFilterEditorWidget.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_input: function(e) {
|
_input: function(e) {
|
||||||
let filterEl = e.target.closest(".filter"),
|
let filterEl = e.target.closest(".filter");
|
||||||
index = this._getFilterElementIndex(filterEl),
|
let index = this._getFilterElementIndex(filterEl);
|
||||||
filter = this.filters[index],
|
let filter = this.filters[index];
|
||||||
def = this._definition(filter.name);
|
let def = this._definition(filter.name);
|
||||||
|
|
||||||
if (def.type !== "string") {
|
if (def.type !== "string") {
|
||||||
e.target.value = fixFloat(e.target.value);
|
e.target.value = fixFloat(e.target.value);
|
||||||
|
@ -366,9 +375,9 @@ CSSFilterEditorWidget.prototype = {
|
||||||
this.el.classList.add("dragging");
|
this.el.classList.add("dragging");
|
||||||
// label-dragging
|
// label-dragging
|
||||||
} else if (e.target.classList.contains("devtools-draglabel")) {
|
} else if (e.target.classList.contains("devtools-draglabel")) {
|
||||||
let label = e.target,
|
let label = e.target;
|
||||||
input = filterEl.querySelector("input"),
|
let input = filterEl.querySelector("input");
|
||||||
index = this._getFilterElementIndex(filterEl);
|
let index = this._getFilterElementIndex(filterEl);
|
||||||
|
|
||||||
this._dragging = {
|
this._dragging = {
|
||||||
index, label, input,
|
index, label, input,
|
||||||
|
@ -386,19 +395,7 @@ CSSFilterEditorWidget.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = select.value;
|
const key = select.value;
|
||||||
const def = this._definition(key);
|
this.add(key, null);
|
||||||
// UNIT_MAPPING[string] is an empty string (falsy), so
|
|
||||||
// using || doesn't work here
|
|
||||||
const unitLabel = typeof UNIT_MAPPING[def.type] === "undefined" ?
|
|
||||||
UNIT_MAPPING[DEFAULT_FILTER_TYPE] :
|
|
||||||
UNIT_MAPPING[def.type];
|
|
||||||
|
|
||||||
// string-type filters have no default value but a placeholder instead
|
|
||||||
if (!unitLabel) {
|
|
||||||
this.add(key);
|
|
||||||
} else {
|
|
||||||
this.add(key, def.range[0] + unitLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
|
@ -423,9 +420,9 @@ CSSFilterEditorWidget.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_dragFilterElement: function(e) {
|
_dragFilterElement: function(e) {
|
||||||
const rect = this.filtersList.getBoundingClientRect(),
|
const rect = this.filtersList.getBoundingClientRect();
|
||||||
top = e.pageY - LIST_PADDING,
|
let top = e.pageY - LIST_PADDING;
|
||||||
bottom = e.pageY + LIST_PADDING;
|
let bottom = e.pageY + LIST_PADDING;
|
||||||
// don't allow dragging over top/bottom of list
|
// don't allow dragging over top/bottom of list
|
||||||
if (top < rect.top || bottom > rect.bottom) {
|
if (top < rect.top || bottom > rect.bottom) {
|
||||||
return;
|
return;
|
||||||
|
@ -439,8 +436,11 @@ CSSFilterEditorWidget.prototype = {
|
||||||
// change is the number of _steps_ taken from initial position
|
// change is the number of _steps_ taken from initial position
|
||||||
// i.e. how many elements we have passed
|
// i.e. how many elements we have passed
|
||||||
let change = delta / LIST_ITEM_HEIGHT;
|
let change = delta / LIST_ITEM_HEIGHT;
|
||||||
change = change > 0 ? Math.floor(change) :
|
if (change > 0) {
|
||||||
change < 0 ? Math.ceil(change) : change;
|
change = Math.floor(change);
|
||||||
|
} else if (change < 0) {
|
||||||
|
change = Math.ceil(change);
|
||||||
|
}
|
||||||
|
|
||||||
const children = this.filtersList.children;
|
const children = this.filtersList.children;
|
||||||
const index = [...children].indexOf(filterEl);
|
const index = [...children].indexOf(filterEl);
|
||||||
|
@ -489,8 +489,11 @@ CSSFilterEditorWidget.prototype = {
|
||||||
|
|
||||||
const filter = this.filters[dragging.index];
|
const filter = this.filters[dragging.index];
|
||||||
const [min, max] = this._definition(filter.name).range;
|
const [min, max] = this._definition(filter.name).range;
|
||||||
value = value < min ? min :
|
if (value < min) {
|
||||||
value > max ? max : value;
|
value = min;
|
||||||
|
} else if (value > max) {
|
||||||
|
value = max;
|
||||||
|
}
|
||||||
|
|
||||||
input.value = fixFloat(value);
|
input.value = fixFloat(value);
|
||||||
|
|
||||||
|
@ -551,8 +554,8 @@ CSSFilterEditorWidget.prototype = {
|
||||||
_savePreset: function(e) {
|
_savePreset: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
let name = this.addPresetInput.value,
|
let name = this.addPresetInput.value;
|
||||||
value = this.getCssValue();
|
let value = this.getCssValue();
|
||||||
|
|
||||||
if (!name || !value || value === "none") {
|
if (!name || !value || value === "none") {
|
||||||
this.emit("preset-save-error");
|
this.emit("preset-save-error");
|
||||||
|
@ -593,9 +596,9 @@ CSSFilterEditorWidget.prototype = {
|
||||||
|
|
||||||
let el = base.cloneNode(true);
|
let el = base.cloneNode(true);
|
||||||
|
|
||||||
let [name, value] = el.children,
|
let [name, value] = el.children;
|
||||||
label = name.children[1],
|
let label = name.children[1];
|
||||||
[input, unitPreview] = value.children;
|
let [input, unitPreview] = value.children;
|
||||||
|
|
||||||
let min, max;
|
let min, max;
|
||||||
if (def.range) {
|
if (def.range) {
|
||||||
|
@ -637,7 +640,8 @@ CSSFilterEditorWidget.prototype = {
|
||||||
this.filtersList.appendChild(el);
|
this.filtersList.appendChild(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastInput = this.filtersList.querySelector(`.filter:last-of-type input`);
|
let lastInput =
|
||||||
|
this.filtersList.querySelector(`.filter:last-of-type input`);
|
||||||
if (lastInput) {
|
if (lastInput) {
|
||||||
lastInput.focus();
|
lastInput.focus();
|
||||||
// move cursor to end of input
|
// move cursor to end of input
|
||||||
|
@ -685,6 +689,7 @@ CSSFilterEditorWidget.prototype = {
|
||||||
* filter's definition
|
* filter's definition
|
||||||
*/
|
*/
|
||||||
_definition: function(name) {
|
_definition: function(name) {
|
||||||
|
name = name.toLowerCase();
|
||||||
return filterList.find(a => a.name === name);
|
return filterList.find(a => a.name === name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -708,6 +713,14 @@ CSSFilterEditorWidget.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let {name, value} of tokenizeFilterValue(cssValue)) {
|
for (let {name, value} of tokenizeFilterValue(cssValue)) {
|
||||||
|
// If the specified value is invalid, replace it with the
|
||||||
|
// default.
|
||||||
|
if (name !== "url") {
|
||||||
|
if (!DOMUtils.cssPropertyIsValid("filter", name + "(" + value + ")")) {
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.add(name, value);
|
this.add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,15 +735,31 @@ CSSFilterEditorWidget.prototype = {
|
||||||
* filter name (e.g. blur)
|
* filter name (e.g. blur)
|
||||||
* @param {String} value
|
* @param {String} value
|
||||||
* value of the filter (e.g. 30px, 20%)
|
* value of the filter (e.g. 30px, 20%)
|
||||||
|
* If this is |null|, then a default value may be supplied.
|
||||||
* @return {Number}
|
* @return {Number}
|
||||||
* The index of the new filter in the current list of filters
|
* The index of the new filter in the current list of filters
|
||||||
*/
|
*/
|
||||||
add: function(name, value = "") {
|
add: function(name, value) {
|
||||||
const def = this._definition(name);
|
const def = this._definition(name);
|
||||||
if (!def) {
|
if (!def) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value === null) {
|
||||||
|
// UNIT_MAPPING[string] is an empty string (falsy), so
|
||||||
|
// using || doesn't work here
|
||||||
|
const unitLabel = typeof UNIT_MAPPING[def.type] === "undefined" ?
|
||||||
|
UNIT_MAPPING[DEFAULT_FILTER_TYPE] :
|
||||||
|
UNIT_MAPPING[def.type];
|
||||||
|
|
||||||
|
// string-type filters have no default value but a placeholder instead
|
||||||
|
if (!unitLabel) {
|
||||||
|
value = "";
|
||||||
|
} else {
|
||||||
|
value = def.range[0] + unitLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let unit = def.type === "string"
|
let unit = def.type === "string"
|
||||||
? ""
|
? ""
|
||||||
: (/[a-zA-Z%]+/.exec(value) || [])[0];
|
: (/[a-zA-Z%]+/.exec(value) || [])[0];
|
||||||
|
@ -752,7 +781,7 @@ CSSFilterEditorWidget.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = this.filters.push({value, unit, name: def.name}) - 1;
|
const index = this.filters.push({value, unit, name}) - 1;
|
||||||
this.emit("updated", this.getCssValue());
|
this.emit("updated", this.getCssValue());
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
|
@ -940,8 +969,8 @@ function getNeighbourNumber(string, index) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let left = /-?[0-9.]*$/.exec(string.slice(0, index)),
|
let left = /-?[0-9.]*$/.exec(string.slice(0, index));
|
||||||
right = /-?[0-9.]*/.exec(string.slice(index));
|
let right = /-?[0-9.]*/.exec(string.slice(index));
|
||||||
|
|
||||||
left = left ? left[0] : "";
|
left = left ? left[0] : "";
|
||||||
right = right ? right[0] : "";
|
right = right ? right[0] : "";
|
||||||
|
|
|
@ -19,9 +19,24 @@
|
||||||
--row-hover-background-color: rgba(76,158,217,0.2);
|
--row-hover-background-color: rgba(76,158,217,0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html, .theme-body, #app, #memory-tool, #memory-tool-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-body {
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--theme-body-background);
|
||||||
|
}
|
||||||
|
|
||||||
#memory-tool-container {
|
#memory-tool-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
--toolbar-height: 20px;
|
||||||
|
/**
|
||||||
|
* If --heap-tree-row-height changes, be sure to change HEAP_TREE_ROW_HEIGHT
|
||||||
|
* in `devtools/client/memory/components/heap.js`.
|
||||||
|
*/
|
||||||
|
--heap-tree-row-height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +78,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 20px;
|
height: var(--toolbar-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,13 +106,18 @@
|
||||||
width: 186px;
|
width: 186px;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
background-color: var(--theme-toolbar-background);
|
||||||
|
border-color: var(--theme-splitter-color);
|
||||||
|
color: var(--theme-body-color-alt);
|
||||||
|
border-left-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list > li {
|
.list > li {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
color: var(--theme-body-color);
|
color: var(--theme-body-color);
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid rgba(128,128,128,0.15);
|
||||||
border-top: 1px solid rgba(128,128,128,0.15);
|
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +147,9 @@
|
||||||
|
|
||||||
#heap-view {
|
#heap-view {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
border-color: var(--theme-splitter-color);
|
||||||
|
color: var(--theme-body-color)
|
||||||
|
border-left-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#heap-view .heap-view-panel {
|
#heap-view .heap-view-panel {
|
||||||
|
@ -138,65 +161,86 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heap View
|
* Heap Tree View
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.heap-view {
|
#heap-view .theme-twisty {
|
||||||
position: relative;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-view .theme-twisty {
|
.tree {
|
||||||
text-align: end;
|
height: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item {
|
.tree .header {
|
||||||
|
height: 17px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--theme-body-color);
|
||||||
|
background-color: var(--theme-tab-toolbar-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree span {
|
||||||
|
border-left-color: var(--cell-border-color);
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node {
|
||||||
|
height: var(--heap-tree-row-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heap-tree-item, .header {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
/* display: none; */
|
height: var(--heap-tree-row-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item[expanded] {
|
.heap-tree-item span, .header span {
|
||||||
display: block;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item:nth-child(2n) {
|
.tree-node:nth-child(2n) {
|
||||||
background-color: var(--row-alt-background-color);
|
background-color: var(--row-alt-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item:hover {
|
.tree-node:hover {
|
||||||
background-color: var(--row-hover-background-color);
|
background-color: var(--row-hover-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item:focus {
|
.tree-node:focus {
|
||||||
background-color: var(--theme-selection-background);
|
background-color: var(--theme-selection-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item:focus description {
|
.header {
|
||||||
color: var(--theme-selection-color) !important;
|
background-color: var(--theme-tab-toolbar-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-item:focus .call-tree-cell {
|
.header span {
|
||||||
-moz-border-end-color: var(--focus-cell-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.heap-tree-cell[type="bytes"], .heap-tree-cell[type="count"] {
|
|
||||||
position: absolute;
|
|
||||||
text-align: right;
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heap-tree-cell[type="name"] {
|
|
||||||
width: 150px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: block;
|
text-align: center;
|
||||||
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-cell[type="count"] {
|
.heap-tree-item-bytes,
|
||||||
left: 300px;
|
.heap-tree-item-count,
|
||||||
|
.heap-tree-item-total-bytes,
|
||||||
|
.heap-tree-item-total-count {
|
||||||
|
text-align: right;
|
||||||
|
border-right: var(--cell-border-color) 1px solid;
|
||||||
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heap-tree-cell[type="bytes"] {
|
.heap-tree-item-count,
|
||||||
left: 250px;
|
.heap-tree-item-total-count {
|
||||||
|
width: 5vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heap-tree-item-bytes,
|
||||||
|
.heap-tree-item-total-bytes {
|
||||||
|
width: 7vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heap-tree-item-name {
|
||||||
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,6 +549,15 @@
|
||||||
* Marker colors
|
* Marker colors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
menuitem.marker-color-graphs-full-red:before,
|
||||||
|
.marker-color-graphs-full-red {
|
||||||
|
background-color: var(--theme-graphs-full-red);
|
||||||
|
}
|
||||||
|
menuitem.marker-color-graphs-full-blue:before,
|
||||||
|
.marker-color-graphs-full-blue {
|
||||||
|
background-color: var(--theme-graphs-full-blue);
|
||||||
|
}
|
||||||
|
|
||||||
menuitem.marker-color-graphs-green:before,
|
menuitem.marker-color-graphs-green:before,
|
||||||
.marker-color-graphs-green {
|
.marker-color-graphs-green {
|
||||||
background-color: var(--theme-graphs-green);
|
background-color: var(--theme-graphs-green);
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
--theme-graphs-orange: #d97e00;
|
--theme-graphs-orange: #d97e00;
|
||||||
--theme-graphs-red: #e57180;
|
--theme-graphs-red: #e57180;
|
||||||
--theme-graphs-grey: #cccccc;
|
--theme-graphs-grey: #cccccc;
|
||||||
|
--theme-graphs-full-red: #f00;
|
||||||
|
--theme-graphs-full-blue: #00f;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root.theme-dark {
|
:root.theme-dark {
|
||||||
|
@ -90,4 +92,6 @@
|
||||||
--theme-graphs-orange: #d96629;
|
--theme-graphs-orange: #d96629;
|
||||||
--theme-graphs-red: #eb5368;
|
--theme-graphs-red: #eb5368;
|
||||||
--theme-graphs-grey: #757873;
|
--theme-graphs-grey: #757873;
|
||||||
|
--theme-graphs-full-red: #f00;
|
||||||
|
--theme-graphs-full-blue: #00f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,10 @@ OutputParser.prototype = {
|
||||||
safeCssPropertySupportsType(name, DOMUtils.TYPE_COLOR) ||
|
safeCssPropertySupportsType(name, DOMUtils.TYPE_COLOR) ||
|
||||||
safeCssPropertySupportsType(name, DOMUtils.TYPE_GRADIENT);
|
safeCssPropertySupportsType(name, DOMUtils.TYPE_GRADIENT);
|
||||||
|
|
||||||
if (this._cssPropertySupportsValue(name, value)) {
|
// The filter property is special in that we want to show the
|
||||||
|
// swatch even if the value is invalid, because this way the user
|
||||||
|
// can easily use the editor to fix it.
|
||||||
|
if (options.expectFilter || this._cssPropertySupportsValue(name, value)) {
|
||||||
return this._parse(value, options);
|
return this._parse(value, options);
|
||||||
}
|
}
|
||||||
this._appendTextNode(value);
|
this._appendTextNode(value);
|
||||||
|
|
|
@ -60,8 +60,6 @@ NS_IMETHODIMP AudioChannelAgent::GetAudioChannelType(int32_t *aAudioChannelType)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* boolean init (in nsIDOMWindow window, in long channelType,
|
|
||||||
* in nsIAudioChannelAgentCallback callback); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
AudioChannelAgent::Init(nsIDOMWindow* aWindow, int32_t aChannelType,
|
AudioChannelAgent::Init(nsIDOMWindow* aWindow, int32_t aChannelType,
|
||||||
nsIAudioChannelAgentCallback *aCallback)
|
nsIAudioChannelAgentCallback *aCallback)
|
||||||
|
@ -70,8 +68,6 @@ AudioChannelAgent::Init(nsIDOMWindow* aWindow, int32_t aChannelType,
|
||||||
/* useWeakRef = */ false);
|
/* useWeakRef = */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* boolean initWithWeakCallback (in nsIDOMWindow window, in long channelType,
|
|
||||||
* in nsIAudioChannelAgentCallback callback); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
AudioChannelAgent::InitWithWeakCallback(nsIDOMWindow* aWindow,
|
AudioChannelAgent::InitWithWeakCallback(nsIDOMWindow* aWindow,
|
||||||
int32_t aChannelType,
|
int32_t aChannelType,
|
||||||
|
|
|
@ -323,13 +323,16 @@ AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel,
|
||||||
MOZ_ASSERT(aVolume && aMuted);
|
MOZ_ASSERT(aVolume && aMuted);
|
||||||
MOZ_ASSERT(aAudioChannel < NUMBER_OF_AUDIO_CHANNELS);
|
MOZ_ASSERT(aAudioChannel < NUMBER_OF_AUDIO_CHANNELS);
|
||||||
|
|
||||||
*aVolume = 1.0;
|
|
||||||
*aMuted = false;
|
|
||||||
|
|
||||||
if (!aWindow || !aWindow->IsOuterWindow()) {
|
if (!aWindow || !aWindow->IsOuterWindow()) {
|
||||||
|
*aVolume = 0.0;
|
||||||
|
*aMuted = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*aVolume = 1.0;
|
||||||
|
*aMuted = false;
|
||||||
|
|
||||||
AudioChannelWindow* winData = nullptr;
|
AudioChannelWindow* winData = nullptr;
|
||||||
nsCOMPtr<nsPIDOMWindow> window = aWindow;
|
nsCOMPtr<nsPIDOMWindow> window = aWindow;
|
||||||
|
|
||||||
|
|
|
@ -448,9 +448,6 @@ Exception::ToString(nsACString& _retval)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void initialize (in AUTF8String aMessage, in nsresult aResult,
|
|
||||||
* in AUTF8String aName, in nsIStackFrame aLocation,
|
|
||||||
* in nsISupports aData, in nsIException aInner); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
Exception::Initialize(const nsACString& aMessage, nsresult aResult,
|
Exception::Initialize(const nsACString& aMessage, nsresult aResult,
|
||||||
const nsACString& aName, nsIStackFrame *aLocation,
|
const nsACString& aName, nsIStackFrame *aLocation,
|
||||||
|
|
|
@ -5109,6 +5109,14 @@ nsDocument::DispatchContentLoadedEvents()
|
||||||
NS_LITERAL_STRING("DOMContentLoaded"),
|
NS_LITERAL_STRING("DOMContentLoaded"),
|
||||||
true, false);
|
true, false);
|
||||||
|
|
||||||
|
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
|
||||||
|
nsIDocShell* docShell = this->GetDocShell();
|
||||||
|
|
||||||
|
if (timelines && timelines->HasConsumer(docShell)) {
|
||||||
|
timelines->AddMarkerForDocShell(
|
||||||
|
docShell, "document::DOMContentLoaded", MarkerTracingType::TIMESTAMP);
|
||||||
|
}
|
||||||
|
|
||||||
if (mTiming) {
|
if (mTiming) {
|
||||||
mTiming->NotifyDOMContentLoadedEnd(nsIDocument::GetDocumentURI());
|
mTiming->NotifyDOMContentLoadedEnd(nsIDocument::GetDocumentURI());
|
||||||
}
|
}
|
||||||
|
@ -7598,7 +7606,6 @@ nsIDocument::GetDocumentURIObject() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// readonly attribute DOMString compatMode;
|
|
||||||
// Returns "BackCompat" if we are in quirks mode, "CSS1Compat" if we are
|
// Returns "BackCompat" if we are in quirks mode, "CSS1Compat" if we are
|
||||||
// in almost standards or full standards mode. See bug 105640. This was
|
// in almost standards or full standards mode. See bug 105640. This was
|
||||||
// implemented to match MSIE's compatMode property.
|
// implemented to match MSIE's compatMode property.
|
||||||
|
|
|
@ -2856,8 +2856,7 @@ nsObjectLoadingContent::ScriptRequestPluginInstance(JSContext* aCx,
|
||||||
aCx == nsContentUtils::GetCurrentJSContext());
|
aCx == nsContentUtils::GetCurrentJSContext());
|
||||||
bool callerIsContentJS = (nsContentUtils::GetCurrentJSContext() &&
|
bool callerIsContentJS = (nsContentUtils::GetCurrentJSContext() &&
|
||||||
!nsContentUtils::IsCallerChrome() &&
|
!nsContentUtils::IsCallerChrome() &&
|
||||||
!nsContentUtils::IsCallerContentXBL() &&
|
!nsContentUtils::IsCallerContentXBL());
|
||||||
JS_IsRunning(aCx));
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> thisContent =
|
nsCOMPtr<nsIContent> thisContent =
|
||||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "nsCORSListenerProxy.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using mozilla::net::ReferrerPolicy;
|
using mozilla::net::ReferrerPolicy;
|
||||||
|
@ -42,7 +41,7 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
|
nsresult LoadDocument(nsIChannel* aChannel,
|
||||||
bool aChannelIsSync, bool aForceToXML,
|
bool aChannelIsSync, bool aForceToXML,
|
||||||
ReferrerPolicy aReferrerPolicy,
|
ReferrerPolicy aReferrerPolicy,
|
||||||
nsIDOMDocument** aResult);
|
nsIDOMDocument** aResult);
|
||||||
|
@ -130,31 +129,31 @@ NS_IMPL_ISUPPORTS(nsSyncLoader,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||||
nsIPrincipal *aLoaderPrincipal,
|
|
||||||
bool aChannelIsSync,
|
bool aChannelIsSync,
|
||||||
bool aForceToXML,
|
bool aForceToXML,
|
||||||
ReferrerPolicy aReferrerPolicy,
|
ReferrerPolicy aReferrerPolicy,
|
||||||
nsIDOMDocument **aResult)
|
nsIDOMDocument **aResult)
|
||||||
{
|
{
|
||||||
|
NS_ENSURE_ARG(aChannel);
|
||||||
NS_ENSURE_ARG_POINTER(aResult);
|
NS_ENSURE_ARG_POINTER(aResult);
|
||||||
*aResult = nullptr;
|
*aResult = nullptr;
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> loaderUri;
|
|
||||||
if (aLoaderPrincipal) {
|
|
||||||
aLoaderPrincipal->GetURI(getter_AddRefs(loaderUri));
|
|
||||||
}
|
|
||||||
|
|
||||||
mChannel = aChannel;
|
mChannel = aChannel;
|
||||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
|
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
|
||||||
if (http) {
|
if (http) {
|
||||||
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
||||||
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
|
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
|
||||||
false);
|
false);
|
||||||
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||||
|
if (loadInfo) {
|
||||||
|
nsCOMPtr<nsIURI> loaderUri;
|
||||||
|
loadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(loaderUri));
|
||||||
if (loaderUri) {
|
if (loaderUri) {
|
||||||
http->SetReferrerWithPolicy(loaderUri, aReferrerPolicy);
|
http->SetReferrerWithPolicy(loaderUri, aReferrerPolicy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hook us up to listen to redirects and the like.
|
// Hook us up to listen to redirects and the like.
|
||||||
// Do this before setting up the cross-site proxy since
|
// Do this before setting up the cross-site proxy since
|
||||||
|
@ -186,14 +185,6 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||||
listener.swap(forceListener);
|
listener.swap(forceListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aLoaderPrincipal) {
|
|
||||||
RefPtr<nsCORSListenerProxy> corsListener =
|
|
||||||
new nsCORSListenerProxy(listener, aLoaderPrincipal, false);
|
|
||||||
rv = corsListener->Init(mChannel, DataURIHandling::Disallow);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
listener = corsListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aChannelIsSync) {
|
if (aChannelIsSync) {
|
||||||
rv = PushSyncStream(listener);
|
rv = PushSyncStream(listener);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +217,7 @@ nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener)
|
||||||
mAsyncLoadStatus = NS_OK;
|
mAsyncLoadStatus = NS_OK;
|
||||||
|
|
||||||
// Start reading from the channel
|
// Start reading from the channel
|
||||||
nsresult rv = mChannel->AsyncOpen(this, nullptr);
|
nsresult rv = mChannel->AsyncOpen2(this);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
// process events until we're finished.
|
// process events until we're finished.
|
||||||
|
@ -254,7 +245,7 @@ nsresult
|
||||||
nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
|
nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIInputStream> in;
|
nsCOMPtr<nsIInputStream> in;
|
||||||
nsresult rv = mChannel->Open(getter_AddRefs(in));
|
nsresult rv = mChannel->Open2(getter_AddRefs(in));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mLoading = true;
|
mLoading = true;
|
||||||
|
@ -309,8 +300,12 @@ nsSyncLoader::GetInterface(const nsIID & aIID,
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsresult
|
nsresult
|
||||||
nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
nsSyncLoadService::LoadDocument(nsIURI *aURI,
|
||||||
nsILoadGroup *aLoadGroup, bool aForceToXML,
|
nsContentPolicyType aContentPolicyType,
|
||||||
|
nsIPrincipal *aLoaderPrincipal,
|
||||||
|
nsSecurityFlags aSecurityFlags,
|
||||||
|
nsILoadGroup *aLoadGroup,
|
||||||
|
bool aForceToXML,
|
||||||
ReferrerPolicy aReferrerPolicy,
|
ReferrerPolicy aReferrerPolicy,
|
||||||
nsIDOMDocument** aResult)
|
nsIDOMDocument** aResult)
|
||||||
{
|
{
|
||||||
|
@ -318,8 +313,8 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
||||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||||
aURI,
|
aURI,
|
||||||
aLoaderPrincipal,
|
aLoaderPrincipal,
|
||||||
nsILoadInfo::SEC_NORMAL,
|
aSecurityFlags,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
aContentPolicyType,
|
||||||
aLoadGroup);
|
aLoadGroup);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
@ -328,15 +323,12 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isChrome = false, isResource = false;
|
bool isChrome = false, isResource = false;
|
||||||
bool isSync = (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
|
bool isSync =
|
||||||
isChrome) ||
|
(NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) ||
|
||||||
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
|
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) && isResource);
|
||||||
isResource);
|
|
||||||
|
|
||||||
RefPtr<nsSyncLoader> loader = new nsSyncLoader();
|
RefPtr<nsSyncLoader> loader = new nsSyncLoader();
|
||||||
return loader->LoadDocument(channel, aLoaderPrincipal, isSync,
|
return loader->LoadDocument(channel, isSync, aForceToXML,
|
||||||
aForceToXML, aReferrerPolicy, aResult);
|
aReferrerPolicy, aResult);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
|
|
@ -29,17 +29,22 @@ public:
|
||||||
* Synchronously load the document from the specified URI.
|
* Synchronously load the document from the specified URI.
|
||||||
*
|
*
|
||||||
* @param aURI URI to load the document from.
|
* @param aURI URI to load the document from.
|
||||||
|
* @param aContentPolicyType contentPolicyType to be set on the channel
|
||||||
* @param aLoaderPrincipal Principal of loading document. For security
|
* @param aLoaderPrincipal Principal of loading document. For security
|
||||||
* checks and referrer header. May be null if no
|
* checks and referrer header.
|
||||||
* security checks should be done.
|
* @param aSecurityFlags securityFlags to be set on the channel
|
||||||
* @param aLoadGroup The loadgroup to use for loading the document.
|
* @param aLoadGroup The loadgroup to use for loading the document.
|
||||||
* @param aForceToXML Whether to parse the document as XML, regardless of
|
* @param aForceToXML Whether to parse the document as XML, regardless of
|
||||||
* content type.
|
* content type.
|
||||||
* @param referrerPolicy Referrer policy.
|
* @param referrerPolicy Referrer policy.
|
||||||
* @param aResult [out] The document loaded from the URI.
|
* @param aResult [out] The document loaded from the URI.
|
||||||
*/
|
*/
|
||||||
static nsresult LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
static nsresult LoadDocument(nsIURI *aURI,
|
||||||
nsILoadGroup *aLoadGroup, bool aForceToXML,
|
nsContentPolicyType aContentPolicyType,
|
||||||
|
nsIPrincipal *aLoaderPrincipal,
|
||||||
|
nsSecurityFlags aSecurityFlags,
|
||||||
|
nsILoadGroup *aLoadGroup,
|
||||||
|
bool aForceToXML,
|
||||||
mozilla::net::ReferrerPolicy aReferrerPolicy,
|
mozilla::net::ReferrerPolicy aReferrerPolicy,
|
||||||
nsIDOMDocument** aResult);
|
nsIDOMDocument** aResult);
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,9 @@ ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
struct ErrorResult::Message {
|
struct ErrorResult::Message {
|
||||||
|
Message() { MOZ_COUNT_CTOR(ErrorResult::Message); }
|
||||||
|
~Message() { MOZ_COUNT_DTOR(ErrorResult::Message); }
|
||||||
|
|
||||||
nsTArray<nsString> mArgs;
|
nsTArray<nsString> mArgs;
|
||||||
dom::ErrNum mErrorNumber;
|
dom::ErrNum mErrorNumber;
|
||||||
|
|
||||||
|
|
|
@ -3262,8 +3262,7 @@ class IDLValue(IDLObject):
|
||||||
elif self.type.isInteger() and type.isFloat():
|
elif self.type.isInteger() and type.isFloat():
|
||||||
# Convert an integer literal into float
|
# Convert an integer literal into float
|
||||||
if -2**24 <= self.value <= 2**24:
|
if -2**24 <= self.value <= 2**24:
|
||||||
floatType = BuiltinTypes[IDLBuiltinType.Types.float]
|
return IDLValue(self.location, type, float(self.value))
|
||||||
return IDLValue(self.location, floatType, float(self.value))
|
|
||||||
else:
|
else:
|
||||||
raise WebIDLError("Converting value %s to %s will lose precision." %
|
raise WebIDLError("Converting value %s to %s will lose precision." %
|
||||||
(self.value, type), [location])
|
(self.value, type), [location])
|
||||||
|
@ -3281,7 +3280,7 @@ class IDLValue(IDLObject):
|
||||||
math.isnan(self.value))):
|
math.isnan(self.value))):
|
||||||
raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
|
raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
|
||||||
% self.value, [location])
|
% self.value, [location])
|
||||||
return self
|
return IDLValue(self.location, type, self.value)
|
||||||
elif self.type.isString() and type.isUSVString():
|
elif self.type.isString() and type.isUSVString():
|
||||||
# Allow USVStrings to use default value just like
|
# Allow USVStrings to use default value just like
|
||||||
# DOMString. No coercion is required in this case as Codegen.py
|
# DOMString. No coercion is required in this case as Codegen.py
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
import WebIDL
|
import WebIDL
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
("::TestConsts::zero", "zero", "Byte", 0),
|
||||||
|
("::TestConsts::b", "b", "Byte", -1),
|
||||||
|
("::TestConsts::o", "o", "Octet", 2),
|
||||||
|
("::TestConsts::s", "s", "Short", -3),
|
||||||
|
("::TestConsts::us", "us", "UnsignedShort", 4),
|
||||||
|
("::TestConsts::l", "l", "Long", -5),
|
||||||
|
("::TestConsts::ul", "ul", "UnsignedLong", 6),
|
||||||
|
("::TestConsts::ull", "ull", "UnsignedLongLong", 7),
|
||||||
|
("::TestConsts::ll", "ll", "LongLong", -8),
|
||||||
|
("::TestConsts::t", "t", "Boolean", True),
|
||||||
|
("::TestConsts::f", "f", "Boolean", False),
|
||||||
|
("::TestConsts::n", "n", "BooleanOrNull", None),
|
||||||
|
("::TestConsts::nt", "nt", "BooleanOrNull", True),
|
||||||
|
("::TestConsts::nf", "nf", "BooleanOrNull", False),
|
||||||
|
("::TestConsts::fl", "fl", "Float", 0.2),
|
||||||
|
("::TestConsts::db", "db", "Double", 0.2),
|
||||||
|
("::TestConsts::ufl", "ufl", "UnrestrictedFloat", 0.2),
|
||||||
|
("::TestConsts::udb", "udb", "UnrestrictedDouble", 0.2),
|
||||||
|
("::TestConsts::fli", "fli", "Float", 2),
|
||||||
|
("::TestConsts::dbi", "dbi", "Double", 2),
|
||||||
|
("::TestConsts::ufli", "ufli", "UnrestrictedFloat", 2),
|
||||||
|
("::TestConsts::udbi", "udbi", "UnrestrictedDouble", 2),
|
||||||
|
]
|
||||||
|
|
||||||
def WebIDLTest(parser, harness):
|
def WebIDLTest(parser, harness):
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface TestConsts {
|
interface TestConsts {
|
||||||
|
@ -17,6 +42,14 @@ def WebIDLTest(parser, harness):
|
||||||
const boolean? n = null;
|
const boolean? n = null;
|
||||||
const boolean? nt = true;
|
const boolean? nt = true;
|
||||||
const boolean? nf = false;
|
const boolean? nf = false;
|
||||||
|
const float fl = 0.2;
|
||||||
|
const double db = 0.2;
|
||||||
|
const unrestricted float ufl = 0.2;
|
||||||
|
const unrestricted double udb = 0.2;
|
||||||
|
const float fli = 2;
|
||||||
|
const double dbi = 2;
|
||||||
|
const unrestricted float ufli = 2;
|
||||||
|
const unrestricted double udbi = 2;
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -29,11 +62,9 @@ def WebIDLTest(parser, harness):
|
||||||
"Should be an IDLInterface")
|
"Should be an IDLInterface")
|
||||||
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName")
|
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName")
|
||||||
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
||||||
harness.check(len(iface.members), 14, "Expect 14 members")
|
harness.check(len(iface.members), len(expected), "Expect %s members" % len(expected))
|
||||||
|
|
||||||
consts = iface.members
|
for (const, (QName, name, type, value)) in zip(iface.members, expected):
|
||||||
|
|
||||||
def checkConst(const, QName, name, type, value):
|
|
||||||
harness.ok(isinstance(const, WebIDL.IDLConst),
|
harness.ok(isinstance(const, WebIDL.IDLConst),
|
||||||
"Should be an IDLConst")
|
"Should be an IDLConst")
|
||||||
harness.ok(const.isConst(), "Const is a const")
|
harness.ok(const.isConst(), "Const is a const")
|
||||||
|
@ -47,18 +78,3 @@ def WebIDLTest(parser, harness):
|
||||||
"Const's value has the same type as the type")
|
"Const's value has the same type as the type")
|
||||||
harness.check(const.value.value, value, "Const value has the right value.")
|
harness.check(const.value.value, value, "Const value has the right value.")
|
||||||
|
|
||||||
checkConst(consts[0], "::TestConsts::zero", "zero", "Byte", 0)
|
|
||||||
checkConst(consts[1], "::TestConsts::b", "b", "Byte", -1)
|
|
||||||
checkConst(consts[2], "::TestConsts::o", "o", "Octet", 2)
|
|
||||||
checkConst(consts[3], "::TestConsts::s", "s", "Short", -3)
|
|
||||||
checkConst(consts[4], "::TestConsts::us", "us", "UnsignedShort", 4)
|
|
||||||
checkConst(consts[5], "::TestConsts::l", "l", "Long", -5)
|
|
||||||
checkConst(consts[6], "::TestConsts::ul", "ul", "UnsignedLong", 6)
|
|
||||||
checkConst(consts[7], "::TestConsts::ull", "ull", "UnsignedLongLong", 7)
|
|
||||||
checkConst(consts[8], "::TestConsts::ll", "ll", "LongLong", -8)
|
|
||||||
checkConst(consts[9], "::TestConsts::t", "t", "Boolean", True)
|
|
||||||
checkConst(consts[10], "::TestConsts::f", "f", "Boolean", False)
|
|
||||||
checkConst(consts[11], "::TestConsts::n", "n", "BooleanOrNull", None)
|
|
||||||
checkConst(consts[12], "::TestConsts::nt", "nt", "BooleanOrNull", True)
|
|
||||||
checkConst(consts[13], "::TestConsts::nf", "nf", "BooleanOrNull", False)
|
|
||||||
|
|
||||||
|
|
|
@ -1414,7 +1414,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||||
mIsSkiaGL = true;
|
mIsSkiaGL = true;
|
||||||
} else {
|
} else {
|
||||||
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
|
gfxCriticalNote << "Failed to create a SkiaGL DrawTarget, falling back to software\n";
|
||||||
mode = RenderingMode::SoftwareBackendMode;
|
mode = RenderingMode::SoftwareBackendMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,6 +1470,10 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||||
mTarget = sErrorTarget;
|
mTarget = sErrorTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop a note in the debug builds if we ever use accelerated Skia canvas.
|
||||||
|
if (mIsSkiaGL && mTarget && mTarget->GetType() == DrawTargetType::HARDWARE_RASTER) {
|
||||||
|
gfxWarningOnce() << "Using SkiaGL canvas.";
|
||||||
|
}
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5329,9 +5333,6 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
|
||||||
JS::ToInt32(dirtyHeight));
|
JS::ToInt32(dirtyHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
// void putImageData (in ImageData d, in float x, in float y);
|
|
||||||
// void putImageData (in ImageData d, in double x, in double y, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
|
CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
|
||||||
dom::Uint8ClampedArray* aArray,
|
dom::Uint8ClampedArray* aArray,
|
||||||
|
|
|
@ -59,8 +59,6 @@ NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void newButtonEvent (in uint32_t index, in uint32_t button,
|
|
||||||
in boolean pressed); */
|
|
||||||
NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||||
uint32_t aButton,
|
uint32_t aButton,
|
||||||
bool aPressed)
|
bool aPressed)
|
||||||
|
@ -69,8 +67,6 @@ NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void newButtonEvent (in uint32_t index, in uint32_t button,
|
|
||||||
in boolean pressed, double value); */
|
|
||||||
NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
||||||
uint32_t aButton,
|
uint32_t aButton,
|
||||||
bool aPressed,
|
bool aPressed,
|
||||||
|
@ -80,8 +76,6 @@ NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis,
|
|
||||||
in double value); */
|
|
||||||
NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
|
NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
|
||||||
uint32_t aAxis,
|
uint32_t aAxis,
|
||||||
double aValue)
|
double aValue)
|
||||||
|
|
|
@ -3194,8 +3194,6 @@ ConvertToMidasInternalCommand(const nsAString & inCommandID,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: don't let this call do anything if the page is not done loading */
|
/* TODO: don't let this call do anything if the page is not done loading */
|
||||||
/* boolean execCommand(in DOMString commandID, in boolean doShowUI,
|
|
||||||
in DOMString value); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHTMLDocument::ExecCommand(const nsAString& commandID,
|
nsHTMLDocument::ExecCommand(const nsAString& commandID,
|
||||||
bool doShowUI,
|
bool doShowUI,
|
||||||
|
|
|
@ -129,7 +129,7 @@ function sendKeyAndAssertResult(testdata) {
|
||||||
charCode: 0,
|
charCode: 0,
|
||||||
code: expectedValues.code || '',
|
code: expectedValues.code || '',
|
||||||
keyCode: expectedValues.keyCode || 0,
|
keyCode: expectedValues.keyCode || 0,
|
||||||
location: 0,
|
location: expectedValues.location ? expectedValues.location : 0,
|
||||||
repeat: expectedValues.repeat || false,
|
repeat: expectedValues.repeat || false,
|
||||||
value: gCurrentValue,
|
value: gCurrentValue,
|
||||||
shift: false,
|
shift: false,
|
||||||
|
@ -145,7 +145,7 @@ function sendKeyAndAssertResult(testdata) {
|
||||||
charCode: expectedValues.charCode,
|
charCode: expectedValues.charCode,
|
||||||
code: expectedValues.code || '',
|
code: expectedValues.code || '',
|
||||||
keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
|
keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
|
||||||
location: 0,
|
location: expectedValues.location ? expectedValues.location : 0,
|
||||||
repeat: expectedValues.repeat || false,
|
repeat: expectedValues.repeat || false,
|
||||||
value: gCurrentValue,
|
value: gCurrentValue,
|
||||||
shift: false,
|
shift: false,
|
||||||
|
@ -156,9 +156,22 @@ function sendKeyAndAssertResult(testdata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testdata.expectedInput) {
|
if (testdata.expectedInput) {
|
||||||
|
switch (testdata.expectedInput) {
|
||||||
|
case 'Enter':
|
||||||
|
gCurrentValue += '\n';
|
||||||
|
break;
|
||||||
|
case 'Backspace':
|
||||||
|
gCurrentValue =
|
||||||
|
gCurrentValue.substr(0, gCurrentValue.length - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gCurrentValue += testdata.expectedInput;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
expectedEventDetail.push({
|
expectedEventDetail.push({
|
||||||
type: 'input',
|
type: 'input',
|
||||||
value: gCurrentValue += testdata.expectedInput
|
value: gCurrentValue
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +182,7 @@ function sendKeyAndAssertResult(testdata) {
|
||||||
charCode: 0,
|
charCode: 0,
|
||||||
code: expectedValues.code || '',
|
code: expectedValues.code || '',
|
||||||
keyCode: expectedValues.keyCode || 0,
|
keyCode: expectedValues.keyCode || 0,
|
||||||
location: 0,
|
location: expectedValues.location ? expectedValues.location : 0,
|
||||||
repeat: expectedValues.repeat || false,
|
repeat: expectedValues.repeat || false,
|
||||||
value: gCurrentValue,
|
value: gCurrentValue,
|
||||||
shift: false,
|
shift: false,
|
||||||
|
@ -1052,6 +1065,117 @@ function runSendKeyEnterTests() {
|
||||||
return promiseQueue;
|
return promiseQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runSendKeyNumpadTests() {
|
||||||
|
gTestDescription = 'runSendKeyNumpadTests(): ';
|
||||||
|
var promiseQueue = Promise.resolve();
|
||||||
|
|
||||||
|
var tests = [];
|
||||||
|
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||||||
|
.forEach(function(key) {
|
||||||
|
let charCode = key.charCodeAt(0);
|
||||||
|
|
||||||
|
tests.push({
|
||||||
|
dict: {
|
||||||
|
key: key,
|
||||||
|
code: 'Numpad' + key
|
||||||
|
},
|
||||||
|
expectedKeypress: true,
|
||||||
|
expectedInput: key,
|
||||||
|
expectedValues: {
|
||||||
|
key: key, code: 'Numpad' + key,
|
||||||
|
keyCode: charCode, charCode: charCode,
|
||||||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[['+', 'NumpadAdd'],
|
||||||
|
[',', 'NumpadComma'],
|
||||||
|
['.', 'NumpadDecimal'],
|
||||||
|
['.', 'NumpadComma'], // Locale-specific NumpadComma
|
||||||
|
[',', 'NumpadDecimal'], // Locale-specific NumpadDecimal
|
||||||
|
['/', 'NumpadDivide'],
|
||||||
|
['=', 'NumpadEqual'],
|
||||||
|
// ['#', 'NumpadHash'], // Not supported yet.
|
||||||
|
['*', 'NumpadMultiply'],
|
||||||
|
['(', 'NumpadParenLeft'],
|
||||||
|
[')', 'NumpadParenRight'],
|
||||||
|
// ['*', 'NumpadStar'], // Not supported yet.
|
||||||
|
['-', 'NumpadSubtract']].forEach(function([key, code]) {
|
||||||
|
tests.push({
|
||||||
|
dict: {
|
||||||
|
key: key,
|
||||||
|
code: code
|
||||||
|
},
|
||||||
|
expectedKeypress: true,
|
||||||
|
expectedInput: key,
|
||||||
|
expectedValues: {
|
||||||
|
key: key, code: code, keyCode: 0, charCode: key.charCodeAt(0),
|
||||||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
'NumpadComma', // Locale-specific NumpadComma -- outputs nothing
|
||||||
|
'NumpadClear',
|
||||||
|
'NumpadClearEntry',
|
||||||
|
'NumpadMemoryAdd',
|
||||||
|
'NumpadMemoryClear',
|
||||||
|
'NumpadMemoryRecall',
|
||||||
|
'NumpadMemoryStore',
|
||||||
|
'NumpadMemorySubtract'
|
||||||
|
].forEach(function(code) {
|
||||||
|
tests.push({
|
||||||
|
dict: {
|
||||||
|
key: 'Unidentified',
|
||||||
|
code: code
|
||||||
|
},
|
||||||
|
expectedKeypress: true,
|
||||||
|
expectedValues: {
|
||||||
|
key: 'Unidentified', code: code, keyCode: 0, charCode: 0,
|
||||||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tests.push({
|
||||||
|
dict: {
|
||||||
|
key: 'Enter',
|
||||||
|
code: 'NumpadEnter'
|
||||||
|
},
|
||||||
|
expectedKeypress: true,
|
||||||
|
expectedInput: '\n',
|
||||||
|
expectedValues: {
|
||||||
|
key: 'Enter', code: 'NumpadEnter',
|
||||||
|
keyCode: KeyboardEvent.DOM_VK_RETURN, charCode: 0,
|
||||||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tests.push({
|
||||||
|
dict: {
|
||||||
|
key: 'Backspace',
|
||||||
|
code: 'NumpadBackspace'
|
||||||
|
},
|
||||||
|
expectedKeypress: true,
|
||||||
|
expectedInput: 'Backspace', // Special value
|
||||||
|
expectedValues: {
|
||||||
|
key: 'Backspace', code: 'NumpadBackspace',
|
||||||
|
keyCode: KeyboardEvent.DOM_VK_BACK_SPACE, charCode: 0,
|
||||||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tests.forEach((test) => {
|
||||||
|
promiseQueue = promiseQueue.then(() => {
|
||||||
|
return sendKeyAndAssertResult(test);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return promiseQueue;
|
||||||
|
}
|
||||||
|
|
||||||
function runSendKeyRejectionTests() {
|
function runSendKeyRejectionTests() {
|
||||||
gTestDescription = 'runSendKeyRejectionTests(): ';
|
gTestDescription = 'runSendKeyRejectionTests(): ';
|
||||||
var promiseQueue = Promise.resolve();
|
var promiseQueue = Promise.resolve();
|
||||||
|
@ -1636,6 +1760,7 @@ function runTest() {
|
||||||
.then(() => runSendKeyUSKeyboardSymbolsTests())
|
.then(() => runSendKeyUSKeyboardSymbolsTests())
|
||||||
.then(() => runSendKeyGreekLettersTests())
|
.then(() => runSendKeyGreekLettersTests())
|
||||||
.then(() => runSendKeyEnterTests())
|
.then(() => runSendKeyEnterTests())
|
||||||
|
.then(() => runSendKeyNumpadTests())
|
||||||
.then(() => runSendKeyRejectionTests())
|
.then(() => runSendKeyRejectionTests())
|
||||||
.then(() => runCompositionWithKeyEventTests())
|
.then(() => runCompositionWithKeyEventTests())
|
||||||
.then(() => runCompositionWithoutKeyEventTests())
|
.then(() => runCompositionWithoutKeyEventTests())
|
||||||
|
|
|
@ -184,7 +184,7 @@ static char const *const gWebMCodecs[7] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DecoderTraits::IsWebMType(const nsACString& aType)
|
DecoderTraits::IsWebMTypeAndEnabled(const nsACString& aType)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_WEBM
|
#ifdef MOZ_WEBM
|
||||||
if (!MediaDecoder::IsWebMEnabled()) {
|
if (!MediaDecoder::IsWebMEnabled()) {
|
||||||
|
@ -200,7 +200,7 @@ DecoderTraits::IsWebMType(const nsACString& aType)
|
||||||
static bool
|
static bool
|
||||||
IsGStreamerSupportedType(const nsACString& aMimeType)
|
IsGStreamerSupportedType(const nsACString& aMimeType)
|
||||||
{
|
{
|
||||||
if (DecoderTraits::IsWebMType(aMimeType))
|
if (DecoderTraits::IsWebMTypeAndEnabled(aMimeType))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!MediaDecoder::IsGStreamerEnabled())
|
if (!MediaDecoder::IsGStreamerEnabled())
|
||||||
|
@ -352,7 +352,7 @@ IsMP4SupportedType(const nsACString& aType,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DecoderTraits::IsMP4Type(const nsACString& aType)
|
DecoderTraits::IsMP4TypeAndEnabled(const nsACString& aType)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_FMP4
|
#ifdef MOZ_FMP4
|
||||||
return IsMP4SupportedType(aType);
|
return IsMP4SupportedType(aType);
|
||||||
|
@ -364,6 +364,9 @@ static bool
|
||||||
IsMP3SupportedType(const nsACString& aType,
|
IsMP3SupportedType(const nsACString& aType,
|
||||||
const nsAString& aCodecs = EmptyString())
|
const nsAString& aCodecs = EmptyString())
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_OMX_DECODER
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
return MP3Decoder::CanHandleMediaType(aType, aCodecs);
|
return MP3Decoder::CanHandleMediaType(aType, aCodecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,12 +438,12 @@ DecoderTraits::CanHandleCodecsType(const char* aMIMEType,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if !defined(MOZ_OMX_WEBM_DECODER)
|
#if !defined(MOZ_OMX_WEBM_DECODER)
|
||||||
if (IsWebMType(nsDependentCString(aMIMEType))) {
|
if (IsWebMTypeAndEnabled(nsDependentCString(aMIMEType))) {
|
||||||
codecList = gWebMCodecs;
|
codecList = gWebMCodecs;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_FMP4
|
#ifdef MOZ_FMP4
|
||||||
if (IsMP4Type(nsDependentCString(aMIMEType))) {
|
if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) {
|
||||||
if (IsMP4SupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
|
if (IsMP4SupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
|
||||||
return CANPLAY_YES;
|
return CANPLAY_YES;
|
||||||
} else {
|
} else {
|
||||||
|
@ -530,11 +533,11 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
|
||||||
return CANPLAY_MAYBE;
|
return CANPLAY_MAYBE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (IsMP4Type(nsDependentCString(aMIMEType))) {
|
if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) {
|
||||||
return CANPLAY_MAYBE;
|
return CANPLAY_MAYBE;
|
||||||
}
|
}
|
||||||
#if !defined(MOZ_OMX_WEBM_DECODER)
|
#if !defined(MOZ_OMX_WEBM_DECODER)
|
||||||
if (IsWebMType(nsDependentCString(aMIMEType))) {
|
if (IsWebMTypeAndEnabled(nsDependentCString(aMIMEType))) {
|
||||||
return CANPLAY_MAYBE;
|
return CANPLAY_MAYBE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -662,7 +665,7 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
|
||||||
return decoder.forget();
|
return decoder.forget();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (DecoderTraits::IsWebMType(aType)) {
|
if (DecoderTraits::IsWebMTypeAndEnabled(aType)) {
|
||||||
decoder = new WebMDecoder(aOwner);
|
decoder = new WebMDecoder(aOwner);
|
||||||
return decoder.forget();
|
return decoder.forget();
|
||||||
}
|
}
|
||||||
|
@ -744,7 +747,7 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
|
||||||
decoderReader = new AndroidMediaReader(aDecoder, aType);
|
decoderReader = new AndroidMediaReader(aDecoder, aType);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (IsWebMType(aType)) {
|
if (IsWebMTypeAndEnabled(aType)) {
|
||||||
decoderReader = Preferences::GetBool("media.format-reader.webm", true) ?
|
decoderReader = Preferences::GetBool("media.format-reader.webm", true) ?
|
||||||
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource()))) :
|
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource()))) :
|
||||||
new WebMReader(aDecoder);
|
new WebMReader(aDecoder);
|
||||||
|
@ -784,7 +787,7 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
|
||||||
(IsOmxSupportedType(aType) &&
|
(IsOmxSupportedType(aType) &&
|
||||||
!IsB2GSupportOnlyType(aType)) ||
|
!IsB2GSupportOnlyType(aType)) ||
|
||||||
#endif
|
#endif
|
||||||
IsWebMType(aType) ||
|
IsWebMTypeAndEnabled(aType) ||
|
||||||
#ifdef MOZ_GSTREAMER
|
#ifdef MOZ_GSTREAMER
|
||||||
IsGStreamerSupportedType(aType) ||
|
IsGStreamerSupportedType(aType) ||
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,8 +70,8 @@ public:
|
||||||
// OnConnected signal. (currently RTSP only)
|
// OnConnected signal. (currently RTSP only)
|
||||||
static bool DecoderWaitsForOnConnected(const nsACString& aType);
|
static bool DecoderWaitsForOnConnected(const nsACString& aType);
|
||||||
|
|
||||||
static bool IsWebMType(const nsACString& aType);
|
static bool IsWebMTypeAndEnabled(const nsACString& aType);
|
||||||
static bool IsMP4Type(const nsACString& aType);
|
static bool IsMP4TypeAndEnabled(const nsACString& aType);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -69,6 +69,21 @@ static const char* const gMediaSourceTypes[6] = {
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns true if we should enable MSE webm regardless of preferences.
|
||||||
|
// 1. If MP4/H264 isn't supported:
|
||||||
|
// * Windows XP
|
||||||
|
// * Windows Vista and Server 2008 without the optional "Platform Update Supplement"
|
||||||
|
// * N/KN editions (Europe and Korea) of Windows 7/8/8.1/10 without the
|
||||||
|
// optional "Windows Media Feature Pack"
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsWebMForced()
|
||||||
|
{
|
||||||
|
bool mp4supported =
|
||||||
|
DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"));
|
||||||
|
return !mp4supported;
|
||||||
|
}
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
IsTypeSupported(const nsAString& aType)
|
IsTypeSupported(const nsAString& aType)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +103,7 @@ IsTypeSupported(const nsAString& aType)
|
||||||
|
|
||||||
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
|
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
|
||||||
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
|
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
|
||||||
if (DecoderTraits::IsMP4Type(mimeTypeUTF8)) {
|
if (DecoderTraits::IsMP4TypeAndEnabled(mimeTypeUTF8)) {
|
||||||
if (!Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
|
if (!Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
}
|
}
|
||||||
|
@ -98,8 +113,9 @@ IsTypeSupported(const nsAString& aType)
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
} else if (DecoderTraits::IsWebMType(mimeTypeUTF8)) {
|
} else if (DecoderTraits::IsWebMTypeAndEnabled(mimeTypeUTF8)) {
|
||||||
if (!Preferences::GetBool("media.mediasource.webm.enabled", false)) {
|
if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
|
||||||
|
IsWebMForced())) {
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
}
|
}
|
||||||
if (hasCodecs &&
|
if (hasCodecs &&
|
||||||
|
|
|
@ -376,7 +376,13 @@ TrackBuffersManager::CompleteResetParserState()
|
||||||
// to discard now.
|
// to discard now.
|
||||||
track->mQueuedSamples.Clear();
|
track->mQueuedSamples.Clear();
|
||||||
}
|
}
|
||||||
// 6. Remove all bytes from the input buffer.
|
|
||||||
|
// 6. If the mode attribute equals "sequence", then set the group start timestamp to the group end timestamp
|
||||||
|
if (mSourceBufferAttributes->GetAppendMode() == SourceBufferAppendMode::Sequence) {
|
||||||
|
mGroupStartTimestamp = Some(mGroupEndTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Remove all bytes from the input buffer.
|
||||||
mIncomingBuffers.Clear();
|
mIncomingBuffers.Clear();
|
||||||
mInputBuffer = nullptr;
|
mInputBuffer = nullptr;
|
||||||
if (mCurrentInputBuffer) {
|
if (mCurrentInputBuffer) {
|
||||||
|
@ -401,7 +407,7 @@ TrackBuffersManager::CompleteResetParserState()
|
||||||
}
|
}
|
||||||
RecreateParser(true);
|
RecreateParser(true);
|
||||||
|
|
||||||
// 7. Set append state to WAITING_FOR_SEGMENT.
|
// 8. Set append state to WAITING_FOR_SEGMENT.
|
||||||
SetAppendState(AppendState::WAITING_FOR_SEGMENT);
|
SetAppendState(AppendState::WAITING_FOR_SEGMENT);
|
||||||
|
|
||||||
// Reject our promise immediately.
|
// Reject our promise immediately.
|
||||||
|
|
|
@ -100,7 +100,7 @@ nsresult
|
||||||
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
|
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
|
||||||
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
|
MOZ_RELEASE_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
|
||||||
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
||||||
RefPtr<nsCORSListenerProxy> corsListener =
|
RefPtr<nsCORSListenerProxy> corsListener =
|
||||||
new nsCORSListenerProxy(aInAndOutListener,
|
new nsCORSListenerProxy(aInAndOutListener,
|
||||||
|
|
|
@ -156,7 +156,6 @@ DOMSVGPathSeg::IndexIsValid()
|
||||||
// Implementation of DOMSVGPathSeg sub-classes below this point
|
// Implementation of DOMSVGPathSeg sub-classes below this point
|
||||||
|
|
||||||
#define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \
|
#define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \
|
||||||
/* attribute type propName; */ \
|
|
||||||
type \
|
type \
|
||||||
DOMSVGPathSeg##segName::propName() \
|
DOMSVGPathSeg##segName::propName() \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -338,7 +338,6 @@ StumblerInfo::DumpStumblerInfo()
|
||||||
target->Dispatch(event, NS_DISPATCH_NORMAL);
|
target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void notifyGetCellInfoList (in uint32_t count, [array, size_is (count)] in nsICellInfo result); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos)
|
StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos)
|
||||||
{
|
{
|
||||||
|
@ -353,7 +352,6 @@ StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void notifyGetCellInfoListFailed (in DOMString error); */
|
|
||||||
NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoListFailed(const nsAString& error)
|
NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoListFailed(const nsAString& error)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
|
@ -102,7 +102,9 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocument> xslDocument;
|
nsCOMPtr<nsIDOMDocument> xslDocument;
|
||||||
rv = nsSyncLoadService::LoadDocument(xslUri, nsContentUtils::GetSystemPrincipal(),
|
rv = nsSyncLoadService::LoadDocument(xslUri, nsIContentPolicy::TYPE_XSLT,
|
||||||
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||||
nullptr, true, mozilla::net::RP_Default,
|
nullptr, true, mozilla::net::RP_Default,
|
||||||
getter_AddRefs(xslDocument));
|
getter_AddRefs(xslDocument));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
txParseDocumentFromURI(const nsAString& aHref,
|
||||||
nsAString& aErrMsg, txXPathNode** aResult)
|
const txXPathNode& aLoader,
|
||||||
|
nsAString& aErrMsg,
|
||||||
|
txXPathNode** aResult)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aResult);
|
NS_ENSURE_ARG_POINTER(aResult);
|
||||||
*aResult = nullptr;
|
*aResult = nullptr;
|
||||||
|
@ -36,7 +38,9 @@ txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
||||||
nsIDOMDocument* theDocument = nullptr;
|
nsIDOMDocument* theDocument = nullptr;
|
||||||
nsAutoSyncOperation sync(loaderDocument);
|
nsAutoSyncOperation sync(loaderDocument);
|
||||||
rv = nsSyncLoadService::LoadDocument(documentURI,
|
rv = nsSyncLoadService::LoadDocument(documentURI,
|
||||||
|
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
|
||||||
loaderDocument->NodePrincipal(),
|
loaderDocument->NodePrincipal(),
|
||||||
|
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
|
||||||
loadGroup, true,
|
loadGroup, true,
|
||||||
loaderDocument->GetReferrerPolicy(),
|
loaderDocument->GetReferrerPolicy(),
|
||||||
&theDocument);
|
&theDocument);
|
||||||
|
|
|
@ -629,20 +629,6 @@ txSyncCompileObserver::loadURI(const nsAString& aUri,
|
||||||
getter_AddRefs(referrerPrincipal));
|
getter_AddRefs(referrerPrincipal));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Content Policy
|
|
||||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
|
||||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET,
|
|
||||||
uri,
|
|
||||||
referrerPrincipal,
|
|
||||||
nullptr,
|
|
||||||
NS_LITERAL_CSTRING("application/xml"),
|
|
||||||
nullptr,
|
|
||||||
&shouldLoad);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (NS_CP_REJECTED(shouldLoad)) {
|
|
||||||
return NS_ERROR_DOM_BAD_URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is probably called by js, a loadGroup for the channel doesn't
|
// This is probably called by js, a loadGroup for the channel doesn't
|
||||||
// make sense.
|
// make sense.
|
||||||
nsCOMPtr<nsINode> source;
|
nsCOMPtr<nsINode> source;
|
||||||
|
@ -652,8 +638,12 @@ txSyncCompileObserver::loadURI(const nsAString& aUri,
|
||||||
}
|
}
|
||||||
nsAutoSyncOperation sync(source ? source->OwnerDoc() : nullptr);
|
nsAutoSyncOperation sync(source ? source->OwnerDoc() : nullptr);
|
||||||
nsCOMPtr<nsIDOMDocument> document;
|
nsCOMPtr<nsIDOMDocument> document;
|
||||||
rv = nsSyncLoadService::LoadDocument(uri, referrerPrincipal, nullptr,
|
|
||||||
false, aReferrerPolicy,
|
rv = nsSyncLoadService::LoadDocument(uri, nsIContentPolicy::TYPE_XSLT,
|
||||||
|
referrerPrincipal,
|
||||||
|
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
|
||||||
|
nullptr, false,
|
||||||
|
aReferrerPolicy,
|
||||||
getter_AddRefs(document));
|
getter_AddRefs(document));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,6 @@ NS_IMETHODIMP nsTransactionList::ItemIsBatch(int32_t aIndex, bool *aIsBatch)
|
||||||
return item->GetIsBatch(aIsBatch);
|
return item->GetIsBatch(aIsBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void getData (in long aIndex,
|
|
||||||
[optional] out unsigned long aLength,
|
|
||||||
[array, size_is (aLength), retval]
|
|
||||||
out nsISupports aData); */
|
|
||||||
NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex,
|
NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex,
|
||||||
uint32_t *aLength,
|
uint32_t *aLength,
|
||||||
nsISupports ***aData)
|
nsISupports ***aData)
|
||||||
|
|
|
@ -415,9 +415,6 @@ NS_IMETHODIMP nsWebBrowserPersist::SetProgressListener(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void saveURI (in nsIURI aURI, in nsISupports aCacheKey, in nsIURI aReferrer,
|
|
||||||
in nsIInputStream aPostData, in wstring aExtraHeaders,
|
|
||||||
in nsISupports aFile, in nsILoadContext aPrivayContext); */
|
|
||||||
NS_IMETHODIMP nsWebBrowserPersist::SaveURI(
|
NS_IMETHODIMP nsWebBrowserPersist::SaveURI(
|
||||||
nsIURI *aURI, nsISupports *aCacheKey,
|
nsIURI *aURI, nsISupports *aCacheKey,
|
||||||
nsIURI *aReferrer, uint32_t aReferrerPolicy,
|
nsIURI *aReferrer, uint32_t aReferrerPolicy,
|
||||||
|
@ -533,7 +530,6 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveDocument(
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void cancel(nsresult aReason); */
|
|
||||||
NS_IMETHODIMP nsWebBrowserPersist::Cancel(nsresult aReason)
|
NS_IMETHODIMP nsWebBrowserPersist::Cancel(nsresult aReason)
|
||||||
{
|
{
|
||||||
mCancel = true;
|
mCancel = true;
|
||||||
|
@ -1002,8 +998,6 @@ nsWebBrowserPersist::OnDataAvailable(
|
||||||
// nsWebBrowserPersist::nsIProgressEventSink
|
// nsWebBrowserPersist::nsIProgressEventSink
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|
||||||
/* void onProgress (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in long long aProgress, in long long aProgressMax); */
|
|
||||||
NS_IMETHODIMP nsWebBrowserPersist::OnProgress(
|
NS_IMETHODIMP nsWebBrowserPersist::OnProgress(
|
||||||
nsIRequest *request, nsISupports *ctxt, int64_t aProgress,
|
nsIRequest *request, nsISupports *ctxt, int64_t aProgress,
|
||||||
int64_t aProgressMax)
|
int64_t aProgressMax)
|
||||||
|
@ -1055,8 +1049,6 @@ NS_IMETHODIMP nsWebBrowserPersist::OnProgress(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStatus (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsresult status, in wstring statusArg); */
|
|
||||||
NS_IMETHODIMP nsWebBrowserPersist::OnStatus(
|
NS_IMETHODIMP nsWebBrowserPersist::OnStatus(
|
||||||
nsIRequest *request, nsISupports *ctxt, nsresult status,
|
nsIRequest *request, nsISupports *ctxt, nsresult status,
|
||||||
const char16_t *statusArg)
|
const char16_t *statusArg)
|
||||||
|
|
|
@ -546,20 +546,17 @@ typedef Log<LOG_CRITICAL, CriticalLogger> CriticalLog;
|
||||||
// firstTime = false;
|
// firstTime = false;
|
||||||
// gfxCriticalError() << "This message only shows up once;
|
// gfxCriticalError() << "This message only shows up once;
|
||||||
// }
|
// }
|
||||||
#ifdef GFX_LOG_DEBUG
|
#if defined(DEBUG)
|
||||||
#define gfxDebug mozilla::gfx::DebugLog
|
#define gfxDebug mozilla::gfx::DebugLog
|
||||||
#define gfxDebugOnce static gfxDebug GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxDebug
|
#define gfxDebugOnce static gfxDebug GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxDebug
|
||||||
#else
|
#else
|
||||||
#define gfxDebug if (1) ; else mozilla::gfx::NoLog
|
#define gfxDebug if (1) ; else mozilla::gfx::NoLog
|
||||||
#define gfxDebugOnce if (1) ; else mozilla::gfx::NoLog
|
#define gfxDebugOnce if (1) ; else mozilla::gfx::NoLog
|
||||||
#endif
|
#endif
|
||||||
#ifdef GFX_LOG_WARNING
|
|
||||||
|
// Have gfxWarning available (behind a runtime preference)
|
||||||
#define gfxWarning mozilla::gfx::WarningLog
|
#define gfxWarning mozilla::gfx::WarningLog
|
||||||
#define gfxWarningOnce static gfxWarning GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxWarning
|
#define gfxWarningOnce static gfxWarning GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxWarning
|
||||||
#else
|
|
||||||
#define gfxWarning if (1) ; else mozilla::gfx::NoLog
|
|
||||||
#define gfxWarningOnce if (1) ; else mozilla::gfx::NoLog
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// In the debug build, this is equivalent to the default gfxCriticalError.
|
// In the debug build, this is equivalent to the default gfxCriticalError.
|
||||||
// In the non-debug build, on nightly and dev edition, it will MOZ_CRASH.
|
// In the non-debug build, on nightly and dev edition, it will MOZ_CRASH.
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
|
<PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_WARNING</PreprocessorDefinitions>
|
<PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
|
|
@ -179,17 +179,6 @@ for var in ('USE_CAIRO', 'MOZ2D_HAS_MOZ_CAIRO'):
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
||||||
DEFINES['MOZ_ENABLE_FREETYPE'] = True
|
DEFINES['MOZ_ENABLE_FREETYPE'] = True
|
||||||
|
|
||||||
if CONFIG['MOZ_DEBUG']:
|
|
||||||
DEFINES['GFX_LOG_DEBUG'] = True
|
|
||||||
DEFINES['GFX_LOG_WARNING'] = True
|
|
||||||
|
|
||||||
# Define the GFX_LOG_WARNING in release builds (available, but controlled by a
|
|
||||||
# preference), though we may want to consider only doing it in the nightly
|
|
||||||
# build, if the size of gfxWarning() code ends up making a difference.
|
|
||||||
# See bug 1074952.
|
|
||||||
# if CONFIG['NIGHTLY_BUILD']:
|
|
||||||
DEFINES['GFX_LOG_WARNING'] = True
|
|
||||||
|
|
||||||
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||||
|
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
||||||
|
|
|
@ -11,6 +11,13 @@
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "nsAppRunner.h"
|
#include "nsAppRunner.h"
|
||||||
|
|
||||||
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
|
#include "libdisplay/GonkDisplay.h" // for GonkDisplay
|
||||||
|
#include <ui/Fence.h>
|
||||||
|
#include "nsWindow.h"
|
||||||
|
#include "nsScreenManagerGonk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
class Matrix4x4;
|
class Matrix4x4;
|
||||||
|
@ -353,5 +360,49 @@ DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
|
void
|
||||||
|
Compositor::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
// OpenGL does not provide ReleaseFence for rendering.
|
||||||
|
// Instead use DispAcquireFence as layer buffer's ReleaseFence
|
||||||
|
// to prevent flickering and tearing.
|
||||||
|
// DispAcquireFence is DisplaySurface's AcquireFence.
|
||||||
|
// AcquireFence will be signaled when a buffer's content is available.
|
||||||
|
// See Bug 974152.
|
||||||
|
|
||||||
|
if (!aLayer || !aWidget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsWindow* window = static_cast<nsWindow*>(aWidget);
|
||||||
|
RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
|
||||||
|
window->GetScreen()->GetPrevDispAcquireFd());
|
||||||
|
mReleaseFenceHandle.Merge(FenceHandle(fence));
|
||||||
|
}
|
||||||
|
|
||||||
|
FenceHandle
|
||||||
|
Compositor::GetReleaseFence()
|
||||||
|
{
|
||||||
|
if (!mReleaseFenceHandle.IsValid()) {
|
||||||
|
return FenceHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetDupFdObj();
|
||||||
|
return FenceHandle(fdObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
Compositor::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FenceHandle
|
||||||
|
Compositor::GetReleaseFence()
|
||||||
|
{
|
||||||
|
return FenceHandle();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -370,12 +370,9 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void EndFrame() = 0;
|
virtual void EndFrame() = 0;
|
||||||
|
|
||||||
virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget) {}
|
virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget);
|
||||||
|
|
||||||
virtual FenceHandle GetReleaseFence()
|
virtual FenceHandle GetReleaseFence();
|
||||||
{
|
|
||||||
return FenceHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post-rendering stuff if the rendering is done outside of this Compositor
|
* Post-rendering stuff if the rendering is done outside of this Compositor
|
||||||
|
@ -541,6 +538,10 @@ protected:
|
||||||
RefPtr<gfx::DrawTarget> mTarget;
|
RefPtr<gfx::DrawTarget> mTarget;
|
||||||
gfx::IntRect mTargetBounds;
|
gfx::IntRect mTargetBounds;
|
||||||
|
|
||||||
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
|
FenceHandle mReleaseFenceHandle;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LayersBackend sBackend;
|
static LayersBackend sBackend;
|
||||||
|
|
||||||
|
|
|
@ -397,18 +397,15 @@ ConvertOmxYUVFormatToRGB565(android::sp<GraphicBuffer>& aBuffer,
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfx::SourceSurface>
|
already_AddRefed<gfx::DataSourceSurface>
|
||||||
GrallocImage::GetAsSourceSurface()
|
GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
|
||||||
|
gfx::IntSize aSize,
|
||||||
|
const layers::PlanarYCbCrData& aYcbcrData)
|
||||||
{
|
{
|
||||||
if (!mTextureClient) {
|
MOZ_ASSERT(aGraphicBuffer.get());
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
android::sp<GraphicBuffer> graphicBuffer =
|
|
||||||
mTextureClient->GetGraphicBuffer();
|
|
||||||
|
|
||||||
RefPtr<gfx::DataSourceSurface> surface =
|
RefPtr<gfx::DataSourceSurface> surface =
|
||||||
gfx::Factory::CreateDataSourceSurface(GetSize(), gfx::SurfaceFormat::R5G6B5);
|
gfx::Factory::CreateDataSourceSurface(aSize, gfx::SurfaceFormat::R5G6B5);
|
||||||
if (NS_WARN_IF(!surface)) {
|
if (NS_WARN_IF(!surface)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -420,13 +417,13 @@ GrallocImage::GetAsSourceSurface()
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t rv;
|
int32_t rv;
|
||||||
rv = ConvertOmxYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface, mData);
|
rv = ConvertOmxYUVFormatToRGB565(aGraphicBuffer, surface, &mappedSurface, aYcbcrData);
|
||||||
if (rv == OK) {
|
if (rv == OK) {
|
||||||
surface->Unmap();
|
surface->Unmap();
|
||||||
return surface.forget();
|
return surface.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ConvertVendorYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface);
|
rv = ConvertVendorYUVFormatToRGB565(aGraphicBuffer, surface, &mappedSurface);
|
||||||
surface->Unmap();
|
surface->Unmap();
|
||||||
if (rv != OK) {
|
if (rv != OK) {
|
||||||
NS_WARNING("Unknown color format");
|
NS_WARNING("Unknown color format");
|
||||||
|
@ -436,6 +433,22 @@ GrallocImage::GetAsSourceSurface()
|
||||||
return surface.forget();
|
return surface.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::SourceSurface>
|
||||||
|
GrallocImage::GetAsSourceSurface()
|
||||||
|
{
|
||||||
|
if (!mTextureClient) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
android::sp<GraphicBuffer> graphicBuffer =
|
||||||
|
mTextureClient->GetGraphicBuffer();
|
||||||
|
|
||||||
|
RefPtr<gfx::DataSourceSurface> surface =
|
||||||
|
GetDataSourceSurfaceFrom(graphicBuffer, mSize, mData);
|
||||||
|
|
||||||
|
return surface.forget();
|
||||||
|
}
|
||||||
|
|
||||||
android::sp<android::GraphicBuffer>
|
android::sp<android::GraphicBuffer>
|
||||||
GrallocImage::GetGraphicBuffer() const
|
GrallocImage::GetGraphicBuffer() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,11 @@ namespace layers {
|
||||||
|
|
||||||
class GrallocTextureClientOGL;
|
class GrallocTextureClientOGL;
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DataSourceSurface>
|
||||||
|
GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
|
||||||
|
gfx::IntSize aSize,
|
||||||
|
const layers::PlanarYCbCrData& aYcbcrData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The YUV format supported by Android HAL
|
* The YUV format supported by Android HAL
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "GrallocTextureHostBasic.h"
|
||||||
|
#include "GrallocImages.h" // for GetDataSourceSurfaceFrom()
|
||||||
|
#include "mozilla/layers/SharedBufferManagerParent.h"
|
||||||
|
|
||||||
|
#if ANDROID_VERSION >= 17
|
||||||
|
#include <ui/Fence.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
static SurfaceFormat
|
||||||
|
HalFormatToSurfaceFormat(int aHalFormat, TextureFlags aFlags)
|
||||||
|
{
|
||||||
|
bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED);
|
||||||
|
switch (aHalFormat) {
|
||||||
|
case android::PIXEL_FORMAT_BGRA_8888:
|
||||||
|
return swapRB ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8A8;
|
||||||
|
case android::PIXEL_FORMAT_RGBA_8888:
|
||||||
|
return swapRB ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::R8G8B8A8;
|
||||||
|
case android::PIXEL_FORMAT_RGBX_8888:
|
||||||
|
return swapRB ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::R8G8B8X8;
|
||||||
|
case android::PIXEL_FORMAT_RGB_565:
|
||||||
|
return gfx::SurfaceFormat::R5G6B5;
|
||||||
|
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||||
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||||
|
case HAL_PIXEL_FORMAT_YCbCr_422_I:
|
||||||
|
case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
|
||||||
|
case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
|
||||||
|
case HAL_PIXEL_FORMAT_YV12:
|
||||||
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
|
||||||
|
#endif
|
||||||
|
// Needs convert to RGB565
|
||||||
|
return gfx::SurfaceFormat::R5G6B5;
|
||||||
|
default:
|
||||||
|
if (aHalFormat >= 0x100 && aHalFormat <= 0x1FF) {
|
||||||
|
// Reserved range for HAL specific formats.
|
||||||
|
// Needs convert to RGB565
|
||||||
|
return gfx::SurfaceFormat::R5G6B5;
|
||||||
|
} else {
|
||||||
|
MOZ_CRASH("Unhandled HAL pixel format");
|
||||||
|
return SurfaceFormat::UNKNOWN; // not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
NeedsConvertFromYUVtoRGB565(int aHalFormat)
|
||||||
|
{
|
||||||
|
switch (aHalFormat) {
|
||||||
|
case android::PIXEL_FORMAT_BGRA_8888:
|
||||||
|
case android::PIXEL_FORMAT_RGBA_8888:
|
||||||
|
case android::PIXEL_FORMAT_RGBX_8888:
|
||||||
|
case android::PIXEL_FORMAT_RGB_565:
|
||||||
|
return false;
|
||||||
|
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||||
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||||
|
case HAL_PIXEL_FORMAT_YCbCr_422_I:
|
||||||
|
case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
|
||||||
|
case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
|
||||||
|
case HAL_PIXEL_FORMAT_YV12:
|
||||||
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
if (aHalFormat >= 0x100 && aHalFormat <= 0x1FF) {
|
||||||
|
// Reserved range for HAL specific formats.
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
MOZ_CRASH("Unhandled HAL pixel format");
|
||||||
|
return false; // not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GrallocTextureHostBasic::GrallocTextureHostBasic(
|
||||||
|
TextureFlags aFlags,
|
||||||
|
const NewSurfaceDescriptorGralloc& aDescriptor)
|
||||||
|
: TextureHost(aFlags)
|
||||||
|
, mGrallocHandle(aDescriptor)
|
||||||
|
, mSize(0, 0)
|
||||||
|
, mCropSize(0, 0)
|
||||||
|
, mFormat(gfx::SurfaceFormat::UNKNOWN)
|
||||||
|
, mIsOpaque(aDescriptor.isOpaque())
|
||||||
|
{
|
||||||
|
android::GraphicBuffer* grallocBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
|
MOZ_ASSERT(grallocBuffer);
|
||||||
|
|
||||||
|
if (grallocBuffer) {
|
||||||
|
mFormat =
|
||||||
|
HalFormatToSurfaceFormat(grallocBuffer->getPixelFormat(),
|
||||||
|
aFlags & TextureFlags::RB_SWAPPED);
|
||||||
|
mSize = gfx::IntSize(grallocBuffer->getWidth(), grallocBuffer->getHeight());
|
||||||
|
mCropSize = mSize;
|
||||||
|
} else {
|
||||||
|
printf_stderr("gralloc buffer is nullptr\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GrallocTextureHostBasic::Lock()
|
||||||
|
{
|
||||||
|
if (!mCompositor || !IsValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTextureSource) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
android::sp<android::GraphicBuffer> graphicBuffer =
|
||||||
|
GetGraphicBufferFromDesc(mGrallocHandle);
|
||||||
|
MOZ_ASSERT(graphicBuffer.get());
|
||||||
|
|
||||||
|
RefPtr<gfx::DataSourceSurface> surf;
|
||||||
|
if (NeedsConvertFromYUVtoRGB565(graphicBuffer->getPixelFormat())) {
|
||||||
|
PlanarYCbCrData ycbcrData;
|
||||||
|
surf = GetDataSourceSurfaceFrom(graphicBuffer,
|
||||||
|
mCropSize,
|
||||||
|
ycbcrData);
|
||||||
|
} else {
|
||||||
|
uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
|
||||||
|
int32_t rv = graphicBuffer->lock(usage,
|
||||||
|
reinterpret_cast<void**>(&mMappedBuffer));
|
||||||
|
if (rv) {
|
||||||
|
mMappedBuffer = nullptr;
|
||||||
|
NS_WARNING("Couldn't lock graphic buffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
surf = Factory::CreateWrappingDataSourceSurface(
|
||||||
|
mMappedBuffer,
|
||||||
|
graphicBuffer->getStride() * gfx::BytesPerPixel(mFormat),
|
||||||
|
mCropSize,
|
||||||
|
mFormat);
|
||||||
|
}
|
||||||
|
mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
|
||||||
|
mTextureSource->Update(surf, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GrallocTextureHostBasic::IsValid() const
|
||||||
|
{
|
||||||
|
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
|
return graphicBuffer != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GrallocTextureHostBasic::BindTextureSource(CompositableTextureSourceRef& aTexture)
|
||||||
|
{
|
||||||
|
aTexture = mTextureSource;
|
||||||
|
return !!aTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::UnbindTextureSource()
|
||||||
|
{
|
||||||
|
ClearTextureSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::ClearTextureSource()
|
||||||
|
{
|
||||||
|
mTextureSource = nullptr;
|
||||||
|
if (mMappedBuffer) {
|
||||||
|
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
|
MOZ_ASSERT(graphicBuffer);
|
||||||
|
mMappedBuffer = nullptr;
|
||||||
|
graphicBuffer->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::SetCompositor(Compositor* aCompositor)
|
||||||
|
{
|
||||||
|
BasicCompositor* compositor = static_cast<BasicCompositor*>(aCompositor);
|
||||||
|
mCompositor = compositor;
|
||||||
|
if (mTextureSource) {
|
||||||
|
mTextureSource->SetCompositor(compositor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::SurfaceFormat
|
||||||
|
GrallocTextureHostBasic::GetFormat() const {
|
||||||
|
return mFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::WaitAcquireFenceHandleSyncComplete()
|
||||||
|
{
|
||||||
|
if (!mAcquireFenceHandle.IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ANDROID_VERSION >= 17
|
||||||
|
RefPtr<FenceHandle::FdObj> fdObj = mAcquireFenceHandle.GetAndResetFdObj();
|
||||||
|
android::sp<android::Fence> fence(
|
||||||
|
new android::Fence(fdObj->GetAndResetFd()));
|
||||||
|
|
||||||
|
// Wait fece complete with timeout.
|
||||||
|
// If a source of the fence becomes invalid because of error,
|
||||||
|
// fene complete is not signaled. See Bug 1061435.
|
||||||
|
int rv = fence->wait(400 /*400 msec*/);
|
||||||
|
if (rv != android::OK) {
|
||||||
|
NS_ERROR("failed to wait fence complete");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::SetCropRect(nsIntRect aCropRect)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0));
|
||||||
|
MOZ_ASSERT(!aCropRect.IsEmpty());
|
||||||
|
MOZ_ASSERT(aCropRect.width <= mSize.width);
|
||||||
|
MOZ_ASSERT(aCropRect.height <= mSize.height);
|
||||||
|
|
||||||
|
gfx::IntSize cropSize(aCropRect.width, aCropRect.height);
|
||||||
|
if (mCropSize == cropSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCropSize = cropSize;
|
||||||
|
ClearTextureSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::DeallocateSharedData()
|
||||||
|
{
|
||||||
|
ClearTextureSource();
|
||||||
|
|
||||||
|
if (mGrallocHandle.buffer().type() != MaybeMagicGrallocBufferHandle::Tnull_t) {
|
||||||
|
MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer();
|
||||||
|
base::ProcessId owner;
|
||||||
|
if (handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
|
||||||
|
owner = handle.get_GrallocBufferRef().mOwner;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
owner = handle.get_MagicGrallocBufferHandle().mRef.mOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::ForgetSharedData()
|
||||||
|
{
|
||||||
|
ClearTextureSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrallocTextureHostBasic::DeallocateDeviceData()
|
||||||
|
{
|
||||||
|
ClearTextureSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerRenderState
|
||||||
|
GrallocTextureHostBasic::GetRenderState()
|
||||||
|
{
|
||||||
|
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
|
|
||||||
|
if (graphicBuffer) {
|
||||||
|
LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
|
||||||
|
if (mIsOpaque) {
|
||||||
|
flags |= LayerRenderStateFlags::OPAQUE;
|
||||||
|
}
|
||||||
|
if (mFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
|
||||||
|
flags |= LayerRenderStateFlags::ORIGIN_BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
if (mFlags & TextureFlags::RB_SWAPPED) {
|
||||||
|
flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
|
||||||
|
}
|
||||||
|
return LayerRenderState(graphicBuffer,
|
||||||
|
mCropSize,
|
||||||
|
flags,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LayerRenderState();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
|
||||||
|
#define MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
|
||||||
|
|
||||||
|
#include "mozilla/layers/BasicCompositor.h"
|
||||||
|
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
||||||
|
#include "mozilla/layers/TextureHostBasic.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class BasicCompositor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A TextureHost for shared gralloc
|
||||||
|
*
|
||||||
|
* Most of the logic actually happens in GrallocTextureSourceBasic.
|
||||||
|
*/
|
||||||
|
class GrallocTextureHostBasic : public TextureHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GrallocTextureHostBasic(TextureFlags aFlags,
|
||||||
|
const NewSurfaceDescriptorGralloc& aDescriptor);
|
||||||
|
|
||||||
|
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||||
|
|
||||||
|
virtual bool Lock() override;
|
||||||
|
|
||||||
|
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||||
|
|
||||||
|
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
|
||||||
|
|
||||||
|
virtual void UnbindTextureSource() override;
|
||||||
|
|
||||||
|
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
|
||||||
|
{
|
||||||
|
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void WaitAcquireFenceHandleSyncComplete() override;
|
||||||
|
|
||||||
|
virtual gfx::IntSize GetSize() const override { return mCropSize; }
|
||||||
|
|
||||||
|
virtual void SetCropRect(nsIntRect aCropRect) override;
|
||||||
|
|
||||||
|
virtual void DeallocateSharedData() override;
|
||||||
|
|
||||||
|
virtual void ForgetSharedData() override;
|
||||||
|
|
||||||
|
virtual void DeallocateDeviceData() override;
|
||||||
|
|
||||||
|
virtual LayerRenderState GetRenderState() override;
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
void ClearTextureSource();
|
||||||
|
|
||||||
|
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||||
|
virtual const char* Name() override { return "GrallocTextureHostBasic"; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RefPtr<BasicCompositor> mCompositor;
|
||||||
|
RefPtr<DataTextureSource> mTextureSource;
|
||||||
|
NewSurfaceDescriptorGralloc mGrallocHandle;
|
||||||
|
// gralloc buffer size.
|
||||||
|
gfx::IntSize mSize;
|
||||||
|
// Size reported by TextureClient, can be different in some cases (video?),
|
||||||
|
// used by LayerRenderState.
|
||||||
|
gfx::IntSize mCropSize;
|
||||||
|
gfx::SurfaceFormat mFormat;
|
||||||
|
bool mIsOpaque;
|
||||||
|
/**
|
||||||
|
* Points to a mapped gralloc buffer when TextureSource is valid.
|
||||||
|
*/
|
||||||
|
uint8_t* mMappedBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
|
|
@ -7,6 +7,9 @@
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
#include "MacIOSurfaceTextureHostBasic.h"
|
#include "MacIOSurfaceTextureHostBasic.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
#include "GrallocTextureHostBasic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla::gl;
|
using namespace mozilla::gl;
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
@ -25,6 +28,13 @@ CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
|
||||||
aDesc.get_SurfaceDescriptorMacIOSurface();
|
aDesc.get_SurfaceDescriptorMacIOSurface();
|
||||||
return MakeAndAddRef<MacIOSurfaceTextureHostBasic>(aFlags, desc);
|
return MakeAndAddRef<MacIOSurfaceTextureHostBasic>(aFlags, desc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
if (aDesc.type() == SurfaceDescriptor::TNewSurfaceDescriptorGralloc) {
|
||||||
|
const NewSurfaceDescriptorGralloc& desc =
|
||||||
|
aDesc.get_NewSurfaceDescriptorGralloc();
|
||||||
|
return MakeAndAddRef<GrallocTextureHostBasic>(aFlags, desc);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,12 @@
|
||||||
#include "SharedSurface.h"
|
#include "SharedSurface.h"
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
#include "mozilla/layers/GrallocTextureClient.h"
|
||||||
#include "SharedSurfaceGralloc.h"
|
#include "SharedSurfaceGralloc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace mozilla::gl;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
|
|
@ -214,10 +214,10 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
||||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||||
|
|
||||||
case SurfaceDescriptor::TEGLImageDescriptor:
|
case SurfaceDescriptor::TEGLImageDescriptor:
|
||||||
case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
|
|
||||||
case SurfaceDescriptor::TSurfaceTextureDescriptor:
|
case SurfaceDescriptor::TSurfaceTextureDescriptor:
|
||||||
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
||||||
|
|
||||||
|
case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
|
||||||
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
|
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
|
||||||
if (aBackend == LayersBackend::LAYERS_OPENGL) {
|
if (aBackend == LayersBackend::LAYERS_OPENGL) {
|
||||||
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
||||||
|
|
|
@ -670,6 +670,9 @@ SharedTextureClientD3D9::SharedTextureClientD3D9(ISurfaceAllocator* aAllocator,
|
||||||
SharedTextureClientD3D9::~SharedTextureClientD3D9()
|
SharedTextureClientD3D9::~SharedTextureClientD3D9()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(SharedTextureClientD3D9);
|
MOZ_COUNT_DTOR(SharedTextureClientD3D9);
|
||||||
|
if (mTexture) {
|
||||||
|
gfxWindowsPlatform::sD3D9SharedTextureUsed -= mDesc.Width * mDesc.Height * 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -678,9 +681,6 @@ SharedTextureClientD3D9::FinalizeOnIPDLThread()
|
||||||
if (mTexture && mActor) {
|
if (mTexture && mActor) {
|
||||||
KeepUntilFullDeallocation(MakeUnique<TKeepAlive<IDirect3DTexture9>>(mTexture));
|
KeepUntilFullDeallocation(MakeUnique<TKeepAlive<IDirect3DTexture9>>(mTexture));
|
||||||
}
|
}
|
||||||
if (mTexture) {
|
|
||||||
gfxWindowsPlatform::sD3D9SharedTextureUsed -= mDesc.Width * mDesc.Height * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -217,9 +217,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
# has full system permissions there.
|
# has full system permissions there.
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||||
EXPORTS.mozilla.layers += [
|
EXPORTS.mozilla.layers += [
|
||||||
|
'basic/GrallocTextureHostBasic.h',
|
||||||
'ipc/ShadowLayerUtilsGralloc.h',
|
'ipc/ShadowLayerUtilsGralloc.h',
|
||||||
]
|
]
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
'basic/GrallocTextureHostBasic.cpp',
|
||||||
'GrallocImages.cpp',
|
'GrallocImages.cpp',
|
||||||
'opengl/EGLImageHelpers.cpp',
|
'opengl/EGLImageHelpers.cpp',
|
||||||
'opengl/GrallocTextureClient.cpp',
|
'opengl/GrallocTextureClient.cpp',
|
||||||
|
|
|
@ -51,13 +51,6 @@
|
||||||
|
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
|
||||||
#include "libdisplay/GonkDisplay.h" // for GonkDisplay
|
|
||||||
#include <ui/Fence.h>
|
|
||||||
#include "nsWindow.h"
|
|
||||||
#include "nsScreenManagerGonk.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -1458,50 +1451,6 @@ CompositorOGL::EndFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
|
||||||
void
|
|
||||||
CompositorOGL::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
|
|
||||||
{
|
|
||||||
// OpenGL does not provide ReleaseFence for rendering.
|
|
||||||
// Instead use DispAcquireFence as layer buffer's ReleaseFence
|
|
||||||
// to prevent flickering and tearing.
|
|
||||||
// DispAcquireFence is DisplaySurface's AcquireFence.
|
|
||||||
// AcquireFence will be signaled when a buffer's content is available.
|
|
||||||
// See Bug 974152.
|
|
||||||
|
|
||||||
if (!aLayer || !aWidget) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nsWindow* window = static_cast<nsWindow*>(aWidget);
|
|
||||||
RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
|
|
||||||
window->GetScreen()->GetPrevDispAcquireFd());
|
|
||||||
mReleaseFenceHandle.Merge(FenceHandle(fence));
|
|
||||||
}
|
|
||||||
|
|
||||||
FenceHandle
|
|
||||||
CompositorOGL::GetReleaseFence()
|
|
||||||
{
|
|
||||||
if (!mReleaseFenceHandle.IsValid()) {
|
|
||||||
return FenceHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetDupFdObj();
|
|
||||||
return FenceHandle(fdObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
CompositorOGL::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FenceHandle
|
|
||||||
CompositorOGL::GetReleaseFence()
|
|
||||||
{
|
|
||||||
return FenceHandle();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
|
CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,8 +232,6 @@ public:
|
||||||
const gfx::Rect& aVisibleRect) override;
|
const gfx::Rect& aVisibleRect) override;
|
||||||
|
|
||||||
virtual void EndFrame() override;
|
virtual void EndFrame() override;
|
||||||
virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget) override;
|
|
||||||
virtual FenceHandle GetReleaseFence() override;
|
|
||||||
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
|
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
|
||||||
|
|
||||||
virtual bool SupportsPartialTextureUpdate() override;
|
virtual bool SupportsPartialTextureUpdate() override;
|
||||||
|
@ -452,7 +450,6 @@ private:
|
||||||
*/
|
*/
|
||||||
gfx::IntSize mViewportSize;
|
gfx::IntSize mViewportSize;
|
||||||
|
|
||||||
FenceHandle mReleaseFenceHandle;
|
|
||||||
ShaderProgramOGL *mCurrentProgram;
|
ShaderProgramOGL *mCurrentProgram;
|
||||||
|
|
||||||
gfx::Rect mRenderBound;
|
gfx::Rect mRenderBound;
|
||||||
|
|
|
@ -118,7 +118,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
|
||||||
mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
|
mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
|
||||||
mCropSize = mSize;
|
mCropSize = mSize;
|
||||||
} else {
|
} else {
|
||||||
printf_stderr("gralloc buffer is nullptr");
|
printf_stderr("gralloc buffer is nullptr\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ GrallocTextureHostOGL::WaitAcquireFenceHandleSyncComplete()
|
||||||
EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(),
|
EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(),
|
||||||
sync,
|
sync,
|
||||||
0,
|
0,
|
||||||
400000000 /*400 usec*/);
|
400000000 /*400 msec*/);
|
||||||
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
|
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
|
||||||
NS_ERROR("failed to wait native fence sync");
|
NS_ERROR("failed to wait native fence sync");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html style="font-size: 70368744177663%; -moz-background-size: 2199023255552em 809464690865px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4%2F58BAAT%2FAf9jgNErAAAAAElFTkSuQmCC);">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<html><body style="font-size-adjust: -18446744073709552000; font-weight: bold;">鎅</body></html>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<html style="-moz-box-shadow: 0 0 0.2em blue; -moz-appearance: button;"><body style="padding: 113in;"></body></html>
|
|
@ -79,10 +79,12 @@ load 483120-2.xhtml
|
||||||
load 487549-1.html
|
load 487549-1.html
|
||||||
load 487724-1.html
|
load 487724-1.html
|
||||||
load 490777-1.html
|
load 490777-1.html
|
||||||
|
load 516512-1.html
|
||||||
load 532726-1.html
|
load 532726-1.html
|
||||||
load 538065-1.html
|
load 538065-1.html
|
||||||
load 546870-1.html
|
load 546870-1.html
|
||||||
load 557348-1.html
|
load 557348-1.html
|
||||||
|
load 563740-1.html
|
||||||
load 580100-1.html
|
load 580100-1.html
|
||||||
load 580212-1.html
|
load 580212-1.html
|
||||||
load 580233-1.html
|
load 580233-1.html
|
||||||
|
@ -90,6 +92,7 @@ load 580719-1.html
|
||||||
load 593526.html
|
load 593526.html
|
||||||
load 593526.xul
|
load 593526.xul
|
||||||
load 594654-1.xhtml
|
load 594654-1.xhtml
|
||||||
|
load 595042-1.html
|
||||||
load 595727-1.html
|
load 595727-1.html
|
||||||
load 624198.xhtml
|
load 624198.xhtml
|
||||||
load 633453-1.html
|
load 633453-1.html
|
||||||
|
|
|
@ -163,7 +163,6 @@ RasterImage::Init(const char* aMimeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
|
|
||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
RasterImage::RequestRefresh(const TimeStamp& aTime)
|
RasterImage::RequestRefresh(const TimeStamp& aTime)
|
||||||
{
|
{
|
||||||
|
@ -543,8 +542,6 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
|
|
||||||
* in uint32_t aFlags); */
|
|
||||||
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
RasterImage::GetFrame(uint32_t aWhichFrame,
|
RasterImage::GetFrame(uint32_t aWhichFrame,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
|
@ -972,7 +969,6 @@ RasterImage::ResetAnimation()
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
// [notxpcom] void setAnimationStartTime ([const] in TimeStamp aTime);
|
|
||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
RasterImage::SetAnimationStartTime(const TimeStamp& aTime)
|
RasterImage::SetAnimationStartTime(const TimeStamp& aTime)
|
||||||
{
|
{
|
||||||
|
@ -1478,15 +1474,6 @@ RasterImage::DrawInternal(DrawableFrameRef&& aFrameRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* [noscript] void draw(in gfxContext aContext,
|
|
||||||
* in Filter aFilter,
|
|
||||||
* [const] in gfxMatrix aUserSpaceToImageSpace,
|
|
||||||
* [const] in gfxRect aFill,
|
|
||||||
* [const] in IntRect aSubimage,
|
|
||||||
* [const] in IntSize aViewportSize,
|
|
||||||
* [const] in SVGImageContext aSVGContext,
|
|
||||||
* in uint32_t aWhichFrame,
|
|
||||||
* in uint32_t aFlags); */
|
|
||||||
NS_IMETHODIMP_(DrawResult)
|
NS_IMETHODIMP_(DrawResult)
|
||||||
RasterImage::Draw(gfxContext* aContext,
|
RasterImage::Draw(gfxContext* aContext,
|
||||||
const IntSize& aSize,
|
const IntSize& aSize,
|
||||||
|
|
|
@ -200,9 +200,6 @@ SVGDocumentWrapper::TickRefreshDriver()
|
||||||
|
|
||||||
/** nsIStreamListener methods **/
|
/** nsIStreamListener methods **/
|
||||||
|
|
||||||
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsIInputStream inStr, in unsigned long sourceOffset,
|
|
||||||
in unsigned long count); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
SVGDocumentWrapper::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
SVGDocumentWrapper::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
||||||
nsIInputStream* inStr,
|
nsIInputStream* inStr,
|
||||||
|
@ -236,8 +233,6 @@ SVGDocumentWrapper::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsresult status); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
SVGDocumentWrapper::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt,
|
SVGDocumentWrapper::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt,
|
||||||
nsresult status)
|
nsresult status)
|
||||||
|
|
|
@ -683,8 +683,6 @@ VectorImage::IsOpaque()
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
|
|
||||||
* in uint32_t aFlags; */
|
|
||||||
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags)
|
VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags)
|
||||||
{
|
{
|
||||||
|
@ -793,13 +791,6 @@ struct SVGDrawingParameters
|
||||||
};
|
};
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* [noscript] void draw(in gfxContext aContext,
|
|
||||||
* [const] in nsIntSize aSize,
|
|
||||||
* [const] in ImageRegion aRegion,
|
|
||||||
* in uint32_t aWhichFrame,
|
|
||||||
* in Filter aFilter,
|
|
||||||
* [const] in MaybeSVGImageContext aSVGContext,
|
|
||||||
* in uint32_t aFlags); */
|
|
||||||
NS_IMETHODIMP_(DrawResult)
|
NS_IMETHODIMP_(DrawResult)
|
||||||
VectorImage::Draw(gfxContext* aContext,
|
VectorImage::Draw(gfxContext* aContext,
|
||||||
const nsIntSize& aSize,
|
const nsIntSize& aSize,
|
||||||
|
@ -1134,8 +1125,6 @@ VectorImage::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* void onStopRequest(in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsresult status); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
VectorImage::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
|
VectorImage::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
|
||||||
nsresult aStatus)
|
nsresult aStatus)
|
||||||
|
@ -1241,9 +1230,6 @@ VectorImage::OnSVGDocumentError()
|
||||||
// nsIStreamListener method
|
// nsIStreamListener method
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
/* void onDataAvailable(in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsIInputStream inStr, in unsigned long sourceOffset,
|
|
||||||
in unsigned long count); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
VectorImage::OnDataAvailable(nsIRequest* aRequest, nsISupports* aCtxt,
|
VectorImage::OnDataAvailable(nsIRequest* aRequest, nsISupports* aCtxt,
|
||||||
nsIInputStream* aInStr, uint64_t aSourceOffset,
|
nsIInputStream* aInStr, uint64_t aSourceOffset,
|
||||||
|
|
|
@ -60,6 +60,12 @@
|
||||||
// - It also added an optional color profile table after the pixel data (and
|
// - It also added an optional color profile table after the pixel data (and
|
||||||
// another optional gap).
|
// another optional gap).
|
||||||
//
|
//
|
||||||
|
// WinBMPv3-ICO. This is a variant of WinBMPv3.
|
||||||
|
// - It's the BMP format used for BMP images within ICO files.
|
||||||
|
// - The only difference with WinBMPv3 is that if an image is 32bpp and has no
|
||||||
|
// compression, then instead of treating the pixel data as 0RGB it is treated
|
||||||
|
// as ARGB, but only if one or more of the A values are non-zero.
|
||||||
|
//
|
||||||
// OS/2 VERSIONS OF THE BMP FORMAT
|
// OS/2 VERSIONS OF THE BMP FORMAT
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// OS2-BMPv1.
|
// OS2-BMPv1.
|
||||||
|
@ -168,6 +174,9 @@ GetBMPLog()
|
||||||
nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
|
nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
|
||||||
: Decoder(aImage)
|
: Decoder(aImage)
|
||||||
, mLexer(Transition::To(State::FILE_HEADER, FileHeader::LENGTH))
|
, mLexer(Transition::To(State::FILE_HEADER, FileHeader::LENGTH))
|
||||||
|
, mIsWithinICO(false)
|
||||||
|
, mMayHaveTransparency(false)
|
||||||
|
, mDoesHaveTransparency(false)
|
||||||
, mNumColors(0)
|
, mNumColors(0)
|
||||||
, mColors(nullptr)
|
, mColors(nullptr)
|
||||||
, mBytesPerColor(0)
|
, mBytesPerColor(0)
|
||||||
|
@ -175,8 +184,6 @@ nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
|
||||||
, mCurrentRow(0)
|
, mCurrentRow(0)
|
||||||
, mCurrentPos(0)
|
, mCurrentPos(0)
|
||||||
, mAbsoluteModeNumPixels(0)
|
, mAbsoluteModeNumPixels(0)
|
||||||
, mUseAlphaData(false)
|
|
||||||
, mHaveAlphaData(false)
|
|
||||||
{
|
{
|
||||||
memset(&mBFH, 0, sizeof(mBFH));
|
memset(&mBFH, 0, sizeof(mBFH));
|
||||||
memset(&mBIH, 0, sizeof(mBIH));
|
memset(&mBIH, 0, sizeof(mBIH));
|
||||||
|
@ -187,13 +194,6 @@ nsBMPDecoder::~nsBMPDecoder()
|
||||||
delete[] mColors;
|
delete[] mColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets whether or not the BMP will use alpha data.
|
|
||||||
void
|
|
||||||
nsBMPDecoder::SetUseAlphaData(bool useAlphaData)
|
|
||||||
{
|
|
||||||
mUseAlphaData = useAlphaData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtains the bits per pixel from the internal BIH header.
|
// Obtains the bits per pixel from the internal BIH header.
|
||||||
int32_t
|
int32_t
|
||||||
nsBMPDecoder::GetBitsPerPixel() const
|
nsBMPDecoder::GetBitsPerPixel() const
|
||||||
|
@ -250,7 +250,8 @@ nsBMPDecoder::FinishInternal()
|
||||||
nsIntRect r(0, 0, mBIH.width, GetHeight());
|
nsIntRect r(0, 0, mBIH.width, GetHeight());
|
||||||
PostInvalidation(r);
|
PostInvalidation(r);
|
||||||
|
|
||||||
if (mUseAlphaData && mHaveAlphaData) {
|
if (mDoesHaveTransparency) {
|
||||||
|
MOZ_ASSERT(mMayHaveTransparency);
|
||||||
PostFrameStop(Opacity::SOME_TRANSPARENCY);
|
PostFrameStop(Opacity::SOME_TRANSPARENCY);
|
||||||
} else {
|
} else {
|
||||||
PostFrameStop(Opacity::OPAQUE);
|
PostFrameStop(Opacity::OPAQUE);
|
||||||
|
@ -268,21 +269,39 @@ BitFields::Value::Set(uint32_t aMask)
|
||||||
{
|
{
|
||||||
mMask = aMask;
|
mMask = aMask;
|
||||||
|
|
||||||
|
// Handle this exceptional case first. The chosen values don't matter
|
||||||
|
// (because a mask of zero will always give a value of zero) except that
|
||||||
|
// mBitWidth:
|
||||||
|
// - shouldn't be zero, because that would cause an infinite loop in Get();
|
||||||
|
// - shouldn't be 5 or 8, because that could cause a false positive match in
|
||||||
|
// IsR5G5B5() or IsR8G8B8().
|
||||||
|
if (mMask == 0x0) {
|
||||||
|
mRightShift = 0;
|
||||||
|
mBitWidth = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the rightmost 1.
|
// Find the rightmost 1.
|
||||||
bool started = false;
|
uint8_t i;
|
||||||
mRightShift = mBitWidth = 0;
|
for (i = 0; i < 32; i++) {
|
||||||
for (uint8_t pos = 0; pos <= 31; pos++) {
|
if (mMask & (1 << i)) {
|
||||||
if (!started && (aMask & (1 << pos))) {
|
|
||||||
mRightShift = pos;
|
|
||||||
started = true;
|
|
||||||
} else if (started && !(aMask & (1 << pos))) {
|
|
||||||
mBitWidth = pos - mRightShift;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mRightShift = i;
|
||||||
|
|
||||||
|
// Now find the leftmost 1 in the same run of 1s. (If there are multiple runs
|
||||||
|
// of 1s -- which isn't valid -- we'll behave as if only the lowest run was
|
||||||
|
// present, which seems reasonable.)
|
||||||
|
for (i = i + 1; i < 32; i++) {
|
||||||
|
if (!(mMask & (1 << i))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mBitWidth = i - mRightShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t
|
MOZ_ALWAYS_INLINE uint8_t
|
||||||
BitFields::Value::Get(uint32_t aValue) const
|
BitFields::Value::Get(uint32_t aValue) const
|
||||||
{
|
{
|
||||||
// Extract the unscaled value.
|
// Extract the unscaled value.
|
||||||
|
@ -314,6 +333,16 @@ BitFields::Value::Get(uint32_t aValue) const
|
||||||
return v2;
|
return v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE uint8_t
|
||||||
|
BitFields::Value::GetAlpha(uint32_t aValue, bool& aHasAlphaOut) const
|
||||||
|
{
|
||||||
|
if (mMask == 0x0) {
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
aHasAlphaOut = true;
|
||||||
|
return Get(aValue);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE uint8_t
|
MOZ_ALWAYS_INLINE uint8_t
|
||||||
BitFields::Value::Get5(uint32_t aValue) const
|
BitFields::Value::Get5(uint32_t aValue) const
|
||||||
{
|
{
|
||||||
|
@ -322,6 +351,14 @@ BitFields::Value::Get5(uint32_t aValue) const
|
||||||
return (v << 3u) | (v >> 2u);
|
return (v << 3u) | (v >> 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE uint8_t
|
||||||
|
BitFields::Value::Get8(uint32_t aValue) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mBitWidth == 8);
|
||||||
|
uint32_t v = (aValue & mMask) >> mRightShift;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BitFields::SetR5G5B5()
|
BitFields::SetR5G5B5()
|
||||||
{
|
{
|
||||||
|
@ -330,12 +367,30 @@ BitFields::SetR5G5B5()
|
||||||
mBlue.Set(0x001f);
|
mBlue.Set(0x001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BitFields::SetR8G8B8()
|
||||||
|
{
|
||||||
|
mRed.Set(0xff0000);
|
||||||
|
mGreen.Set(0xff00);
|
||||||
|
mBlue.Set(0x00ff);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BitFields::IsR5G5B5() const
|
BitFields::IsR5G5B5() const
|
||||||
{
|
{
|
||||||
return mRed.mBitWidth == 5 &&
|
return mRed.mBitWidth == 5 &&
|
||||||
mGreen.mBitWidth == 5 &&
|
mGreen.mBitWidth == 5 &&
|
||||||
mBlue.mBitWidth == 5;
|
mBlue.mBitWidth == 5 &&
|
||||||
|
mAlpha.mMask == 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BitFields::IsR8G8B8() const
|
||||||
|
{
|
||||||
|
return mRed.mBitWidth == 8 &&
|
||||||
|
mGreen.mBitWidth == 8 &&
|
||||||
|
mBlue.mBitWidth == 8 &&
|
||||||
|
mAlpha.mMask == 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t*
|
uint32_t*
|
||||||
|
@ -458,6 +513,9 @@ nsBMPDecoder::ReadInfoHeaderSize(const char* aData, size_t aLength)
|
||||||
PostDataError();
|
PostDataError();
|
||||||
return Transition::Terminate(State::FAILURE);
|
return Transition::Terminate(State::FAILURE);
|
||||||
}
|
}
|
||||||
|
// ICO BMPs must have a WinVMPv3 header. nsICODecoder should have already
|
||||||
|
// terminated decoding if this isn't the case.
|
||||||
|
MOZ_ASSERT_IF(mIsWithinICO, mBIH.bihsize == InfoHeaderLength::WIN_V3);
|
||||||
|
|
||||||
return Transition::To(State::INFO_HEADER_REST,
|
return Transition::To(State::INFO_HEADER_REST,
|
||||||
mBIH.bihsize - BIHSIZE_FIELD_LENGTH);
|
mBIH.bihsize - BIHSIZE_FIELD_LENGTH);
|
||||||
|
@ -530,6 +588,7 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength)
|
||||||
// Post our size to the superclass.
|
// Post our size to the superclass.
|
||||||
uint32_t realHeight = GetHeight();
|
uint32_t realHeight = GetHeight();
|
||||||
PostSize(mBIH.width, realHeight);
|
PostSize(mBIH.width, realHeight);
|
||||||
|
mCurrentRow = realHeight;
|
||||||
|
|
||||||
// Round it up to the nearest byte count, then pad to 4-byte boundary.
|
// Round it up to the nearest byte count, then pad to 4-byte boundary.
|
||||||
// Compute this even for a metadate decode because GetCompressedImageSize()
|
// Compute this even for a metadate decode because GetCompressedImageSize()
|
||||||
|
@ -540,24 +599,69 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength)
|
||||||
mPixelRowSize += 4 - surplus;
|
mPixelRowSize += 4 - surplus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We treat BMPs as transparent if they're 32bpp and alpha is enabled, but
|
size_t bitFieldsLengthStillToRead = 0;
|
||||||
// also if they use RLE encoding, because the 'delta' mode can skip pixels
|
if (mBIH.compression == Compression::BITFIELDS) {
|
||||||
// and cause implicit transparency.
|
// Need to read bitfields.
|
||||||
bool hasTransparency = (mBIH.compression == Compression::RLE8) ||
|
if (mBIH.bihsize >= InfoHeaderLength::WIN_V4) {
|
||||||
(mBIH.compression == Compression::RLE4) ||
|
// Bitfields are present in the info header, so we can read them
|
||||||
(mBIH.bpp == 32 && mUseAlphaData);
|
// immediately.
|
||||||
if (hasTransparency) {
|
mBitFields.ReadFromHeader(aData + 36, /* aReadAlpha = */ true);
|
||||||
|
} else {
|
||||||
|
// Bitfields are present after the info header, so we will read them in
|
||||||
|
// ReadBitfields().
|
||||||
|
bitFieldsLengthStillToRead = BitFields::LENGTH;
|
||||||
|
}
|
||||||
|
} else if (mBIH.bpp == 16) {
|
||||||
|
// No bitfields specified; use the default 5-5-5 values.
|
||||||
|
mBitFields.SetR5G5B5();
|
||||||
|
} else if (mBIH.bpp == 32) {
|
||||||
|
// No bitfields specified; use the default 8-8-8 values.
|
||||||
|
mBitFields.SetR8G8B8();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transition::To(State::BITFIELDS, bitFieldsLengthStillToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BitFields::ReadFromHeader(const char* aData, bool aReadAlpha)
|
||||||
|
{
|
||||||
|
mRed.Set (LittleEndian::readUint32(aData + 0));
|
||||||
|
mGreen.Set(LittleEndian::readUint32(aData + 4));
|
||||||
|
mBlue.Set (LittleEndian::readUint32(aData + 8));
|
||||||
|
if (aReadAlpha) {
|
||||||
|
mAlpha.Set(LittleEndian::readUint32(aData + 12));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LexerTransition<nsBMPDecoder::State>
|
||||||
|
nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength)
|
||||||
|
{
|
||||||
|
mPreGapLength += aLength;
|
||||||
|
|
||||||
|
// If aLength is zero there are no bitfields to read, or we already read them
|
||||||
|
// in ReadInfoHeader().
|
||||||
|
if (aLength != 0) {
|
||||||
|
mBitFields.ReadFromHeader(aData, /* aReadAlpha = */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that RLE-encoded BMPs might be transparent because the 'delta' mode
|
||||||
|
// can skip pixels and cause implicit transparency.
|
||||||
|
mMayHaveTransparency =
|
||||||
|
(mBIH.compression == Compression::RGB && mIsWithinICO && mBIH.bpp == 32) ||
|
||||||
|
mBIH.compression == Compression::RLE8 ||
|
||||||
|
mBIH.compression == Compression::RLE4 ||
|
||||||
|
(mBIH.compression == Compression::BITFIELDS &&
|
||||||
|
mBitFields.mAlpha.IsPresent());
|
||||||
|
if (mMayHaveTransparency) {
|
||||||
PostHasTransparency();
|
PostHasTransparency();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're doing a metadata decode, we're done.
|
// We've now read all the headers. If we're doing a metadata decode, we're
|
||||||
|
// done.
|
||||||
if (IsMetadataDecode()) {
|
if (IsMetadataDecode()) {
|
||||||
return Transition::Terminate(State::SUCCESS);
|
return Transition::Terminate(State::SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're doing a real decode.
|
|
||||||
mCurrentRow = realHeight;
|
|
||||||
|
|
||||||
// Set up the color table, if present; it'll be filled in by ReadColorTable().
|
// Set up the color table, if present; it'll be filled in by ReadColorTable().
|
||||||
if (mBIH.bpp <= 8) {
|
if (mBIH.bpp <= 8) {
|
||||||
mNumColors = 1 << mBIH.bpp;
|
mNumColors = 1 << mBIH.bpp;
|
||||||
|
@ -588,52 +692,13 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength)
|
||||||
// BMPs store their rows in reverse order, so the downscaler needs to
|
// BMPs store their rows in reverse order, so the downscaler needs to
|
||||||
// reverse them again when writing its output.
|
// reverse them again when writing its output.
|
||||||
rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
|
rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
|
||||||
mImageData, hasTransparency,
|
mImageData, mMayHaveTransparency,
|
||||||
/* aFlipVertically = */ true);
|
/* aFlipVertically = */ true);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return Transition::Terminate(State::FAILURE);
|
return Transition::Terminate(State::FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bitFieldsLengthStillToRead = 0;
|
|
||||||
if (mBIH.compression == Compression::BITFIELDS) {
|
|
||||||
// Need to read bitfields.
|
|
||||||
if (mBIH.bihsize >= InfoHeaderLength::WIN_V4) {
|
|
||||||
// Bitfields are present in the info header, so we can read them
|
|
||||||
// immediately.
|
|
||||||
mBitFields.ReadFromHeader(aData + 36);
|
|
||||||
} else {
|
|
||||||
// Bitfields are present after the info header, so we will read them in
|
|
||||||
// ReadBitfields().
|
|
||||||
bitFieldsLengthStillToRead = BitFields::LENGTH;
|
|
||||||
}
|
|
||||||
} else if (mBIH.bpp == 16) {
|
|
||||||
// No bitfields specified; use the default 5-5-5 values.
|
|
||||||
mBitFields.SetR5G5B5();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Transition::To(State::BITFIELDS, bitFieldsLengthStillToRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
BitFields::ReadFromHeader(const char* aData)
|
|
||||||
{
|
|
||||||
mRed.Set (LittleEndian::readUint32(aData + 0));
|
|
||||||
mGreen.Set(LittleEndian::readUint32(aData + 4));
|
|
||||||
mBlue.Set (LittleEndian::readUint32(aData + 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
LexerTransition<nsBMPDecoder::State>
|
|
||||||
nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength)
|
|
||||||
{
|
|
||||||
mPreGapLength += aLength;
|
|
||||||
|
|
||||||
// If aLength is zero there are no bitfields to read, or we already read them
|
|
||||||
// in ReadInfoHeader().
|
|
||||||
if (aLength != 0) {
|
|
||||||
mBitFields.ReadFromHeader(aData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Transition::To(State::COLOR_TABLE, mNumColors * mBytesPerColor);
|
return Transition::To(State::COLOR_TABLE, mNumColors * mBytesPerColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,14 +791,20 @@ nsBMPDecoder::ReadPixelRow(const char* aData)
|
||||||
src += 2;
|
src += 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
bool anyHasAlpha = false;
|
||||||
while (lpos > 0) {
|
while (lpos > 0) {
|
||||||
uint16_t val = LittleEndian::readUint16(src);
|
uint16_t val = LittleEndian::readUint16(src);
|
||||||
SetPixel(dst, mBitFields.mRed.Get(val),
|
SetPixel(dst, mBitFields.mRed.Get(val),
|
||||||
mBitFields.mGreen.Get(val),
|
mBitFields.mGreen.Get(val),
|
||||||
mBitFields.mBlue.Get(val));
|
mBitFields.mBlue.Get(val),
|
||||||
|
mBitFields.mAlpha.GetAlpha(val, anyHasAlpha));
|
||||||
--lpos;
|
--lpos;
|
||||||
src += 2;
|
src += 2;
|
||||||
}
|
}
|
||||||
|
if (anyHasAlpha) {
|
||||||
|
MOZ_ASSERT(mMayHaveTransparency);
|
||||||
|
mDoesHaveTransparency = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -746,19 +817,54 @@ nsBMPDecoder::ReadPixelRow(const char* aData)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
|
if (mBIH.compression == Compression::RGB && mIsWithinICO &&
|
||||||
|
mBIH.bpp == 32) {
|
||||||
|
// This is a special case only used for 32bpp WinBMPv3-ICO files, which
|
||||||
|
// could be in either 0RGB or ARGB format.
|
||||||
while (lpos > 0) {
|
while (lpos > 0) {
|
||||||
if (mUseAlphaData) {
|
// If src[3] is zero, we can't tell at this point if the image is
|
||||||
if (MOZ_UNLIKELY(!mHaveAlphaData && src[3])) {
|
// 0RGB or ARGB. So we just use 0 value as-is. If the image is 0RGB
|
||||||
PostHasTransparency();
|
// then mDoesHaveTransparency will be false at the end, we'll treat
|
||||||
mHaveAlphaData = true;
|
// the image as opaque, and the 0 alpha values will be ignored. If
|
||||||
|
// the image is ARGB then mDoesHaveTransparency will be true at the
|
||||||
|
// end and we'll treat the image as non-opaque. (Note: a
|
||||||
|
// fully-transparent ARGB image is indistinguishable from a 0RGB
|
||||||
|
// image, and we will render such an image as a 0RGB image, i.e.
|
||||||
|
// opaquely. This is unlikely to be a problem in practice.)
|
||||||
|
if (src[3] != 0) {
|
||||||
|
MOZ_ASSERT(mMayHaveTransparency);
|
||||||
|
mDoesHaveTransparency = true;
|
||||||
}
|
}
|
||||||
SetPixel(dst, src[2], src[1], src[0], src[3]);
|
SetPixel(dst, src[2], src[1], src[0], src[3]);
|
||||||
} else {
|
src += 4;
|
||||||
SetPixel(dst, src[2], src[1], src[0]);
|
--lpos;
|
||||||
}
|
}
|
||||||
|
} else if (mBitFields.IsR8G8B8()) {
|
||||||
|
// Specialize this common case.
|
||||||
|
while (lpos > 0) {
|
||||||
|
uint32_t val = LittleEndian::readUint32(src);
|
||||||
|
SetPixel(dst, mBitFields.mRed.Get8(val),
|
||||||
|
mBitFields.mGreen.Get8(val),
|
||||||
|
mBitFields.mBlue.Get8(val));
|
||||||
--lpos;
|
--lpos;
|
||||||
src += 4;
|
src += 4;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bool anyHasAlpha = false;
|
||||||
|
while (lpos > 0) {
|
||||||
|
uint32_t val = LittleEndian::readUint32(src);
|
||||||
|
SetPixel(dst, mBitFields.mRed.Get(val),
|
||||||
|
mBitFields.mGreen.Get(val),
|
||||||
|
mBitFields.mBlue.Get(val),
|
||||||
|
mBitFields.mAlpha.GetAlpha(val, anyHasAlpha));
|
||||||
|
--lpos;
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
if (anyHasAlpha) {
|
||||||
|
MOZ_ASSERT(mMayHaveTransparency);
|
||||||
|
mDoesHaveTransparency = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -840,13 +946,10 @@ nsBMPDecoder::ReadRLESegment(const char* aData)
|
||||||
LexerTransition<nsBMPDecoder::State>
|
LexerTransition<nsBMPDecoder::State>
|
||||||
nsBMPDecoder::ReadRLEDelta(const char* aData)
|
nsBMPDecoder::ReadRLEDelta(const char* aData)
|
||||||
{
|
{
|
||||||
// Delta encoding makes it possible to skip pixels making the image
|
// Delta encoding makes it possible to skip pixels making part of the image
|
||||||
// transparent.
|
// transparent.
|
||||||
if (MOZ_UNLIKELY(!mHaveAlphaData)) {
|
MOZ_ASSERT(mMayHaveTransparency);
|
||||||
PostHasTransparency();
|
mDoesHaveTransparency = true;
|
||||||
mHaveAlphaData = true;
|
|
||||||
}
|
|
||||||
mUseAlphaData = mHaveAlphaData = true;
|
|
||||||
|
|
||||||
if (mDownscaler) {
|
if (mDownscaler) {
|
||||||
// Clear the skipped pixels. (This clears to the end of the row,
|
// Clear the skipped pixels. (This clears to the end of the row,
|
||||||
|
|
|
@ -38,12 +38,26 @@ class BitFields {
|
||||||
void Set(uint32_t aMask);
|
void Set(uint32_t aMask);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Value()
|
||||||
|
{
|
||||||
|
mMask = 0;
|
||||||
|
mRightShift = 0;
|
||||||
|
mBitWidth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this channel is used. Only used for alpha.
|
||||||
|
bool IsPresent() const { return mMask != 0x0; }
|
||||||
|
|
||||||
/// Extracts the single color value from the multi-color value.
|
/// Extracts the single color value from the multi-color value.
|
||||||
uint8_t Get(uint32_t aVal) const;
|
uint8_t Get(uint32_t aVal) const;
|
||||||
|
|
||||||
/// Specialized version of Get() for the case where the bit-width is 5.
|
/// Like Get(), but specially for alpha.
|
||||||
/// (It will assert if called and the bit-width is not 5.)
|
uint8_t GetAlpha(uint32_t aVal, bool& aHasAlphaOut) const;
|
||||||
|
|
||||||
|
/// Specialized versions of Get() for when the bit-width is 5 or 8.
|
||||||
|
/// (They will assert if called and the bit-width is not 5 or 8.)
|
||||||
uint8_t Get5(uint32_t aVal) const;
|
uint8_t Get5(uint32_t aVal) const;
|
||||||
|
uint8_t Get8(uint32_t aVal) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -51,15 +65,23 @@ public:
|
||||||
Value mRed;
|
Value mRed;
|
||||||
Value mGreen;
|
Value mGreen;
|
||||||
Value mBlue;
|
Value mBlue;
|
||||||
|
Value mAlpha;
|
||||||
|
|
||||||
/// Set bitfields to the standard 5-5-5 16bpp values.
|
/// Set bitfields to the standard 5-5-5 16bpp values.
|
||||||
void SetR5G5B5();
|
void SetR5G5B5();
|
||||||
|
|
||||||
|
/// Set bitfields to the standard 8-8-8 32bpp values.
|
||||||
|
void SetR8G8B8();
|
||||||
|
|
||||||
/// Test if bitfields have the standard 5-5-5 16bpp values.
|
/// Test if bitfields have the standard 5-5-5 16bpp values.
|
||||||
bool IsR5G5B5() const;
|
bool IsR5G5B5() const;
|
||||||
|
|
||||||
/// Read the bitfields from a header.
|
/// Test if bitfields have the standard 8-8-8 32bpp values.
|
||||||
void ReadFromHeader(const char* aData);
|
bool IsR8G8B8() const;
|
||||||
|
|
||||||
|
/// Read the bitfields from a header. The reading of the alpha mask is
|
||||||
|
/// optional.
|
||||||
|
void ReadFromHeader(const char* aData, bool aReadAlpha);
|
||||||
|
|
||||||
/// Length of the bitfields structure in the BMP file.
|
/// Length of the bitfields structure in the BMP file.
|
||||||
static const size_t LENGTH = 12;
|
static const size_t LENGTH = 12;
|
||||||
|
@ -76,11 +98,6 @@ class nsBMPDecoder : public Decoder
|
||||||
public:
|
public:
|
||||||
~nsBMPDecoder();
|
~nsBMPDecoder();
|
||||||
|
|
||||||
/// Specifies whether or not the BMP file will contain alpha data. If set to
|
|
||||||
/// true and the BMP is 32BPP, the alpha data will be retrieved from the 4th
|
|
||||||
/// byte of image data per pixel.
|
|
||||||
void SetUseAlphaData(bool useAlphaData);
|
|
||||||
|
|
||||||
/// Obtains the bits per pixel from the internal BIH header.
|
/// Obtains the bits per pixel from the internal BIH header.
|
||||||
int32_t GetBitsPerPixel() const;
|
int32_t GetBitsPerPixel() const;
|
||||||
|
|
||||||
|
@ -97,12 +114,19 @@ public:
|
||||||
/// Obtains the size of the compressed image resource.
|
/// Obtains the size of the compressed image resource.
|
||||||
int32_t GetCompressedImageSize() const;
|
int32_t GetCompressedImageSize() const;
|
||||||
|
|
||||||
/// Obtains whether or not a BMP file had alpha data in its 4th byte for 32BPP
|
/// Mark this BMP as being within an ICO file.
|
||||||
/// bitmaps. Use only after the bitmap has been processed.
|
void SetIsWithinICO() { mIsWithinICO = true; }
|
||||||
bool HasAlphaData() const { return mHaveAlphaData; }
|
|
||||||
|
|
||||||
/// Marks this BMP as having alpha data (due to e.g. an ICO alpha mask).
|
/// Did the BMP file have alpha data of any kind? (Only use this after the
|
||||||
void SetHasAlphaData() { mHaveAlphaData = true; }
|
/// bitmap has been fully decoded.)
|
||||||
|
bool HasTransparency() const { return mDoesHaveTransparency; }
|
||||||
|
|
||||||
|
/// Force transparency from outside. (Used by the ICO decoder.)
|
||||||
|
void SetHasTransparency()
|
||||||
|
{
|
||||||
|
mMayHaveTransparency = true;
|
||||||
|
mDoesHaveTransparency = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void WriteInternal(const char* aBuffer,
|
virtual void WriteInternal(const char* aBuffer,
|
||||||
uint32_t aCount) override;
|
uint32_t aCount) override;
|
||||||
|
@ -151,8 +175,19 @@ private:
|
||||||
bmp::FileHeader mBFH;
|
bmp::FileHeader mBFH;
|
||||||
bmp::V5InfoHeader mBIH;
|
bmp::V5InfoHeader mBIH;
|
||||||
|
|
||||||
|
// If the BMP is within an ICO file our treatment of it differs slightly.
|
||||||
|
bool mIsWithinICO;
|
||||||
|
|
||||||
bmp::BitFields mBitFields;
|
bmp::BitFields mBitFields;
|
||||||
|
|
||||||
|
// Might the image have transparency? Determined from the headers during
|
||||||
|
// metadata decode. (Does not guarantee the image actually has transparency.)
|
||||||
|
bool mMayHaveTransparency;
|
||||||
|
|
||||||
|
// Does the image have transparency? Determined during full decoding, so only
|
||||||
|
// use this after that has been completed.
|
||||||
|
bool mDoesHaveTransparency;
|
||||||
|
|
||||||
uint32_t mNumColors; // The number of used colors, i.e. the number of
|
uint32_t mNumColors; // The number of used colors, i.e. the number of
|
||||||
// entries in mColors, if it's present.
|
// entries in mColors, if it's present.
|
||||||
bmp::ColorTableEntry* mColors; // The color table, if it's present.
|
bmp::ColorTableEntry* mColors; // The color table, if it's present.
|
||||||
|
@ -171,18 +206,6 @@ private:
|
||||||
|
|
||||||
// Only used in RLE_ABSOLUTE state: the number of pixels to read.
|
// Only used in RLE_ABSOLUTE state: the number of pixels to read.
|
||||||
uint32_t mAbsoluteModeNumPixels;
|
uint32_t mAbsoluteModeNumPixels;
|
||||||
|
|
||||||
// Stores whether the image data may store alpha data, or if the alpha data
|
|
||||||
// is unspecified and filled with a padding byte of 0. When a 32BPP bitmap
|
|
||||||
// is stored in an ICO or CUR file, its 4th byte is used for alpha
|
|
||||||
// transparency. When it is stored in a BMP, its 4th byte is reserved and
|
|
||||||
// is always 0. Reference:
|
|
||||||
// http://en.wikipedia.org/wiki/ICO_(file_format)#cite_note-9
|
|
||||||
// Bitmaps where the alpha bytes are all 0 should be fully visible.
|
|
||||||
bool mUseAlphaData;
|
|
||||||
|
|
||||||
// Whether the 4th byte alpha data was found to be non zero and hence used.
|
|
||||||
bool mHaveAlphaData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
|
|
|
@ -393,7 +393,7 @@ nsICODecoder::SniffResource(const char* aData)
|
||||||
// is the AND mask, which isn't present in standalone BMPs.
|
// is the AND mask, which isn't present in standalone BMPs.
|
||||||
nsBMPDecoder* bmpDecoder = new nsBMPDecoder(mImage);
|
nsBMPDecoder* bmpDecoder = new nsBMPDecoder(mImage);
|
||||||
mContainedDecoder = bmpDecoder;
|
mContainedDecoder = bmpDecoder;
|
||||||
bmpDecoder->SetUseAlphaData(true);
|
bmpDecoder->SetIsWithinICO();
|
||||||
mContainedDecoder->SetMetadataDecode(IsMetadataDecode());
|
mContainedDecoder->SetMetadataDecode(IsMetadataDecode());
|
||||||
mContainedDecoder->SetDecoderFlags(GetDecoderFlags());
|
mContainedDecoder->SetDecoderFlags(GetDecoderFlags());
|
||||||
mContainedDecoder->SetSurfaceFlags(GetSurfaceFlags());
|
mContainedDecoder->SetSurfaceFlags(GetSurfaceFlags());
|
||||||
|
@ -525,9 +525,9 @@ nsICODecoder::PrepareForMask()
|
||||||
MOZ_ASSERT(bmpLengthWithHeader < mDirEntry.mBytesInRes);
|
MOZ_ASSERT(bmpLengthWithHeader < mDirEntry.mBytesInRes);
|
||||||
uint32_t maskLength = mDirEntry.mBytesInRes - bmpLengthWithHeader;
|
uint32_t maskLength = mDirEntry.mBytesInRes - bmpLengthWithHeader;
|
||||||
|
|
||||||
// If we have a 32-bpp BMP with alpha data, we ignore the AND mask. We can
|
// If the BMP provides its own transparency, we ignore the AND mask. We can
|
||||||
// also obviously ignore it if the image has zero width or zero height.
|
// also obviously ignore it if the image has zero width or zero height.
|
||||||
if ((bmpDecoder->GetBitsPerPixel() == 32 && bmpDecoder->HasAlphaData()) ||
|
if (bmpDecoder->HasTransparency() ||
|
||||||
GetRealWidth() == 0 || GetRealHeight() == 0) {
|
GetRealWidth() == 0 || GetRealHeight() == 0) {
|
||||||
return Transition::ToUnbuffered(ICOState::FINISHED_RESOURCE,
|
return Transition::ToUnbuffered(ICOState::FINISHED_RESOURCE,
|
||||||
ICOState::SKIP_MASK,
|
ICOState::SKIP_MASK,
|
||||||
|
@ -658,7 +658,7 @@ nsICODecoder::FinishMask()
|
||||||
|
|
||||||
RefPtr<nsBMPDecoder> bmpDecoder =
|
RefPtr<nsBMPDecoder> bmpDecoder =
|
||||||
static_cast<nsBMPDecoder*>(mContainedDecoder.get());
|
static_cast<nsBMPDecoder*>(mContainedDecoder.get());
|
||||||
bmpDecoder->SetHasAlphaData();
|
bmpDecoder->SetHasTransparency();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transition::To(ICOState::FINISHED_RESOURCE, 0);
|
return Transition::To(ICOState::FINISHED_RESOURCE, 0);
|
||||||
|
|
|
@ -268,8 +268,6 @@ nsJPEGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
|
||||||
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
|
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in
|
|
||||||
voidPtr aClosure, in unsigned long aCount); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsJPEGEncoder::ReadSegments(nsWriteSegmentFun aWriter,
|
nsJPEGEncoder::ReadSegments(nsWriteSegmentFun aWriter,
|
||||||
void* aClosure, uint32_t aCount, uint32_t* _retval)
|
void* aClosure, uint32_t aCount, uint32_t* _retval)
|
||||||
|
|
|
@ -548,17 +548,12 @@ nsPNGEncoder::Available(uint64_t* _retval)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [noscript] unsigned long read (in charPtr aBuf,
|
|
||||||
in unsigned long aCount); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPNGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
|
nsPNGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
|
||||||
{
|
{
|
||||||
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
|
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter,
|
|
||||||
in voidPtr aClosure,
|
|
||||||
in unsigned long aCount); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter,
|
nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter,
|
||||||
void* aClosure, uint32_t aCount,
|
void* aClosure, uint32_t aCount,
|
||||||
|
|
|
@ -2008,15 +2008,6 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// imgIRequest loadImage(in nsIURI aURI,
|
|
||||||
// in nsIURI aInitialDocumentURL,
|
|
||||||
// in nsIURI aReferrerURI,
|
|
||||||
// in nsIPrincipal aLoadingPrincipal,
|
|
||||||
// in nsILoadGroup aLoadGroup,
|
|
||||||
// in imgINotificationObserver aObserver,
|
|
||||||
// in nsISupports aCX,
|
|
||||||
// in nsLoadFlags aLoadFlags,
|
|
||||||
// in nsISupports cacheKey);
|
|
||||||
nsresult
|
nsresult
|
||||||
imgLoader::LoadImage(nsIURI* aURI,
|
imgLoader::LoadImage(nsIURI* aURI,
|
||||||
nsIURI* aInitialDocumentURI,
|
nsIURI* aInitialDocumentURI,
|
||||||
|
@ -2294,11 +2285,6 @@ imgLoader::LoadImage(nsIURI* aURI,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* imgIRequest
|
|
||||||
loadImageWithChannelXPCOM(in nsIChannel channel,
|
|
||||||
in imgINotificationObserver aObserver,
|
|
||||||
in nsISupports cx,
|
|
||||||
out nsIStreamListener); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
imgLoader::LoadImageWithChannelXPCOM(nsIChannel* channel,
|
imgLoader::LoadImageWithChannelXPCOM(nsIChannel* channel,
|
||||||
imgINotificationObserver* aObserver,
|
imgINotificationObserver* aObserver,
|
||||||
|
@ -2635,8 +2621,6 @@ ProxyListener::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||||
return mDestListener->OnStartRequest(aRequest, ctxt);
|
return mDestListener->OnStartRequest(aRequest, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsresult status); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ProxyListener::OnStopRequest(nsIRequest* aRequest,
|
ProxyListener::OnStopRequest(nsIRequest* aRequest,
|
||||||
nsISupports* ctxt,
|
nsISupports* ctxt,
|
||||||
|
@ -2651,10 +2635,6 @@ ProxyListener::OnStopRequest(nsIRequest* aRequest,
|
||||||
|
|
||||||
/** nsIStreamListener methods **/
|
/** nsIStreamListener methods **/
|
||||||
|
|
||||||
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsIInputStream inStr,
|
|
||||||
in unsigned long long sourceOffset,
|
|
||||||
in unsigned long count); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ProxyListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
ProxyListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
||||||
nsIInputStream* inStr, uint64_t sourceOffset,
|
nsIInputStream* inStr, uint64_t sourceOffset,
|
||||||
|
@ -2853,8 +2833,6 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||||
return mDestListener->OnStartRequest(aRequest, ctxt);
|
return mDestListener->OnStartRequest(aRequest, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsresult status); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
|
imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
|
||||||
nsISupports* ctxt,
|
nsISupports* ctxt,
|
||||||
|
@ -2873,10 +2851,6 @@ imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
|
||||||
/** nsIStreamListener methods **/
|
/** nsIStreamListener methods **/
|
||||||
|
|
||||||
|
|
||||||
/* void
|
|
||||||
onDataAvailable (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
in nsIInputStream inStr, in unsigned long long sourceOffset,
|
|
||||||
in unsigned long count); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
imgCacheValidator::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
imgCacheValidator::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
|
||||||
nsIInputStream* inStr,
|
nsIInputStream* inStr,
|
||||||
|
|
|
@ -804,8 +804,6 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
|
|
||||||
nsresult status); */
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
imgRequest::OnStopRequest(nsIRequest* aRequest,
|
imgRequest::OnStopRequest(nsIRequest* aRequest,
|
||||||
nsISupports* ctxt, nsresult status)
|
nsISupports* ctxt, nsresult status)
|
||||||
|
|
|
@ -194,13 +194,13 @@ ImageTestCase FirstFramePaddingGIFTestCase()
|
||||||
TEST_CASE_IS_TRANSPARENT);
|
TEST_CASE_IS_TRANSPARENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase()
|
ImageTestCase TransparentIfWithinICOBMPTestCase(TestCaseFlags aFlags)
|
||||||
{
|
{
|
||||||
// Note that we only decode this test case as transparent when the BMP decoder
|
// This is a BMP that is only transparent when decoded as if it is within an
|
||||||
// is set to use alpha data. (That's not the default, which is why it's not marked
|
// ICO file. (Note: aFlags needs to be set to TEST_CASE_DEFAULT_FLAGS or
|
||||||
// TEST_CASE_IS_TRANSPARENT; tests that want to treat this testcase as
|
// TEST_CASE_IS_TRANSPARENT accordingly.)
|
||||||
// transparent need to handle this case manually.)
|
return ImageTestCase("transparent-if-within-ico.bmp", "image/bmp",
|
||||||
return ImageTestCase("transparent.bmp", "image/bmp", IntSize(32, 32));
|
IntSize(32, 32), aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageTestCase RLE4BMPTestCase()
|
ImageTestCase RLE4BMPTestCase()
|
||||||
|
|
|
@ -38,15 +38,15 @@ TEST(ImageMetadata, ImageModuleAvailable)
|
||||||
EXPECT_TRUE(imgTools != nullptr);
|
EXPECT_TRUE(imgTools != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class BMPAlpha
|
enum class BMPWithinICO
|
||||||
{
|
{
|
||||||
DISABLED,
|
NO,
|
||||||
ENABLED
|
YES
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CheckMetadata(const ImageTestCase& aTestCase,
|
CheckMetadata(const ImageTestCase& aTestCase,
|
||||||
BMPAlpha aBMPAlpha = BMPAlpha::DISABLED)
|
BMPWithinICO aBMPWithinICO = BMPWithinICO::NO)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
|
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
|
||||||
ASSERT_TRUE(inputStream != nullptr);
|
ASSERT_TRUE(inputStream != nullptr);
|
||||||
|
@ -70,8 +70,8 @@ CheckMetadata(const ImageTestCase& aTestCase,
|
||||||
DecoderFactory::CreateAnonymousMetadataDecoder(decoderType, sourceBuffer);
|
DecoderFactory::CreateAnonymousMetadataDecoder(decoderType, sourceBuffer);
|
||||||
ASSERT_TRUE(decoder != nullptr);
|
ASSERT_TRUE(decoder != nullptr);
|
||||||
|
|
||||||
if (aBMPAlpha == BMPAlpha::ENABLED) {
|
if (aBMPWithinICO == BMPWithinICO::YES) {
|
||||||
static_cast<nsBMPDecoder*>(decoder.get())->SetUseAlphaData(true);
|
static_cast<nsBMPDecoder*>(decoder.get())->SetIsWithinICO();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the metadata decoder synchronously.
|
// Run the metadata decoder synchronously.
|
||||||
|
@ -100,7 +100,7 @@ CheckMetadata(const ImageTestCase& aTestCase,
|
||||||
EXPECT_EQ(aTestCase.mSize.width, metadataSize.width);
|
EXPECT_EQ(aTestCase.mSize.width, metadataSize.width);
|
||||||
EXPECT_EQ(aTestCase.mSize.height, metadataSize.height);
|
EXPECT_EQ(aTestCase.mSize.height, metadataSize.height);
|
||||||
|
|
||||||
bool expectTransparency = aBMPAlpha == BMPAlpha::ENABLED
|
bool expectTransparency = aBMPWithinICO == BMPWithinICO::YES
|
||||||
? true
|
? true
|
||||||
: bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT);
|
: bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT);
|
||||||
EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY));
|
EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY));
|
||||||
|
@ -114,8 +114,8 @@ CheckMetadata(const ImageTestCase& aTestCase,
|
||||||
DefaultSurfaceFlags());
|
DefaultSurfaceFlags());
|
||||||
ASSERT_TRUE(decoder != nullptr);
|
ASSERT_TRUE(decoder != nullptr);
|
||||||
|
|
||||||
if (aBMPAlpha == BMPAlpha::ENABLED) {
|
if (aBMPWithinICO == BMPWithinICO::YES) {
|
||||||
static_cast<nsBMPDecoder*>(decoder.get())->SetUseAlphaData(true);
|
static_cast<nsBMPDecoder*>(decoder.get())->SetIsWithinICO();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the full decoder synchronously.
|
// Run the full decoder synchronously.
|
||||||
|
@ -164,14 +164,16 @@ TEST(ImageMetadata, FirstFramePaddingGIF)
|
||||||
CheckMetadata(FirstFramePaddingGIFTestCase());
|
CheckMetadata(FirstFramePaddingGIFTestCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ImageMetadata, TransparentBMPWithBMPAlphaOff)
|
TEST(ImageMetadata, TransparentIfWithinICOBMPNotWithinICO)
|
||||||
{
|
{
|
||||||
CheckMetadata(TransparentBMPWhenBMPAlphaEnabledTestCase(), BMPAlpha::ENABLED);
|
CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_DEFAULT_FLAGS),
|
||||||
|
BMPWithinICO::NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ImageMetadata, TransparentBMPWithBMPAlphaOn)
|
TEST(ImageMetadata, TransparentIfWithinICOBMPWithinICO)
|
||||||
{
|
{
|
||||||
CheckMetadata(TransparentBMPWhenBMPAlphaEnabledTestCase(), BMPAlpha::ENABLED);
|
CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_IS_TRANSPARENT),
|
||||||
|
BMPWithinICO::YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ImageMetadata, RLE4BMP) { CheckMetadata(RLE4BMPTestCase()); }
|
TEST(ImageMetadata, RLE4BMP) { CheckMetadata(RLE4BMPTestCase()); }
|
||||||
|
|
|
@ -29,7 +29,7 @@ TEST_HARNESS_FILES.gtest += [
|
||||||
'no-frame-delay.gif',
|
'no-frame-delay.gif',
|
||||||
'rle4.bmp',
|
'rle4.bmp',
|
||||||
'rle8.bmp',
|
'rle8.bmp',
|
||||||
'transparent.bmp',
|
'transparent-if-within-ico.bmp',
|
||||||
'transparent.gif',
|
'transparent.gif',
|
||||||
'transparent.png',
|
'transparent.png',
|
||||||
]
|
]
|
||||||
|
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 4.1 KiB После Ширина: | Высота: | Размер: 4.1 KiB |
|
@ -108,7 +108,5 @@ fuzzy(1,1516) == rgb16.bmp rgb16.png
|
||||||
# "A 32-bit image with a BITFIELDS segment. As usual, there are 8 bits per color
|
# "A 32-bit image with a BITFIELDS segment. As usual, there are 8 bits per color
|
||||||
# channel, and 8 unused bits. But the color channels are in an unusual order,
|
# channel, and 8 unused bits. But the color channels are in an unusual order,
|
||||||
# so the viewer must read the BITFIELDS, and not just guess."
|
# so the viewer must read the BITFIELDS, and not just guess."
|
||||||
# [XXX: we get this completely wrong because we don't handle BITFIELDS at all
|
== rgb32bf.bmp rgb24.png
|
||||||
# in 32bpp BMPs. Chromium gets this right.]
|
|
||||||
fails == rgb32bf.bmp rgb24.png
|
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,7 @@ fuzzy(1,899) == pal8os2v2-16.bmp pal8.png
|
||||||
# "A 16-bit image with an alpha channel. There are 4 bits for each color
|
# "A 16-bit image with an alpha channel. There are 4 bits for each color
|
||||||
# channel, and 4 bits for the alpha channel. It’s not clear if this is valid,
|
# channel, and 4 bits for the alpha channel. It’s not clear if this is valid,
|
||||||
# but I can’t find anything that suggests it isn’t."
|
# but I can’t find anything that suggests it isn’t."
|
||||||
# [XXX: we don't even try to do transparency for 16bpp. Chromium gets the
|
== rgba16-4444.bmp rgba16-4444.png
|
||||||
# transparency right.]
|
|
||||||
fails == rgba16-4444.bmp rgba16-4444.png
|
|
||||||
|
|
||||||
# BMP: bihsize=40, 127 x 64, bpp=24, compression=0, colors=300
|
# BMP: bihsize=40, 127 x 64, bpp=24, compression=0, colors=300
|
||||||
# "A 24-bit image, with a palette containing 300 colors. The fact that the
|
# "A 24-bit image, with a palette containing 300 colors. The fact that the
|
||||||
|
@ -114,18 +112,14 @@ fails == rgba16-4444.bmp rgba16-4444.png
|
||||||
# BMP: bihsize=40, 127 x 64, bpp=32, compression=3, colors=0
|
# BMP: bihsize=40, 127 x 64, bpp=32, compression=3, colors=0
|
||||||
# "A 32 bits/pixel image, with all 32 bits used: 11 each for red and green, and
|
# "A 32 bits/pixel image, with all 32 bits used: 11 each for red and green, and
|
||||||
# 10 for blue. As far as I know, this is perfectly valid, but it is unusual."
|
# 10 for blue. As far as I know, this is perfectly valid, but it is unusual."
|
||||||
# [XXX: we get this completely wrong because we don't handle BITFIELDS at all
|
fuzzy(1,1408) == rgb32-111110.bmp rgb24.png
|
||||||
# in 32bpp BMPs. Chromium gets this right.]
|
|
||||||
fails == rgb32-111110.bmp rgb24.png
|
|
||||||
|
|
||||||
# BMP: bihsize=124, 127 x 64, bpp=32, compression=3, colors=0
|
# BMP: bihsize=124, 127 x 64, bpp=32, compression=3, colors=0
|
||||||
# "A BMP with an alpha channel. Transparency is barely documented, so it’s
|
# "A BMP with an alpha channel. Transparency is barely documented, so it’s
|
||||||
# possible that this file is not correctly formed. The color channels are in an
|
# possible that this file is not correctly formed. The color channels are in an
|
||||||
# unusual order, to prevent viewers from passing this test by making a lucky
|
# unusual order, to prevent viewers from passing this test by making a lucky
|
||||||
# guess."
|
# guess."
|
||||||
# [XXX: we get this completely wrong because we don't handle BITFIELDS at all
|
== rgba32.bmp rgba32.png
|
||||||
# in 32bpp BMPs, especially not with alpha. Chromium gets this right.]
|
|
||||||
fails == rgba32.bmp rgba32.png
|
|
||||||
|
|
||||||
# BMP: bihsize=40, 127 x 64, bpp=32, compression=6, colors=0
|
# BMP: bihsize=40, 127 x 64, bpp=32, compression=6, colors=0
|
||||||
# "An image of type BI_ALPHABITFIELDS. Supposedly, this was used on Windows CE.
|
# "An image of type BI_ALPHABITFIELDS. Supposedly, this was used on Windows CE.
|
||||||
|
|
|
@ -130,9 +130,6 @@ nsScriptableUnicodeConverter::ConvertToUnicode(const nsACString& aSrc, nsAString
|
||||||
_retval);
|
_retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AString convertFromByteArray([const,array,size_is(aCount)] in octet aData,
|
|
||||||
in unsigned long aCount);
|
|
||||||
*/
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData,
|
nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData,
|
||||||
uint32_t aCount,
|
uint32_t aCount,
|
||||||
|
@ -168,10 +165,6 @@ nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void convertToByteArray(in AString aString,
|
|
||||||
[optional] out unsigned long aLen,
|
|
||||||
[array, size_is(aLen),retval] out octet aData);
|
|
||||||
*/
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptableUnicodeConverter::ConvertToByteArray(const nsAString& aString,
|
nsScriptableUnicodeConverter::ConvertToByteArray(const nsAString& aString,
|
||||||
uint32_t* aLen,
|
uint32_t* aLen,
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче