merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-08-04 13:01:07 +02:00
commit 0903b3fd7b
383 changed files with 10634 additions and 4688 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1190180 - need clobber for backouts
Bug 1186748 needed a CLOBBER again

View File

@ -692,7 +692,8 @@ void
DocAccessible::AttributeWillChange(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType)
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aNewValue)
{
Accessible* accessible = GetAccessible(aElement);
if (!accessible) {
@ -733,7 +734,8 @@ void
DocAccessible::AttributeChanged(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID, nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
NS_ASSERTION(!IsDefunct(),
"Attribute changed called on defunct document accessible!");

View File

@ -9,6 +9,7 @@ let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/ExtensionContent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
"resource:///modules/E10SUtils.jsm");
@ -656,3 +657,8 @@ let DOMFullscreenHandler = {
}
};
DOMFullscreenHandler.init();
ExtensionContent.init(this);
addEventListener("unload", () => {
ExtensionContent.uninit(this);
});

View File

@ -0,0 +1,20 @@
/* 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/. */
"use strict";
Components.utils.import("resource://gre/modules/Extension.jsm");
let extension;
function startup(data, reason)
{
extension = new Extension(data);
extension.startup();
}
function shutdown(data, reason)
{
extension.shutdown();
}

View File

@ -0,0 +1,326 @@
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
Cu.import("resource://gre/modules/devtools/event-emitter.js");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
let {
EventManager,
DefaultWeakMap,
ignoreEvent,
runSafe,
} = ExtensionUtils;
// WeakMap[Extension -> BrowserAction]
let browserActionMap = new WeakMap();
function browserActionOf(extension)
{
return browserActionMap.get(extension);
}
function makeWidgetId(id)
{
id = id.toLowerCase();
return id.replace(/[^a-z0-9_-]/g, "_");
}
let nextActionId = 0;
// Responsible for the browser_action section of the manifest as well
// as the associated popup.
function BrowserAction(options, extension)
{
this.extension = extension;
this.id = makeWidgetId(extension.id) + "-browser-action";
this.widget = null;
this.title = new DefaultWeakMap(extension.localize(options.default_title));
this.badgeText = new DefaultWeakMap();
this.badgeBackgroundColor = new DefaultWeakMap();
this.icon = new DefaultWeakMap(options.default_icon);
this.popup = new DefaultWeakMap(options.default_popup);
// Make the default something that won't compare equal to anything.
this.prevPopups = new DefaultWeakMap({});
this.context = null;
}
BrowserAction.prototype = {
build() {
let widget = CustomizableUI.createWidget({
id: this.id,
type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: document => {
let node = document.createElement("toolbarbutton");
node.id = this.id;
node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional badged-button");
node.setAttribute("constrain-size", "true");
this.updateTab(null, node);
let tabbrowser = document.defaultView.gBrowser;
tabbrowser.ownerDocument.addEventListener("TabSelect", () => {
this.updateTab(tabbrowser.selectedTab, node);
});
node.addEventListener("command", event => {
if (node.getAttribute("type") != "panel") {
this.emit("click");
}
});
return node;
},
});
this.widget = widget;
},
// Initialize the toolbar icon and popup given that |tab| is the
// current tab and |node| is the CustomizableUI node. Note: |tab|
// will be null if we don't know the current tab yet (during
// initialization).
updateTab(tab, node) {
let window = node.ownerDocument.defaultView;
let title = this.getProperty(tab, "title");
if (title) {
node.setAttribute("tooltiptext", title);
node.setAttribute("label", title);
} else {
node.removeAttribute("tooltiptext");
node.removeAttribute("label");
}
let badgeText = this.badgeText.get(tab);
if (badgeText) {
node.setAttribute("badge", badgeText);
} else {
node.removeAttribute("badge");
}
function toHex(n) {
return Math.floor(n / 16).toString(16) + (n % 16).toString(16);
}
let badgeNode = node.ownerDocument.getAnonymousElementByAttribute(node,
'class', 'toolbarbutton-badge');
if (badgeNode) {
let color = this.badgeBackgroundColor.get(tab);
if (Array.isArray(color)) {
color = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
}
badgeNode.style.backgroundColor = color;
}
let iconURL = this.getIcon(tab, node);
node.setAttribute("image", iconURL);
let popup = this.getProperty(tab, "popup");
if (popup != this.prevPopups.get(window)) {
this.prevPopups.set(window, popup);
let panel = node.querySelector("panel");
if (panel) {
panel.remove();
}
if (popup) {
let popupURL = this.extension.baseURI.resolve(popup);
node.setAttribute("type", "panel");
let document = node.ownerDocument;
let panel = document.createElement("panel");
panel.setAttribute("class", "browser-action-panel");
panel.setAttribute("type", "arrow");
panel.setAttribute("flip", "slide");
node.appendChild(panel);
let browser = document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("width", "500");
browser.setAttribute("height", "500");
panel.appendChild(browser);
let loadListener = () => {
panel.removeEventListener("load", loadListener);
if (this.context) {
this.context.unload();
}
this.context = new ExtensionPage(this.extension, {
type: "popup",
contentWindow: browser.contentWindow,
uri: Services.io.newURI(popupURL, null, null),
docShell: browser.docShell,
});
GlobalManager.injectInDocShell(browser.docShell, this.extension, this.context);
browser.setAttribute("src", popupURL);
};
panel.addEventListener("load", loadListener);
} else {
node.removeAttribute("type");
}
}
},
// Note: tab is allowed to be null here.
getIcon(tab, node) {
let icon = this.icon.get(tab);
let url;
if (typeof(icon) != "object") {
url = icon;
} else {
let window = node.ownerDocument.defaultView;
let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
let res = {value: 1}
utils.getResolution(res);
let size = res.value == 1 ? 19 : 38;
url = icon[size];
}
if (url) {
return this.extension.baseURI.resolve(url);
} else {
return "chrome://browser/content/extension.svg";
}
},
// Update the toolbar button for a given window.
updateWindow(window) {
let tab = window.gBrowser ? window.gBrowser.selectedTab : null;
let node = CustomizableUI.getWidget(this.id).forWindow(window).node;
this.updateTab(tab, node);
},
// Update the toolbar button when the extension changes the icon,
// title, badge, etc. If it only changes a parameter for a single
// tab, |tab| will be that tab. Otherwise it will be null.
updateOnChange(tab) {
if (tab) {
if (tab.selected) {
this.updateWindow(tab.ownerDocument.defaultView);
}
} else {
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (window.gBrowser) {
this.updateWindow(window);
}
}
}
},
// tab is allowed to be null.
// prop should be one of "icon", "title", "badgeText", "popup", or "badgeBackgroundColor".
setProperty(tab, prop, value) {
this[prop].set(tab, value);
this.updateOnChange(tab);
},
// tab is allowed to be null.
// prop should be one of "title", "badgeText", "popup", or "badgeBackgroundColor".
getProperty(tab, prop) {
return this[prop].get(tab);
},
shutdown() {
CustomizableUI.destroyWidget(this.id);
},
};
EventEmitter.decorate(BrowserAction.prototype);
extensions.on("manifest_browser_action", (type, directive, extension, manifest) => {
let browserAction = new BrowserAction(manifest.browser_action, extension);
browserAction.build();
browserActionMap.set(extension, browserAction);
});
extensions.on("shutdown", (type, extension) => {
if (browserActionMap.has(extension)) {
browserActionMap.get(extension).shutdown();
browserActionMap.delete(extension);
}
});
extensions.registerAPI((extension, context) => {
return {
browserAction: {
onClicked: new EventManager(context, "browserAction.onClicked", fire => {
let listener = () => {
let tab = TabManager.activeTab;
fire(TabManager.convert(extension, tab));
};
browserActionOf(extension).on("click", listener);
return () => {
browserActionOf(extension).off("click", listener);
};
}).api(),
setTitle: function(details) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
browserActionOf(extension).setProperty(tab, "title", details.title);
},
getTitle: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
let title = browserActionOf(extension).getProperty(tab, "title");
runSafe(context, callback, title);
},
setIcon: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
if (details.imageData) {
// FIXME: Support the imageData attribute.
return;
}
browserActionOf(extension).setProperty(tab, "icon", details.path);
},
setBadgeText: function(details) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
browserActionOf(extension).setProperty(tab, "badgeText", details.text);
},
getBadgeText: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
let text = browserActionOf(extension).getProperty(tab, "badgeText");
runSafe(context, callback, text);
},
setPopup: function(details) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
browserActionOf(extension).setProperty(tab, "popup", details.popup);
},
getPopup: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
let popup = browserActionOf(extension).getProperty(tab, "popup");
runSafe(context, callback, popup);
},
setBadgeBackgroundColor: function(details) {
let color = details.color;
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
browserActionOf(extension).setProperty(tab, "badgeBackgroundColor", details.color);
},
getBadgeBackgroundColor: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
let color = browserActionOf(extension).getProperty(tab, "badgeBackgroundColor");
runSafe(context, callback, color);
},
}
};
});

View File

@ -0,0 +1,8 @@
extensions.registerPrivilegedAPI("contextMenus", (extension, context) => {
return {
contextMenus: {
create() {},
removeAll() {},
},
};
});

View File

@ -0,0 +1,486 @@
XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
"resource:///modules/NewTabURL.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
let {
EventManager,
ignoreEvent,
runSafe,
} = ExtensionUtils;
// This function is pretty tightly tied to Extension.jsm.
// Its job is to fill in the |tab| property of the sender.
function getSender(context, target, sender)
{
// The message was sent from a content script to a <browser> element.
// We can just get the |tab| from |target|.
if (target instanceof Ci.nsIDOMXULElement) {
// The message came from a content script.
let tabbrowser = target.ownerDocument.defaultView.gBrowser;
if (!tabbrowser) {
return;
}
let tab = tabbrowser.getTabForBrowser(target);
sender.tab = TabManager.convert(context.extension, tab);
} else {
// The message came from an ExtensionPage. In that case, it should
// include a tabId property (which is filled in by the page-open
// listener below).
if ("tabId" in sender) {
sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
delete sender.tabId;
}
}
}
// WeakMap[ExtensionPage -> {tab, parentWindow}]
let pageDataMap = new WeakMap();
// This listener fires whenever an extension page opens in a tab
// (either initiated by the extension or the user). Its job is to fill
// in some tab-specific details and keep data around about the
// ExtensionPage.
extensions.on("page-load", (type, page, params, sender, delegate) => {
if (params.type == "tab") {
let browser = params.docShell.chromeEventHandler;
let parentWindow = browser.ownerDocument.defaultView;
let tab = parentWindow.gBrowser.getTabForBrowser(browser);
sender.tabId = TabManager.getId(tab);
pageDataMap.set(page, {tab, parentWindow});
}
delegate.getSender = getSender;
});
extensions.on("page-unload", (type, page) => {
pageDataMap.delete(page);
});
extensions.on("page-shutdown", (type, page) => {
if (pageDataMap.has(page)) {
let {tab, parentWindow} = pageDataMap.get(page);
pageDataMap.delete(page);
parentWindow.gBrowser.removeTab(tab);
}
});
extensions.on("fill-browser-data", (type, browser, data, result) => {
let tabId = TabManager.getBrowserId(browser);
if (tabId == -1) {
result.cancel = true;
return;
}
data.tabId = tabId;
});
// TODO: activeTab permission
extensions.registerAPI((extension, context) => {
let self = {
tabs: {
onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
let tab = event.originalTarget;
let tabId = TabManager.getId(tab);
let windowId = WindowManager.getId(tab.ownerDocument.defaultView);
fire({tabId, windowId});
}).api(),
onCreated: new EventManager(context, "tabs.onCreated", fire => {
let listener = event => {
let tab = event.originalTarget;
fire({tab: TabManager.convert(extension, tab)});
};
let windowListener = window => {
for (let tab of window.gBrowser.tabs) {
fire({tab: TabManager.convert(extension, tab)});
}
};
WindowListManager.addOpenListener(windowListener, false);
AllWindowEvents.addListener("TabOpen", listener);
return () => {
WindowListManager.removeOpenListener(windowListener);
AllWindowEvents.removeListener("TabOpen", listener);
};
}).api(),
onUpdated: new EventManager(context, "tabs.onUpdated", fire => {
function sanitize(extension, changeInfo) {
let result = {};
let nonempty = false;
for (let prop in changeInfo) {
if ((prop != "favIconUrl" && prop != "url") || extension.hasPermission("tabs")) {
nonempty = true;
result[prop] = changeInfo[prop];
}
}
return [nonempty, result];
}
let listener = event => {
let tab = event.originalTarget;
let window = tab.ownerDocument.defaultView;
let tabId = TabManager.getId(tab);
let changeInfo = {};
let needed = false;
if (event.type == "TabAttrModified") {
if (event.detail.changed.indexOf("image") != -1) {
changeInfo.favIconUrl = window.gBrowser.getIcon(tab);
needed = true;
}
} else if (event.type == "TabPinned") {
changeInfo.pinned = true;
needed = true;
} else if (event.type == "TabUnpinned") {
changeInfo.pinned = false;
needed = true;
}
[needed, changeInfo] = sanitize(extension, changeInfo);
if (needed) {
fire(tabId, changeInfo, TabManager.convert(extension, tab));
}
};
let progressListener = {
onStateChange(browser, webProgress, request, stateFlags, statusCode) {
if (!webProgress.isTopLevel) {
return;
}
let status;
if (stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
status = "loading";
} else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
status = "complete";
}
} else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
statusCode == Cr.NS_BINDING_ABORTED) {
status = "complete";
}
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
let tab = gBrowser.getTabForBrowser(browser);
let tabId = TabManager.getId(tab);
let [needed, changeInfo] = sanitize(extension, {status});
fire(tabId, changeInfo, TabManager.convert(extension, tab));
},
onLocationChange(browser, webProgress, request, locationURI, flags) {
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
let tab = gBrowser.getTabForBrowser(browser);
let tabId = TabManager.getId(tab);
let [needed, changeInfo] = sanitize(extension, {url: locationURI.spec});
if (needed) {
fire(tabId, changeInfo, TabManager.convert(extension, tab));
}
},
};
AllWindowEvents.addListener("progress", progressListener);
AllWindowEvents.addListener("TabAttrModified", listener);
AllWindowEvents.addListener("TabPinned", listener);
AllWindowEvents.addListener("TabUnpinned", listener);
return () => {
AllWindowEvents.removeListener("progress", progressListener);
AllWindowEvents.addListener("TabAttrModified", listener);
AllWindowEvents.addListener("TabPinned", listener);
AllWindowEvents.addListener("TabUnpinned", listener);
};
}).api(),
onReplaced: ignoreEvent(),
onRemoved: new EventManager(context, "tabs.onRemoved", fire => {
let tabListener = event => {
let tab = event.originalTarget;
let tabId = TabManager.getId(tab);
let windowId = WindowManager.getId(tab.ownerDocument.defaultView);
let removeInfo = {windowId, isWindowClosing: false};
fire(tabId, removeInfo);
};
let windowListener = window => {
for (let tab of window.gBrowser.tabs) {
let tabId = TabManager.getId(tab);
let windowId = WindowManager.getId(window);
let removeInfo = {windowId, isWindowClosing: true};
fire(tabId, removeInfo);
}
};
WindowListManager.addCloseListener(windowListener);
AllWindowEvents.addListener("TabClose", tabListener);
return () => {
WindowListManager.removeCloseListener(windowListener);
AllWindowEvents.removeListener("TabClose", tabListener);
};
}).api(),
create: function(createProperties, callback) {
if (!createProperties) {
createProperties = {};
}
let url = createProperties.url || NewTabURL.get();
url = extension.baseURI.resolve(url);
function createInWindow(window) {
let tab = window.gBrowser.addTab(url);
let active = true;
if ("active" in createProperties) {
active = createProperties.active;
} else if ("selected" in createProperties) {
active = createProperties.selected;
}
if (active) {
window.gBrowser.selectedTab = tab;
}
if ("index" in createProperties) {
window.gBrowser.moveTabTo(tab, createProperties.index);
}
if (createProperties.pinned) {
window.gBrowser.pinTab(tab);
}
if (callback) {
runSafe(context, callback, TabManager.convert(extension, tab));
}
}
let window = createProperties.windowId ?
WindowManager.getWindow(createProperties.windowId) :
WindowManager.topWindow;
if (!window.gBrowser) {
let obs = (finishedWindow, topic, data) => {
if (finishedWindow != window) {
return;
}
Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
createInWindow(window);
};
Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
} else {
createInWindow(window);
}
},
remove: function(tabs, callback) {
if (!Array.isArray(tabs)) {
tabs = [tabs];
}
for (let tabId of tabs) {
let tab = TabManager.getTab(tabId);
tab.ownerDocument.defaultView.gBrowser.removeTab(tab);
}
if (callback) {
runSafe(context, callback);
}
},
update: function(...args) {
let tabId, updateProperties, callback;
if (args.length == 1) {
updateProperties = args[0];
} else {
[tabId, updateProperties, callback] = args;
}
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let tabbrowser = tab.ownerDocument.gBrowser;
if ("url" in updateProperties) {
tab.linkedBrowser.loadURI(updateProperties.url);
}
if ("active" in updateProperties) {
if (updateProperties.active) {
tabbrowser.selectedTab = tab;
} else {
// Not sure what to do here? Which tab should we select?
}
}
if ("pinned" in updateProperties) {
if (updateProperties.pinned) {
tabbrowser.pinTab(tab);
} else {
tabbrowser.unpinTab(tab);
}
}
// FIXME: highlighted/selected, openerTabId
if (callback) {
runSafe(context, callback, TabManager.convert(extension, tab));
}
},
reload: function(tabId, reloadProperties, callback) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
if (reloadProperties && reloadProperties.bypassCache) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
}
tab.linkedBrowser.reloadWithFlags(flags);
if (callback) {
runSafe(context, callback);
}
},
get: function(tabId, callback) {
let tab = TabManager.getTab(tabId);
runSafe(context, callback, TabManager.convert(extension, tab));
},
getAllInWindow: function(...args) {
let window, callback;
if (args.length == 1) {
callbacks = args[0];
} else {
window = WindowManager.getWindow(args[0]);
callback = args[1];
}
if (!window) {
window = WindowManager.topWindow;
}
return self.tabs.query({windowId: WindowManager.getId(window)}, callback);
},
query: function(queryInfo, callback) {
if (!queryInfo) {
queryInfo = {};
}
function matches(window, tab) {
let props = ["active", "pinned", "highlighted", "status", "title", "url", "index"];
for (let prop of props) {
if (prop in queryInfo && queryInfo[prop] != tab[prop]) {
return false;
}
}
let lastFocused = window == WindowManager.topWindow;
if ("lastFocusedWindow" in queryInfo && queryInfo.lastFocusedWindow != lastFocused) {
return false;
}
let windowType = WindowManager.windowType(window);
if ("windowType" in queryInfo && queryInfo.windowType != windowType) {
return false;
}
if ("windowId" in queryInfo) {
if (queryInfo.windowId == WindowManager.WINDOW_ID_CURRENT) {
if (context.contentWindow != window) {
return false;
}
} else {
if (queryInfo.windowId != tab.windowId) {
return false;
}
}
}
if ("currentWindow" in queryInfo) {
let eq = window == context.contentWindow;
if (queryInfo.currentWindow != eq) {
return false;
}
}
return true;
}
let result = [];
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
let tabs = TabManager.getTabs(extension, window);
for (let tab of tabs) {
if (matches(window, tab)) {
result.push(tab);
}
}
}
runSafe(context, callback, result);
},
_execute: function(tabId, details, kind, callback) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let mm = tab.linkedBrowser.messageManager;
let options = {js: [], css: []};
if (details.code) {
options[kind + 'Code'] = details.code;
}
if (details.file) {
options[kind].push(extension.baseURI.resolve(details.file));
}
if (details.allFrames) {
options.all_frames = details.allFrames;
}
if (details.matchAboutBlank) {
options.match_about_blank = details.matchAboutBlank;
}
if (details.runAt) {
options.run_at = details.runAt;
}
mm.sendAsyncMessage("Extension:Execute",
{extensionId: extension.id, options});
// TODO: Call the callback with the result (which is what???).
},
executeScript: function(...args) {
if (args.length == 1) {
self.tabs._execute(undefined, args[0], 'js', undefined);
} else {
self.tabs._execute(args[0], args[1], 'js', args[2]);
}
},
insertCss: function(tabId, details, callback) {
if (args.length == 1) {
self.tabs._execute(undefined, args[0], 'css', undefined);
} else {
self.tabs._execute(args[0], args[1], 'css', args[2]);
}
},
connect: function(tabId, connectInfo) {
let tab = TabManager.getTab(tabId);
let mm = tab.linkedBrowser.messageManager;
let name = connectInfo.name || "";
let recipient = {extensionId: extension.id};
if ("frameId" in connectInfo) {
recipient.frameId = connectInfo.frameId;
}
return context.messenger.connect(mm, name, recipient);
},
sendMessage: function(tabId, message, options, responseCallback) {
let tab = TabManager.getTab(tabId);
let mm = tab.linkedBrowser.messageManager;
let recipient = {extensionId: extension.id};
if (options && "frameId" in options) {
recipient.frameId = options.frameId;
}
return context.messenger.sendMessage(mm, message, recipient, responseCallback);
},
},
};
return self;
});

View File

@ -0,0 +1,324 @@
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
let {
EventManager,
} = ExtensionUtils;
// This file provides some useful code for the |tabs| and |windows|
// modules. All of the code is installed on |global|, which is a scope
// shared among the different ext-*.js scripts.
// Manages mapping between XUL tabs and extension tab IDs.
global.TabManager = {
_tabs: new WeakMap(),
_nextId: 1,
getId(tab) {
if (this._tabs.has(tab)) {
return this._tabs.get(tab);
}
let id = this._nextId++;
this._tabs.set(tab, id);
return id;
},
getBrowserId(browser) {
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
// Some non-browser windows have gBrowser but not
// getTabForBrowser!
if (gBrowser && gBrowser.getTabForBrowser) {
let tab = gBrowser.getTabForBrowser(browser);
if (tab) {
return this.getId(tab);
}
}
return -1;
},
getTab(tabId) {
// FIXME: Speed this up without leaking memory somehow.
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (!window.gBrowser) {
continue;
}
for (let tab of window.gBrowser.tabs) {
if (this.getId(tab) == tabId) {
return tab;
}
}
}
return null;
},
get activeTab() {
let window = WindowManager.topWindow;
if (window && window.gBrowser) {
return window.gBrowser.selectedTab;
}
return null;
},
getStatus(tab) {
return tab.getAttribute("busy") == "true" ? "loading" : "complete";
},
convert(extension, tab) {
let window = tab.ownerDocument.defaultView;
let windowActive = window == WindowManager.topWindow;
let result = {
id: this.getId(tab),
index: tab._tPos,
windowId: WindowManager.getId(window),
selected: tab.selected,
highlighted: tab.selected,
active: tab.selected,
pinned: tab.pinned,
status: this.getStatus(tab),
incognito: PrivateBrowsingUtils.isBrowserPrivate(tab.linkedBrowser),
width: tab.linkedBrowser.clientWidth,
height: tab.linkedBrowser.clientHeight,
};
if (extension.hasPermission("tabs")) {
result.url = tab.linkedBrowser.currentURI.spec;
if (tab.linkedBrowser.contentTitle) {
result.title = tab.linkedBrowser.contentTitle;
}
let icon = window.gBrowser.getIcon(tab);
if (icon) {
result.favIconUrl = icon;
}
}
return result;
},
getTabs(extension, window) {
if (!window.gBrowser) {
return [];
}
return [ for (tab of window.gBrowser.tabs) this.convert(extension, tab) ];
},
};
// Manages mapping between XUL windows and extension window IDs.
global.WindowManager = {
_windows: new WeakMap(),
_nextId: 0,
WINDOW_ID_NONE: -1,
WINDOW_ID_CURRENT: -2,
get topWindow() {
return Services.wm.getMostRecentWindow("navigator:browser");
},
windowType(window) {
// TODO: Make this work.
return "normal";
},
getId(window) {
if (this._windows.has(window)) {
return this._windows.get(window);
}
let id = this._nextId++;
this._windows.set(window, id);
return id;
},
getWindow(id) {
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (this.getId(window) == id) {
return window;
}
}
return null;
},
convert(extension, window, getInfo) {
let result = {
id: this.getId(window),
focused: window == WindowManager.topWindow,
top: window.screenY,
left: window.screenX,
width: window.outerWidth,
height: window.outerHeight,
incognito: PrivateBrowsingUtils.isWindowPrivate(window),
// We fudge on these next two.
type: this.windowType(window),
state: window.fullScreen ? "fullscreen" : "normal",
};
if (getInfo && getInfo.populate) {
results.tabs = TabManager.getTabs(extension, window);
}
return result;
},
};
// Manages listeners for window opening and closing. A window is
// considered open when the "load" event fires on it. A window is
// closed when a "domwindowclosed" notification fires for it.
global.WindowListManager = {
_openListeners: new Set(),
_closeListeners: new Set(),
addOpenListener(listener, fireOnExisting = true) {
if (this._openListeners.length == 0 && this._closeListeners.length == 0) {
Services.ww.registerNotification(this);
}
this._openListeners.add(listener);
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (window.document.readyState != "complete") {
window.addEventListener("load", this);
} else if (fireOnExisting) {
listener(window);
}
}
},
removeOpenListener(listener) {
this._openListeners.delete(listener);
if (this._openListeners.length == 0 && this._closeListeners.length == 0) {
Services.ww.unregisterNotification(this);
}
},
addCloseListener(listener) {
if (this._openListeners.length == 0 && this._closeListeners.length == 0) {
Services.ww.registerNotification(this);
}
this._closeListeners.add(listener);
},
removeCloseListener(listener) {
this._closeListeners.delete(listener);
if (this._openListeners.length == 0 && this._closeListeners.length == 0) {
Services.ww.unregisterNotification(this);
}
},
handleEvent(event) {
let window = event.target.defaultView;
window.removeEventListener("load", this.loadListener);
if (window.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
for (let listener of this._openListeners) {
listener(window);
}
},
queryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
observe(window, topic, data) {
if (topic == "domwindowclosed") {
if (window.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
window.removeEventListener("load", this);
for (let listener of this._closeListeners) {
listener(window);
}
} else {
window.addEventListener("load", this);
}
},
};
// Provides a facility to listen for DOM events across all XUL windows.
global.AllWindowEvents = {
_listeners: new Map(),
// If |type| is a normal event type, invoke |listener| each time
// that event fires in any open window. If |type| is "progress", add
// a web progress listener that covers all open windows.
addListener(type, listener) {
if (type == "domwindowopened") {
return WindowListManager.addOpenListener(listener);
} else if (type == "domwindowclosed") {
return WindowListManager.addCloseListener(listener);
}
let needOpenListener = this._listeners.size == 0;
if (!this._listeners.has(type)) {
this._listeners.set(type, new Set());
}
let list = this._listeners.get(type);
list.add(listener);
if (needOpenListener) {
WindowListManager.addOpenListener(this.openListener);
}
},
removeListener(type, listener) {
if (type == "domwindowopened") {
return WindowListManager.removeOpenListener(listener);
} else if (type == "domwindowclosed") {
return WindowListManager.removeCloseListener(listener);
}
let listeners = this._listeners.get(type);
listeners.delete(listener);
if (listeners.length == 0) {
this._listeners.delete(type);
if (this._listeners.size == 0) {
WindowListManager.removeOpenListener(this.openListener);
}
}
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (type == "progress") {
window.gBrowser.removeTabsProgressListener(listener);
} else {
window.removeEventListener(type, listener);
}
}
},
// Runs whenever the "load" event fires for a new window.
openListener(window) {
for (let [eventType, listeners] of AllWindowEvents._listeners) {
for (let listener of listeners) {
if (eventType == "progress") {
window.gBrowser.addTabsProgressListener(listener);
} else {
window.addEventListener(eventType, listener);
}
}
}
},
};
// Subclass of EventManager where we just need to call
// add/removeEventListener on each XUL window.
global.WindowEventManager = function(context, name, event, listener)
{
EventManager.call(this, context, name, fire => {
let listener2 = (...args) => listener(fire, ...args);
AllWindowEvents.addListener(event, listener2);
return () => {
AllWindowEvents.removeListener(event, listener2);
}
});
}
WindowEventManager.prototype = Object.create(EventManager.prototype);

View File

@ -0,0 +1,151 @@
XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
"resource:///modules/NewTabURL.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
let {
EventManager,
ignoreEvent,
runSafe,
} = ExtensionUtils;
extensions.registerAPI((extension, context) => {
return {
windows: {
WINDOW_ID_CURRENT: WindowManager.WINDOW_ID_CURRENT,
WINDOW_ID_NONE: WindowManager.WINDOW_ID_NONE,
onCreated:
new WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => {
fire(WindowManager.convert(extension, window));
}).api(),
onRemoved:
new WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => {
fire(WindowManager.getId(window));
}).api(),
onFocusChanged: new EventManager(context, "windows.onFocusChanged", fire => {
// FIXME: This will send multiple messages for a single focus change.
let listener = event => {
let window = WindowManager.topWindow;
let windowId = window ? WindowManager.getId(window) : WindowManager.WINDOW_ID_NONE;
fire(windowId);
};
AllWindowEvents.addListener("focus", listener);
AllWindowEvents.addListener("blur", listener);
return () => {
AllWindowEvents.removeListener("focus", listener);
AllWindowEvents.removeListener("blur", listener);
};
}).api(),
get: function(windowId, getInfo, callback) {
let window = WindowManager.getWindow(windowId);
runSafe(context, callback, WindowManager.convert(extension, window, getInfo));
},
getCurrent: function(getInfo, callback) {
let window = context.contentWindow;
runSafe(context, callback, WindowManager.convert(extension, window, getInfo));
},
getLastFocused: function(...args) {
let getInfo, callback;
if (args.length == 1) {
callback = args[0];
} else {
[getInfo, callback] = args;
}
let window = WindowManager.topWindow;
runSafe(context, callback, WindowManager.convert(extension, window, getInfo));
},
getAll: function(getAll, callback) {
let e = Services.wm.getEnumerator("navigator:browser");
let windows = [];
while (e.hasMoreElements()) {
let window = e.getNext();
windows.push(WindowManager.convert(extension, window, getInfo));
}
runSafe(context, callback, windows);
},
create: function(createData, callback) {
function mkstr(s) {
let result = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
result.data = s;
return result;
}
let args = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
if ("url" in createData) {
if (Array.isArray(createData.url)) {
let array = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
for (let url of createData.url) {
array.AppendElement(mkstr(url));
}
args.AppendElement(array);
} else {
args.AppendElement(mkstr(createData.url));
}
} else {
args.AppendElement(mkstr(NewTabURL.get()));
}
let extraFeatures = "";
if ("incognito" in createData) {
if (createData.incognito) {
extraFeatures += ",private";
} else {
extraFeatures += ",non-private";
}
}
let window = Services.ww.openWindow(null, "chrome://browser/content/browser.xul", "_blank",
"chrome,dialog=no,all" + extraFeatures, args);
if ("left" in createData || "top" in createData) {
let left = "left" in createData ? createData.left : window.screenX;
let top = "top" in createData ? createData.top : window.screenY;
window.moveTo(left, top);
}
if ("width" in createData || "height" in createData) {
let width = "width" in createData ? createData.width : window.outerWidth;
let height = "height" in createData ? createData.height : window.outerHeight;
window.resizeTo(width, height);
}
// TODO: focused, type, state
window.addEventListener("load", function listener() {
window.removeEventListener("load", listener);
if (callback) {
runSafe(context, callback, WindowManager.convert(extension, window));
}
});
},
update: function(windowId, updateInfo, callback) {
let window = WindowManager.getWindow(windowId);
if (updateInfo.focused) {
Services.focus.activeWindow = window;
}
// TODO: All the other properties...
runSafe(context, callback, WindowManager.convert(extension, window));
},
remove: function(windowId, callback) {
let window = WindowManager.getWindow(windowId);
window.close();
let listener = () => {
AllWindowEvents.removeListener("domwindowclosed", listener);
if (callback) {
runSafe(context, callback);
}
};
AllWindowEvents.addListener("domwindowclosed", listener);
},
},
};
});

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="64" height="64" viewBox="0 0 64 64">
<defs>
<style>
.style-puzzle-piece {
fill: url('#gradient-linear-puzzle-piece');
}
</style>
<linearGradient id="gradient-linear-puzzle-piece" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#66cc52" stop-opacity="1"/>
<stop offset="100%" stop-color="#60bf4c" stop-opacity="1"/>
</linearGradient>
</defs>
<path class="style-puzzle-piece" d="M42,62c2.2,0,4-1.8,4-4l0-14.2c0,0,0.4-3.7,2.8-3.7c2.4,0,2.2,3.9,6.7,3.9c2.3,0,6.2-1.2,6.2-8.2 c0-7-3.9-7.9-6.2-7.9c-4.5,0-4.3,3.7-6.7,3.7c-2.4,0-2.8-3.8-2.8-3.8V22c0-2.2-1.8-4-4-4H31.5c0,0-3.4-0.6-3.4-3 c0-2.4,3.8-2.6,3.8-7.1c0-2.3-1.3-5.9-8.3-5.9s-8,3.6-8,5.9c0,4.5,3.4,4.7,3.4,7.1c0,2.4-3.4,3-3.4,3H6c-2.2,0-4,1.8-4,4l0,7.8 c0,0-0.4,6,4.4,6c3.1,0,3.2-4.1,7.3-4.1c2,0,4,1.9,4,6c0,4.2-2,6.3-4,6.3c-4,0-4.2-4.1-7.3-4.1c-4.8,0-4.4,5.8-4.4,5.8L2,58 c0,2.2,1.8,4,4,4H19c0,0,6.3,0.4,6.3-4.4c0-3.1-4-3.6-4-7.7c0-2,2.2-4.5,6.4-4.5c4.2,0,6.6,2.5,6.6,4.5c0,4-3.9,4.6-3.9,7.7 c0,4.9,6.3,4.4,6.3,4.4H42z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,11 @@
# 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/.
browser.jar:
content/browser/extension.svg (extension.svg)
content/browser/ext-utils.js (ext-utils.js)
content/browser/ext-contextMenus.js (ext-contextMenus.js)
content/browser/ext-browserAction.js (ext-browserAction.js)
content/browser/ext-tabs.js (ext-tabs.js)
content/browser/ext-windows.js (ext-windows.js)

View File

@ -0,0 +1,7 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
JAR_MANIFESTS += ['jar.mn']

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
# 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/.
import argparse
import json
import uuid
import sys
import os.path
parser = argparse.ArgumentParser(description='Create install.rdf from manifest.json')
parser.add_argument('--locale')
parser.add_argument('--profile')
parser.add_argument('--uuid')
parser.add_argument('dir')
args = parser.parse_args()
manifestFile = os.path.join(args.dir, 'manifest.json')
manifest = json.load(open(manifestFile))
locale = args.locale
if not locale:
locale = manifest.get('default_locale', 'en-US')
def process_locale(s):
if s.startswith('__MSG_') and s.endswith('__'):
tag = s[6:-2]
path = os.path.join(args.dir, '_locales', locale, 'messages.json')
data = json.load(open(path))
return data[tag]['message']
else:
return s
id = args.uuid
if not id:
id = '{' + str(uuid.uuid4()) + '}'
name = process_locale(manifest['name'])
desc = process_locale(manifest['description'])
version = manifest['version']
installFile = open(os.path.join(args.dir, 'install.rdf'), 'w')
print >>installFile, '<?xml version="1.0"?>'
print >>installFile, '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'
print >>installFile, ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">'
print >>installFile
print >>installFile, ' <Description about="urn:mozilla:install-manifest">'
print >>installFile, ' <em:id>{}</em:id>'.format(id)
print >>installFile, ' <em:type>2</em:type>'
print >>installFile, ' <em:name>{}</em:name>'.format(name)
print >>installFile, ' <em:description>{}</em:description>'.format(desc)
print >>installFile, ' <em:version>{}</em:version>'.format(version)
print >>installFile, ' <em:bootstrap>true</em:bootstrap>'
print >>installFile, ' <em:targetApplication>'
print >>installFile, ' <Description>'
print >>installFile, ' <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>'
print >>installFile, ' <em:minVersion>4.0</em:minVersion>'
print >>installFile, ' <em:maxVersion>50.0</em:maxVersion>'
print >>installFile, ' </Description>'
print >>installFile, ' </em:targetApplication>'
print >>installFile, ' </Description>'
print >>installFile, '</RDF>'
installFile.close()
bootstrapPath = os.path.join(os.path.dirname(sys.argv[0]), 'bootstrap.js')
data = open(bootstrapPath).read()
boot = open(os.path.join(args.dir, 'bootstrap.js'), 'w')
boot.write(data)
boot.close()
if args.profile:
os.system('mkdir -p {}/extensions'.format(args.profile))
output = open(args.profile + '/extensions/' + id, 'w')
print >>output, os.path.realpath(args.dir)
output.close()
else:
dir = os.path.realpath(args.dir)
if dir[-1] == os.sep:
dir = dir[:-1]
os.system('cd "{}"; zip ../"{}".xpi -r *'.format(args.dir, os.path.basename(dir)))

View File

@ -9,6 +9,7 @@ DIRS += [
'customizableui',
'dirprovider',
'downloads',
'extensions',
'feeds',
'loop',
'migration',

View File

@ -169,6 +169,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement",
"resource://gre/modules/ExtensionManagement.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -601,6 +604,12 @@ BrowserGlue.prototype = {
os.addObserver(this, "xpi-signature-changed", false);
os.addObserver(this, "autocomplete-did-enter-text", false);
ExtensionManagement.registerScript("chrome://browser/content/ext-utils.js");
ExtensionManagement.registerScript("chrome://browser/content/ext-browserAction.js");
ExtensionManagement.registerScript("chrome://browser/content/ext-contextMenus.js");
ExtensionManagement.registerScript("chrome://browser/content/ext-tabs.js");
ExtensionManagement.registerScript("chrome://browser/content/ext-windows.js");
this._flashHangCount = 0;
},

View File

@ -26,6 +26,7 @@ CFLAGS="$CFLAGS -Wno-attributes"
CPPFLAGS="$CPPFLAGS -Wno-attributes"
CXXFLAGS="$CXXFLAGS -Wno-attributes"
TOOLTOOL_DIR="$(dirname $topsrcdir)"
export PKG_CONFIG_LIBDIR=/usr/lib64/pkgconfig:/usr/share/pkgconfig
. $topsrcdir/build/unix/mozconfig.gtk

View File

@ -7,10 +7,11 @@
"unpack": true
},
{
"size": 4079256,
"digest": "bb5238558bcf6db2ca395513c8dccaa15dd61b3c375598eb6a685356b0c1a2d9840e3bf81bc00242b872fd798541f53d723777c754412abf0e772b7cc284937c",
"size": 11179576,
"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"setup": "setup.sh",
"unpack": true
},
{

View File

@ -1,16 +0,0 @@
[
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
}
]

View File

@ -8,5 +8,13 @@
"algorithm": "sha512",
"filename": "clang.tar.bz2",
"unpack": true
},
{
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"setup": "setup.sh",
"unpack": true
}
]

View File

@ -7,10 +7,11 @@
"unpack": true
},
{
"size": 4431740,
"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"setup": "setup.sh",
"unpack": true
},
{

View File

@ -10,10 +10,11 @@
"unpack": true
},
{
"size": 4431740,
"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"setup": "setup.sh",
"unpack": true
}
]

View File

@ -1,16 +0,0 @@
[
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
}
]

View File

@ -59,6 +59,15 @@ this.E10SUtils = {
mustLoadRemote = chromeReg.mustLoadURLRemotely(url);
}
if (aURL.startsWith("moz-extension:")) {
canLoadRemote = false;
mustLoadRemote = false;
}
if (aURL.startsWith("view-source:")) {
return this.canLoadURIInProcess(aURL.substr("view-source:".length), aProcess);
}
if (mustLoadRemote)
return processIsRemote;

View File

@ -1944,3 +1944,7 @@ chatbox {
-moz-padding-end: 0 !important;
-moz-margin-end: 0 !important;
}
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}

View File

@ -3685,3 +3685,7 @@ window > chatbox {
padding-left: 0;
padding-right: 0;
}
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}

View File

@ -2904,3 +2904,7 @@ chatbox {
@media not all and (-moz-os-version: windows-xp) {
%include browser-aero.css
}
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}

View File

@ -241,6 +241,7 @@ class CustomTypeAnnotation {
RK_ArrayElement,
RK_BaseClass,
RK_Field,
RK_TemplateInherited,
};
struct AnnotationReason {
QualType Type;
@ -842,6 +843,15 @@ void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag, QualTyp
Diag.Report(Reason.Field->getLocation(), MemberID)
<< Pretty << T << Reason.Field << Reason.Type;
break;
case RK_TemplateInherited:
{
const CXXRecordDecl *Decl = T->getAsCXXRecordDecl();
assert(Decl && "This type should be a C++ class");
Diag.Report(Decl->getLocation(), TemplID)
<< Pretty << T << Reason.Type;
break;
}
default:
return;
}
@ -905,6 +915,29 @@ CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::directAnnotationRea
return Reason;
}
}
// Recurse into template arguments if the annotation
// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
if (MozChecker::hasCustomAnnotation(
Decl, "moz_inherit_type_annotations_from_template_args")) {
const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(Decl);
if (Spec) {
const TemplateArgumentList &Args = Spec->getTemplateArgs();
for (const TemplateArgument &Arg : Args.asArray()) {
if (Arg.getKind() == TemplateArgument::Type) {
QualType Type = Arg.getAsType();
if (hasEffectiveAnnotation(Type)) {
AnnotationReason Reason = { Type, RK_TemplateInherited, nullptr };
Cache[Key] = Reason;
return Reason;
}
}
}
}
}
}
}

View File

@ -0,0 +1,17 @@
#define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
class Normal {};
class MOZ_STACK_CLASS Stack {};
class IndirectStack : Stack {}; // expected-note {{'IndirectStack' is a stack type because it inherits from a stack type 'Stack'}}
template<class T>
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Template {}; // expected-note 2 {{'Template<Stack>' is a stack type because it has a template argument stack type 'Stack'}} expected-note {{'Template<IndirectStack>' is a stack type because it has a template argument stack type 'IndirectStack'}}
class IndirectTemplate : Template<Stack> {}; // expected-note {{'IndirectTemplate' is a stack type because it inherits from a stack type 'Template<Stack>'}}
static Template<Stack> a; // expected-error {{variable of type 'Template<Stack>' only valid on the stack}}
static Template<IndirectStack> b; // expected-error {{variable of type 'Template<IndirectStack>' only valid on the stack}}
static Template<Normal> c;
static IndirectTemplate d; // expected-error {{variable of type 'IndirectTemplate' only valid on the stack}}

View File

@ -9,6 +9,7 @@ SOURCES += [
'TestCustomHeap.cpp',
'TestExplicitOperatorBool.cpp',
'TestGlobalClass.cpp',
'TestInheritTypeAnnotationsFromTemplateArgs.cpp',
'TestMultipleAnnotations.cpp',
'TestMustOverride.cpp',
'TestMustUse.cpp',

View File

@ -47,6 +47,13 @@ leak:webrtc::DesktopApplication::
# Bug 1187518 - SCTP leaks in child process while running WebRTC tests.
leak:recv_function_udp
# Bug 1074310 - Very large e10s vp8 leaks, maybe in WebRTC tests.
leak:set_noise_sensitivity
leak:vp8_alloc_compressor_data
leak:vp8_change_config
leak:vp8_lookahead_init
leak:vpx_codec_enc_init_ver
###
### Many leaks only affect some test suites. The suite annotations are not checked.
@ -107,6 +114,14 @@ leak:MessageLoop::MessageLoop
leak:base::WaitableEvent::TimedWait
leak:MessageLoop::PostTask_Helper
# Bug 1189430 - DNS leaks in mochitest-chrome.
leak:nsDNSService::AsyncResolveExtended
leak:_GetAddrInfo_Portable
# Bug 1189568 - Indirect leaks of IMContextWrapper and nsIntRect.
leak:nsWindow::Create
leak:nsBaseWidget::StoreWindowClipRegion
###
### Leaks with system libraries in their stacks. These show up across a number of tests.

View File

@ -57,7 +57,7 @@ build() {
cd build/$name
eval ../../$name-$version/configure --disable-static $* $configure_args
make $make_flags
make install-strip DESTDIR=$root_dir/gtk3
make install DESTDIR=$root_dir/gtk3
find $root_dir/gtk3 -name \*.la -delete
cd ../..
}
@ -103,5 +103,44 @@ build gtk+
rm -rf $root_dir/gtk3/usr/local/share/gtk-doc
rm -rf $root_dir/gtk3/usr/local/share/locale
# mock build environment doesn't have fonts in /usr/share/fonts, but
# has some in /usr/share/X11/fonts. Add this directory to the
# fontconfig configuration without changing the gtk3 tooltool package.
cat << EOF > $root_dir/gtk3/usr/local/etc/fonts/local.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/usr/share/X11/fonts</dir>
</fontconfig>
EOF
cat <<EOF > $root_dir/gtk3/setup.sh
#!/bin/sh
cd \$(dirname \$0)
# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
LD_LIBRARY_PATH=./usr/local/lib \
PANGO_SYSCONFDIR=./usr/local/etc \
PANGO_LIBDIR=./usr/local/lib \
./usr/local/bin/pango-querymodules > ./usr/local/etc/pango/pango.modules
# same with gdb-pixbuf and loaders.cache
LD_LIBRARY_PATH=./usr/local/lib \
GDK_PIXBUF_MODULE_FILE=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
./usr/local/bin/gdk-pixbuf-query-loaders > ./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
# The fontconfig version in the tooltool package has known uses of
# uninitialized memory when creating its cache, and while most users
# will already have an existing cache, running Firefox on automation
# will create it. Combined with valgrind, this generates irrelevant
# errors.
# So create the fontconfig cache beforehand.
./usr/local/bin/fc-cache
EOF
chmod +x $root_dir/gtk3/setup.sh
cd $cwd
tar -C $root_dir -Jcf gtk3.tar.xz gtk3

View File

@ -1,48 +1,28 @@
# $topsrcdir/gtk3 comes from tooltool, when the tooltool manifest contains it.
if [ -d "$topsrcdir/gtk3" ]; then
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
# $TOOLTOOL_DIR/gtk3 comes from tooltool, when the tooltool manifest contains it.
if [ -d "$TOOLTOOL_DIR/gtk3" ]; then
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
echo PKG_CONFIG_LIBDIR must be set >&2
exit 1
fi
export PKG_CONFIG_SYSROOT_DIR="$topsrcdir/gtk3"
export PKG_CONFIG_PATH="$topsrcdir/gtk3/usr/local/lib/pkgconfig"
export PATH="$topsrcdir/gtk3/usr/local/bin:${PATH}"
export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
# Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
LDFLAGS="-L$topsrcdir/gtk3/usr/local/lib ${LDFLAGS}"
mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib"
LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
ac_add_options --enable-default-toolkit=cairo-gtk3
# Set things up to use Gtk+3 from the tooltool package
mk_add_options "export FONTCONFIG_PATH=$topsrcdir/gtk3/usr/local/etc/fonts"
mk_add_options "export PANGO_SYSCONFDIR=$topsrcdir/gtk3/usr/local/etc"
mk_add_options "export PANGO_LIBDIR=$topsrcdir/gtk3/usr/local/lib"
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$topsrcdir/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
mk_add_options "export GDK_PIXBUF_MODULEDIR=$topsrcdir/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib"
# pango expects absolute paths in pango.modules, and topsrcdir may vary...
LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib \
PANGO_SYSCONFDIR=$topsrcdir/gtk3/usr/local/etc \
PANGO_LIBDIR=$topsrcdir/gtk3/usr/local/lib \
$topsrcdir/gtk3/usr/local/bin/pango-querymodules > $topsrcdir/gtk3/usr/local/etc/pango/pango.modules
# same with gdb-pixbuf and loaders.cache
LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib \
GDK_PIXBUF_MODULE_FILE=$topsrcdir/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
GDK_PIXBUF_MODULEDIR=$topsrcdir/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
$topsrcdir/gtk3/usr/local/bin/gdk-pixbuf-query-loaders > $topsrcdir/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
# mock build environment doesn't have fonts in /usr/share/fonts, but
# has some in /usr/share/X11/fonts. Add this directory to the
# fontconfig configuration without changing the gtk3 tooltool package.
cat << EOF > $topsrcdir/gtk3/usr/local/etc/fonts/local.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/usr/share/X11/fonts</dir>
</fontconfig>
EOF
mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
# Until a tooltool with bug 1188571 landed is available everywhere
$TOOLTOOL_DIR/gtk3/setup.sh
else
ac_add_options --enable-default-toolkit=cairo-gtk2
fi

View File

@ -111,6 +111,13 @@ class MachCommands(MachCommandBase):
'--show-possibly-lost=no',
'--track-origins=yes',
'--trace-children=yes',
# The gstreamer plugin scanner can run as part of executing
# firefox, but is an external program. In some weird cases,
# valgrind finds errors while executing __libc_freeres when
# it runs, but those are not relevant, as it's related to
# executing third party code. So don't trace
# gst-plugin-scanner.
'--trace-children-skip=*/gst-plugin-scanner',
'-v', # Enable verbosity to get the list of used suppressions
]

View File

@ -25,7 +25,7 @@ else
_arch=32
fi
TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/linux${_arch}/valgrind.manifest
TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/linux${_arch}/releng.manifest
TOOLTOOL_SERVER=https://api.pub.build.mozilla.org/tooltool/
(cd $srcdir; python /builds/tooltool.py --url $TOOLTOOL_SERVER --overwrite -m $TOOLTOOL_MANIFEST fetch ${TOOLTOOL_CACHE:+ -c ${TOOLTOOL_CACHE}}) || exit 2

View File

@ -327,7 +327,8 @@ nsSHEntryShared::AttributeWillChange(nsIDocument* aDocument,
dom::Element* aContent,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aNewValue)
{
}
@ -336,7 +337,8 @@ nsSHEntryShared::AttributeChanged(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
RemoveFromBFCacheAsync();
}

View File

@ -2181,9 +2181,11 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
preparsedAttrValue);
}
// Hold a script blocker while calling ParseAttribute since that can call
@ -2191,6 +2193,11 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAutoScriptBlocker scriptBlocker;
nsAttrValue attrValue;
if (preparsedAttrValue) {
attrValue.SwapValueWith(*preparsedAttrValue);
}
// Even the value was pre-parsed in BeforeSetAttr, we still need to call
// ParseAttribute because it can have side effects.
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
attrValue.SetTo(aValue);
}
@ -2230,7 +2237,8 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
NS_ENSURE_SUCCESS(rv, rv);
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
&aParsedValue);
}
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
@ -2257,10 +2265,10 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
nsMutationGuard::DidMutate();
// Copy aParsedValue for later use since it will be lost when we call
// SetAndTakeMappedAttr below
nsAttrValue aValueForAfterSetAttr;
// SetAndSwapMappedAttr below
nsAttrValue valueForAfterSetAttr;
if (aCallAfterSetAttr) {
aValueForAfterSetAttr.SetTo(aParsedValue);
valueForAfterSetAttr.SetTo(aParsedValue);
}
bool hadValidDir = false;
@ -2276,7 +2284,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
// stuff to Element?
if (!IsAttributeMapped(aName) ||
!SetMappedAttribute(document, aName, aParsedValue, &rv)) {
rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue);
rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue);
}
}
else {
@ -2285,8 +2293,13 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
aNamespaceID,
nsIDOMNode::ATTRIBUTE_NODE);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue);
}
// If the old value owns its own data, we know it is OK to keep using it.
const nsAttrValue* oldValue =
aParsedValue.StoresOwnData() ? &aParsedValue : &aOldValue;
NS_ENSURE_SUCCESS(rv, rv);
if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
@ -2300,8 +2313,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
nsIDocument* ownerDoc = OwnerDoc();
if (ownerDoc && GetCustomElementData()) {
nsCOMPtr<nsIAtom> oldValueAtom = aOldValue.GetAsAtom();
nsCOMPtr<nsIAtom> newValueAtom = aValueForAfterSetAttr.GetAsAtom();
nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
LifecycleCallbackArgs args = {
nsDependentAtomString(aName),
aModType == nsIDOMMutationEvent::ADDITION ?
@ -2313,17 +2326,21 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
if (aCallAfterSetAttr) {
rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify);
rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
OnSetDirAttr(this, &aValueForAfterSetAttr,
OnSetDirAttr(this, &valueForAfterSetAttr,
hadValidDir, hadDirAuto, aNotify);
}
}
if (aNotify) {
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
// Don't pass aOldValue to AttributeChanged since it may not be reliable.
// Callers only compute aOldValue under certain conditions which may not
// be triggered by all nsIMutationObservers.
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType,
oldValue == &aParsedValue ? &aParsedValue : nullptr);
}
if (aFireMutation) {
@ -2341,8 +2358,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(newValue);
}
if (!aOldValue.IsEmptyString()) {
mutation.mPrevAttrValue = aOldValue.GetAsAtom();
if (!oldValue->IsEmptyString()) {
mutation.mPrevAttrValue = oldValue->GetAsAtom();
}
mutation.mAttrChange = aModType;
@ -2353,6 +2370,25 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
return NS_OK;
}
nsresult
Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::_class) {
// aValue->GetAttrValue will only be non-null here when this is called
// via Element::SetParsedAttr. This shouldn't happen for "class", but
// this will handle it.
if (aValue && !aValue->GetAttrValue()) {
nsAttrValue attr;
attr.ParseAtomArray(aValue->String());
aValue->TakeParsedValue(attr);
}
}
}
return NS_OK;
}
bool
Element::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
@ -2362,7 +2398,7 @@ Element::ParseAttribute(int32_t aNamespaceID,
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::_class) {
SetFlags(NODE_MAY_HAVE_CLASS);
aResult.ParseAtomArray(aValue);
// Result should have been preparsed above.
return true;
}
if (aAttribute == nsGkAtoms::id) {
@ -2469,7 +2505,8 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
nsIDOMMutationEvent::REMOVAL,
nullptr);
}
bool hasMutationListeners = aNotify &&
@ -2535,8 +2572,10 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
if (aNotify) {
// We can always pass oldValue here since there is no new value which could
// have corrupted it.
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
nsIDOMMutationEvent::REMOVAL, &oldValue);
}
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
@ -3494,4 +3533,4 @@ Element::GetReferrerPolicy()
}
}
return net::RP_Unset;
}
}

View File

@ -477,6 +477,8 @@ public:
virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, bool aNotify) override;
// aParsedValue receives the old value of the attribute. That's useful if
// either the input or output value of aParsedValue is StoresOwnData.
nsresult SetParsedAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
nsAttrValue& aParsedValue, bool aNotify);
// GetAttr is not inlined on purpose, to keep down codesize from all
@ -1087,10 +1089,15 @@ protected:
* @param aNamespaceID namespace of attribute
* @param aAttribute local-name of attribute
* @param aPrefix aPrefix of attribute
* @param aOldValue previous value of attribute. Only needed if
* aFireMutation is true or if the element is a
* custom element (in web components).
* @param aParsedValue parsed new value of attribute
* @param aOldValue The old value of the attribute to use as a fallback
* in the cases where the actual old value (i.e.
* its current value) is !StoresOwnData() --- in which
* case the current value is probably already useless.
* If the current value is StoresOwnData() (or absent),
* aOldValue will not be used.
* @param aParsedValue parsed new value of attribute. Replaced by the
* old value of the attribute. This old value is only
* useful if either it or the new value is StoresOwnData.
* @param aModType nsIDOMMutationEvent::MODIFICATION or ADDITION. Only
* needed if aFireMutation or aNotify is true.
* @param aFireMutation should mutation-events be fired?
@ -1163,17 +1170,16 @@ protected:
* @param aName the localname of the attribute being set
* @param aValue the value it's being set to represented as either a string or
* a parsed nsAttrValue. Alternatively, if the attr is being removed it
* will be null.
* will be null. BeforeSetAttr is allowed to modify aValue by parsing
* the string to an nsAttrValue (to avoid having to reparse it in
* ParseAttribute).
* @param aNotify Whether we plan to notify document observers.
*/
// Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable.
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
bool aNotify)
{
return NS_OK;
}
nsAttrValueOrString* aValue,
bool aNotify);
/**
* Hook that is called by Element::SetAttr to allow subclasses to

View File

@ -607,7 +607,8 @@ ShadowRoot::AttributeChanged(nsIDocument* aDocument,
Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
if (!IsPooledNode(aElement, aElement->GetParent(), mPoolHost)) {
return;

View File

@ -387,14 +387,12 @@ nsAttrAndChildArray::AttrAt(uint32_t aPos) const
}
nsresult
nsAttrAndChildArray::SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
{
uint32_t i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
ATTRS(mImpl)[i].mValue.Reset();
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
return NS_OK;
}
}
@ -414,12 +412,12 @@ nsAttrAndChildArray::SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
}
nsresult
nsAttrAndChildArray::SetAndTakeAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue)
nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue)
{
int32_t namespaceID = aName->NamespaceID();
nsIAtom* localName = aName->NameAtom();
if (namespaceID == kNameSpaceID_None) {
return SetAndTakeAttr(localName, aValue);
return SetAndSwapAttr(localName, aValue);
}
uint32_t i, slotCount = AttrSlotCount();

View File

@ -88,8 +88,9 @@ public:
const nsAttrValue* GetAttr(const nsAString& aName,
nsCaseTreatment aCaseSensitive) const;
const nsAttrValue* AttrAt(uint32_t aPos) const;
nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
nsresult SetAndTakeAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue);
// SetAndSwapAttr swaps the current attribute value with aValue.
nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue);
// Remove the attr at position aPos. The value of the attr is placed in
// aValue; any value that was already in aValue is destroyed.

View File

@ -127,6 +127,12 @@ public:
static void Shutdown();
ValueType Type() const;
// Returns true when this value is self-contained and does not depend on
// the state of its associated element.
// Returns false when this value depends on the state of its associated
// element and may be invalid if that state has been changed by changes to
// that element state outside of attribute setting.
inline bool StoresOwnData() const;
void Reset();

View File

@ -191,6 +191,16 @@ nsAttrValue::IsSVGType(ValueType aType) const
return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd;
}
inline bool
nsAttrValue::StoresOwnData() const
{
if (BaseType() != eOtherBase) {
return true;
}
ValueType t = Type();
return t != eCSSStyleRule && !IsSVGType(t);
}
inline void
nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
{

View File

@ -49,6 +49,21 @@ public:
, mCheapString(nullptr)
{ }
void TakeParsedValue(nsAttrValue& aValue)
{
mStoredAttrValue.SwapValueWith(aValue);
mAttrValue = &mStoredAttrValue;
mStringPtr = nullptr;
}
/**
* If TakeParsedValue has been called, returns the value that it set.
*/
nsAttrValue* GetStoredAttrValue()
{
return mAttrValue == &mStoredAttrValue ? &mStoredAttrValue : nullptr;
}
const nsAttrValue* GetAttrValue() { return mAttrValue; }
/**
* Returns a reference to the string value of the contents of this object.
*
@ -74,6 +89,7 @@ protected:
const nsAttrValue* mAttrValue;
mutable const nsAString* mStringPtr;
mutable nsCheapString mCheapString;
nsAttrValue mStoredAttrValue;
};
#endif // nsAttrValueOrString_h___

View File

@ -659,7 +659,8 @@ nsContentList::Item(uint32_t aIndex)
void
nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
int32_t aNameSpaceID, nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
NS_PRECONDITION(aElement, "Must have a content node to work with");

View File

@ -555,21 +555,15 @@ nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc,
return mAttributeCache.EnumerateRead(aFunc, aUserArg);
}
size_t
AttrCacheSizeEnumerator(const nsAttrKey& aKey,
const nsRefPtr<Attr>& aValue,
MallocSizeOf aMallocSizeOf,
void* aUserArg)
{
return aMallocSizeOf(aValue.get());
}
size_t
nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator,
aMallocSizeOf);
n += mAttributeCache.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (auto iter = mAttributeCache.ConstIter(); !iter.Done(); iter.Next()) {
n += aMallocSizeOf(iter.Data().get());
}
// NB: mContent is non-owning and thus not counted.
return n;

View File

@ -117,7 +117,8 @@ nsMutationReceiver::AttributeWillChange(nsIDocument* aDocument,
mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aNewValue)
{
if (nsAutoMutationBatch::IsBatching() ||
!ObservesAttr(RegisterTarget(), aElement, aNameSpaceID, aAttribute)) {

View File

@ -374,7 +374,7 @@ public:
{
// We can reuse AttributeWillChange implementation.
AttributeWillChange(aDocument, aElement, aNameSpaceID, aAttribute,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::MODIFICATION, nullptr);
}
protected:

View File

@ -12635,7 +12635,7 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
0;
aWindowSizes->mDOMOtherSize +=
mStyledLinks.SizeOfExcludingThis(nullptr, aWindowSizes->mMallocSizeOf);
mStyledLinks.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
aWindowSizes->mDOMOtherSize +=
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);

View File

@ -156,6 +156,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
, mVisible(true)
{
ResetPermissionManagerStatus();
mRemoteFrame = ShouldUseRemoteProcess();
}
nsFrameLoader::~nsFrameLoader()
@ -301,20 +302,12 @@ nsFrameLoader::ReallyStartLoadingInternal()
PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading",
js::ProfileEntry::Category::OTHER);
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
if (mRemoteFrame) {
if (IsRemoteFrame()) {
if (!mRemoteBrowser && !TryRemoteBrowser()) {
NS_WARNING("Couldn't create child process for iframe.");
return NS_ERROR_FAILURE;
}
// Execute pending frame scripts before loading URL
EnsureMessageManager();
// FIXME get error codes from child
mRemoteBrowser->LoadURL(mURIToLoad);
@ -325,6 +318,10 @@ nsFrameLoader::ReallyStartLoadingInternal()
return NS_OK;
}
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(mDocShell,
"MaybeCreateDocShell succeeded with a null mDocShell");
@ -444,11 +441,7 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI)
}
// Bail out if this is an infinite recursion scenario
rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
if (mRemoteFrame) {
if (IsRemoteFrame()) {
return NS_OK;
}
return CheckForRecursiveLoad(aURI);
@ -460,14 +453,16 @@ nsFrameLoader::GetDocShell(nsIDocShell **aDocShell)
*aDocShell = nullptr;
nsresult rv = NS_OK;
if (IsRemoteFrame()) {
return rv;
}
// If we have an owner, make sure we have a docshell and return
// that. If not, we're most likely in the middle of being torn down,
// then we just return null.
if (mOwnerContent) {
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv))
return rv;
if (mRemoteFrame) {
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(mDocShell,
@ -625,42 +620,42 @@ nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
AutoResetInShow resetInShow(this);
mInShow = true;
ScreenIntSize size = frame->GetSubdocumentSize();
if (IsRemoteFrame()) {
return ShowRemoteFrame(size, frame);
}
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return false;
}
if (!mRemoteFrame) {
if (!mDocShell)
return false;
mDocShell->SetMarginWidth(marginWidth);
mDocShell->SetMarginHeight(marginHeight);
nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
if (sc) {
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
scrollbarPrefX);
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
scrollbarPrefY);
}
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
if (presShell) {
// Ensure root scroll frame is reflowed in case scroll preferences or
// margins have changed
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
if (rootScrollFrame) {
presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
NS_FRAME_IS_DIRTY);
}
return true;
}
NS_ASSERTION(mDocShell,
"MaybeCreateDocShell succeeded, but null mDocShell");
if (!mDocShell) {
return false;
}
ScreenIntSize size = frame->GetSubdocumentSize();
if (mRemoteFrame) {
return ShowRemoteFrame(size, frame);
mDocShell->SetMarginWidth(marginWidth);
mDocShell->SetMarginHeight(marginHeight);
nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
if (sc) {
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
scrollbarPrefX);
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
scrollbarPrefY);
}
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
if (presShell) {
// Ensure root scroll frame is reflowed in case scroll preferences or
// margins have changed
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
if (rootScrollFrame) {
presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
NS_FRAME_IS_DIRTY);
}
return true;
}
nsView* view = frame->EnsureInnerView();
@ -682,7 +677,7 @@ nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
// sub-document. This shouldn't be necessary, but given the way our
// editor works, it is. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
presShell = mDocShell->GetPresShell();
if (presShell) {
nsCOMPtr<nsIDOMHTMLDocument> doc =
do_QueryInterface(presShell->GetDocument());
@ -729,7 +724,7 @@ nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
uint32_t aMarginHeight)
{
// We assume that the margins are always zero for remote frames.
if (mRemoteFrame)
if (IsRemoteFrame())
return;
// If there's no docshell, we're probably not up and running yet.
@ -754,7 +749,7 @@ bool
nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
nsSubDocumentFrame *aFrame)
{
NS_ASSERTION(mRemoteFrame, "ShowRemote only makes sense on remote frames.");
NS_ASSERTION(IsRemoteFrame(), "ShowRemote only makes sense on remote frames.");
if (!mRemoteBrowser && !TryRemoteBrowser()) {
NS_ERROR("Couldn't create child process.");
@ -790,9 +785,6 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
mRemoteBrowser->Show(size, parentIsActive);
mRemoteBrowserShown = true;
EnsureMessageManager();
InitializeBrowserAPI();
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
@ -967,11 +959,11 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
"Swapping some sort of random loaders?");
NS_ENSURE_STATE(!mInShow && !aOther->mInShow);
if (mRemoteFrame && aOther->mRemoteFrame) {
if (IsRemoteFrame() && aOther->IsRemoteFrame()) {
return SwapWithOtherRemoteLoader(aOther, aFirstToSwap, aSecondToSwap);
}
if (mRemoteFrame || aOther->mRemoteFrame) {
if (IsRemoteFrame() || aOther->IsRemoteFrame()) {
NS_WARNING("Swapping remote and non-remote frames is not currently supported");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1641,22 +1633,27 @@ nsFrameLoader::ShouldUseRemoteProcess()
eCaseMatters);
}
bool
nsFrameLoader::IsRemoteFrame()
{
if (mRemoteFrame) {
MOZ_ASSERT(!mDocShell, "Found a remote frame with a DocShell");
return true;
}
return false;
}
nsresult
nsFrameLoader::MaybeCreateDocShell()
{
if (mDocShell) {
return NS_OK;
}
if (mRemoteFrame) {
if (IsRemoteFrame()) {
return NS_OK;
}
NS_ENSURE_STATE(!mDestroyCalled);
if (ShouldUseRemoteProcess()) {
mRemoteFrame = true;
return NS_OK;
}
// Get our parent docshell off the document of mOwnerContent
// XXXbz this is such a total hack.... We really need to have a
// better setup for doing this.
@ -1789,8 +1786,6 @@ nsFrameLoader::MaybeCreateDocShell()
webNav->SetSessionHistory(sessionHistory);
}
EnsureMessageManager();
if (OwnerIsAppFrame()) {
// You can't be both an app and a browser frame.
MOZ_ASSERT(!OwnerIsBrowserFrame());
@ -1818,18 +1813,7 @@ nsFrameLoader::MaybeCreateDocShell()
mDocShell->SetIsBrowserInsideApp(containingAppId);
}
InitializeBrowserAPI();
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"inprocess-browser-shown", nullptr);
}
if (OwnerIsBrowserOrAppFrame() && mMessageManager) {
mMessageManager->LoadFrameScript(
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"),
/* allowDelayedLoad = */ true,
/* aRunInGlobalScope */ true);
if (OwnerIsBrowserOrAppFrame()) {
// For inproc frames, set the docshell properties.
nsCOMPtr<nsIDocShellTreeItem> item = do_GetInterface(docShell);
nsAutoString name;
@ -1856,6 +1840,15 @@ nsFrameLoader::MaybeCreateDocShell()
}
}
ReallyLoadFrameScripts();
InitializeBrowserAPI();
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"inprocess-browser-shown", nullptr);
}
return NS_OK;
}
@ -1876,13 +1869,16 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
{
nsresult rv;
MOZ_ASSERT(!IsRemoteFrame(),
"Shouldn't call CheckForRecursiveLoad on remote frames.");
mDepthTooGreat = false;
rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(!mRemoteFrame,
"Shouldn't call CheckForRecursiveLoad on remote frames.");
NS_ASSERTION(mDocShell,
"MaybeCreateDocShell succeeded, but null mDocShell");
if (!mDocShell) {
return NS_ERROR_FAILURE;
}
@ -2004,7 +2000,7 @@ nsFrameLoader::GetWindowDimensions(nsIntRect& aRect)
NS_IMETHODIMP
nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
{
if (mRemoteFrame) {
if (IsRemoteFrame()) {
if (mRemoteBrowser) {
ScreenIntSize size = aIFrame->GetSubdocumentSize();
nsIntRect dimensions;
@ -2232,7 +2228,10 @@ nsFrameLoader::TryRemoteBrowser()
unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
}
return true;
ReallyLoadFrameScripts();
InitializeBrowserAPI();
return true;
}
mozilla::dom::PBrowserParent*
@ -2469,14 +2468,13 @@ nsFrameLoader::EnsureMessageManager()
{
NS_ENSURE_STATE(mOwnerContent);
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
if (mMessageManager) {
return NS_OK;
}
if (!mIsTopLevelContent &&
!OwnerIsBrowserOrAppFrame() &&
!mRemoteFrame &&
!IsRemoteFrame() &&
!(mOwnerContent->IsXULElement() &&
mOwnerContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::forcemessagemanager,
@ -2484,14 +2482,6 @@ nsFrameLoader::EnsureMessageManager()
return NS_OK;
}
bool useRemoteProcess = ShouldUseRemoteProcess();
if (mMessageManager) {
if (useRemoteProcess && mRemoteBrowser) {
mMessageManager->InitWithCallback(this);
}
return NS_OK;
}
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
do_QueryInterface(GetOwnerDoc()->GetWindow());
nsCOMPtr<nsIMessageBroadcaster> parentManager;
@ -2510,18 +2500,33 @@ nsFrameLoader::EnsureMessageManager()
}
}
if (useRemoteProcess) {
mMessageManager = new nsFrameMessageManager(mRemoteBrowser ? this : nullptr,
static_cast<nsFrameMessageManager*>(parentManager.get()),
MM_CHROME);
} else {
mMessageManager = new nsFrameMessageManager(nullptr,
static_cast<nsFrameMessageManager*>(parentManager.get()),
MM_CHROME);
mMessageManager = new nsFrameMessageManager(nullptr,
static_cast<nsFrameMessageManager*>(parentManager.get()),
MM_CHROME);
if (!IsRemoteFrame()) {
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(mDocShell,
"MaybeCreateDocShell succeeded, but null mDocShell");
if (!mDocShell) {
return NS_ERROR_FAILURE;
}
mChildMessageManager =
new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
// Force pending frame scripts to be loaded.
}
return NS_OK;
}
nsresult
nsFrameLoader::ReallyLoadFrameScripts()
{
nsresult rv = EnsureMessageManager();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mMessageManager) {
mMessageManager->InitWithCallback(this);
}
return NS_OK;
@ -2555,6 +2560,8 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
mRemoteFrame = true;
mRemoteBrowser = TabParent::GetFrom(aTabParent);
mChildID = mRemoteBrowser ? mRemoteBrowser->Manager()->ChildID() : 0;
ReallyLoadFrameScripts();
InitializeBrowserAPI();
ShowRemoteFrame(ScreenIntSize(0, 0));
}
@ -2590,7 +2597,8 @@ nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
MOZ_ASSERT(mObservingOwnerContent);
// TODO: Implement ContentShellAdded for remote browsers (bug 658304)
@ -2820,8 +2828,22 @@ nsFrameLoader::GetLoadContext(nsILoadContext** aLoadContext)
void
nsFrameLoader::InitializeBrowserAPI()
{
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
if (browserFrame) {
browserFrame->InitializeBrowserAPI();
if (OwnerIsBrowserOrAppFrame()) {
if (!IsRemoteFrame()) {
nsresult rv = EnsureMessageManager();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (mMessageManager) {
mMessageManager->LoadFrameScript(
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"),
/* allowDelayedLoad = */ true,
/* aRunInGlobalScope */ true);
}
}
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
if (browserFrame) {
browserFrame->InitializeBrowserAPI();
}
}
}

View File

@ -222,6 +222,11 @@ private:
bool ShouldUseRemoteProcess();
/**
* Return true if the frame is a remote frame. Return false otherwise
*/
bool IsRemoteFrame();
/**
* Is this a frameloader for a bona fide <iframe mozbrowser> or
* <iframe mozapp>? (I.e., does the frame return true for
@ -270,6 +275,7 @@ private:
*/
nsresult MaybeCreateDocShell();
nsresult EnsureMessageManager();
nsresult ReallyLoadFrameScripts();
// Updates the subdocument position and size. This gets called only
// when we have our own in-process DocShell.

View File

@ -1432,6 +1432,14 @@ nsFrameMessageManager::GetInitialProcessData(JSContext* aCx, JS::MutableHandleVa
init.setObject(*obj);
}
if (!mChrome && XRE_IsParentProcess()) {
// This is the cpmm in the parent process. We should use the same object as the ppmm.
nsCOMPtr<nsIGlobalProcessScriptLoader> ppmm =
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
ppmm->GetInitialProcessData(aCx, &init);
mInitialProcessData = init;
}
if (!JS_WrapValue(aCx, &init)) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2164,7 +2172,6 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED);
global.forget(aResult);
return NS_OK;
}
static PLDHashOperator

View File

@ -13598,12 +13598,8 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
}
// The things pointed to by the entries will be measured below, so we
// use nullptr for the callback here.
aWindowSizes->mDOMEventTargetsSize +=
mEventTargetObjects.SizeOfExcludingThis(nullptr,
aWindowSizes->mMallocSizeOf);
mEventTargetObjects.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
DOMEventTargetHelper* et = iter.Get()->GetKey();

View File

@ -9,6 +9,7 @@
#include "nsISupports.h"
class nsAttrValue;
class nsIAtom;
class nsIContent;
class nsIDocument;
@ -21,8 +22,8 @@ class Element;
} // namespace mozilla
#define NS_IMUTATION_OBSERVER_IID \
{ 0x16fe5e3e, 0xeadc, 0x4312, \
{ 0x9d, 0x44, 0xb6, 0xbe, 0xdd, 0x6b, 0x54, 0x74 } }
{ 0xdd74f0cc, 0x2849, 0x4d05, \
{ 0x9c, 0xe3, 0xb0, 0x95, 0x3e, 0xc2, 0xfd, 0x44 } }
/**
* Information details about a characterdata change. Basically, we
@ -157,6 +158,8 @@ public:
* @param aModType Whether or not the attribute will be added, changed, or
* removed. The constants are defined in
* nsIDOMMutationEvent.h.
* @param aNewValue The new value, IF it has been preparsed by
* BeforeSetAttr, otherwise null.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
@ -168,7 +171,8 @@ public:
mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) = 0;
int32_t aModType,
const nsAttrValue* aNewValue) = 0;
/**
* Notification that an attribute of an element has changed.
@ -180,6 +184,8 @@ public:
* @param aModType Whether or not the attribute was added, changed, or
* removed. The constants are defined in
* nsIDOMMutationEvent.h.
* @param aOldValue The old value, if either the old value or the new
* value are StoresOwnData() (or absent); null otherwise.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
@ -191,7 +197,8 @@ public:
mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) = 0;
int32_t aModType,
const nsAttrValue* aOldValue) = 0;
/**
* Notification that an attribute of an element has been
@ -336,14 +343,16 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID)
mozilla::dom::Element* aElement, \
int32_t aNameSpaceID, \
nsIAtom* aAttribute, \
int32_t aModType) override;
int32_t aModType, \
const nsAttrValue* aNewValue) override;
#define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED \
virtual void AttributeChanged(nsIDocument* aDocument, \
mozilla::dom::Element* aElement, \
int32_t aNameSpaceID, \
nsIAtom* aAttribute, \
int32_t aModType) override;
int32_t aModType, \
const nsAttrValue* aOldValue) override;
#define NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED \
virtual void ContentAppended(nsIDocument* aDocument, \
@ -405,7 +414,8 @@ _class::AttributeWillChange(nsIDocument* aDocument, \
mozilla::dom::Element* aElement, \
int32_t aNameSpaceID, \
nsIAtom* aAttribute, \
int32_t aModType) \
int32_t aModType, \
const nsAttrValue* aNewValue) \
{ \
} \
void \
@ -413,7 +423,8 @@ _class::AttributeChanged(nsIDocument* aDocument, \
mozilla::dom::Element* aElement, \
int32_t aNameSpaceID, \
nsIAtom* aAttribute, \
int32_t aModType) \
int32_t aModType, \
const nsAttrValue* aOldValue) \
{ \
} \
void \

View File

@ -123,24 +123,26 @@ void
nsNodeUtils::AttributeWillChange(Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aNewValue)
{
nsIDocument* doc = aElement->OwnerDoc();
IMPL_MUTATION_NOTIFICATION(AttributeWillChange, aElement,
(doc, aElement, aNameSpaceID, aAttribute,
aModType));
aModType, aNewValue));
}
void
nsNodeUtils::AttributeChanged(Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
nsIDocument* doc = aElement->OwnerDoc();
IMPL_MUTATION_NOTIFICATION(AttributeChanged, aElement,
(doc, aElement, aNameSpaceID, aAttribute,
aModType));
aModType, aOldValue));
}
void

View File

@ -48,12 +48,15 @@ public:
* @param aNameSpaceID Namespace of changing attribute
* @param aAttribute Local-name of changing attribute
* @param aModType Type of change (add/change/removal)
* @param aNewValue The parsed new value, but only if BeforeSetAttr
* preparsed it!!!
* @see nsIMutationObserver::AttributeWillChange
*/
static void AttributeWillChange(mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType);
int32_t aModType,
const nsAttrValue* aNewValue);
/**
* Send AttributeChanged notifications to nsIMutationObservers.
@ -61,12 +64,16 @@ public:
* @param aNameSpaceID Namespace of changed attribute
* @param aAttribute Local-name of changed attribute
* @param aModType Type of change (add/change/removal)
* @param aOldValue If the old value was StoresOwnData() (or absent),
* that value, otherwise null
* @see nsIMutationObserver::AttributeChanged
*/
static void AttributeChanged(mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType);
int32_t aModType,
const nsAttrValue* aOldValue);
/**
* Send AttributeSetToCurrentValue notifications to nsIMutationObservers.
* @param aElement Element whose data changed

View File

@ -83,7 +83,8 @@ nsScriptElement::AttributeChanged(nsIDocument* aDocument,
Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
MaybeProcessScript();
}

View File

@ -138,7 +138,7 @@ nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(bool aForceInData
ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
// Don't bother going through SetInlineStyleRule, we don't want to fire off
// mutation events or document notifications anyway
nsresult rv = mAttrsAndChildren.SetAndTakeAttr(nsGkAtoms::style, attrValue);
nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -268,7 +268,8 @@ nsAttributeTextNode::AttributeChanged(nsIDocument* aDocument,
Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
aElement == mGrandparent) {

View File

@ -85,7 +85,7 @@ function CameraTestSuite() {
var self = this;
this._window.addEventListener('beforeunload', function() {
if (isDefinedObj(self.viewfinder)) {
self.viewfinder.mozSrcObject = null;
self.viewfinder.srcObject = null;
}
self.hw = null;
@ -211,7 +211,7 @@ CameraTestSuite.prototype = {
function postTest(pass) {
ok(pass, test.name + ' finished');
var camera = self.camera;
self.viewfinder.mozSrcObject = null;
self.viewfinder.srcObject = null;
self.camera = null;
if (!isDefinedObj(camera)) {
@ -325,7 +325,7 @@ CameraTestSuite.prototype = {
return;
}
self.viewfinder.mozSrcObject = self.camera;
self.viewfinder.srcObject = self.camera;
self.viewfinder.play();
self.camera.addEventListener('previewstatechange', onPreviewStateChange);
});

View File

@ -42,7 +42,7 @@ var Camera = {
var camera = d.camera;
var cfg = d.configuration;
Camera.cameraObj = camera;
Camera.viewfinder.mozSrcObject = camera;
Camera.viewfinder.srcObject = camera;
Camera.viewfinder.play();
// Check the default configuration
@ -66,7 +66,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
if (Camera.cameraObj) {
Camera.cameraObj.release();
Camera.cameraObj = null;

View File

@ -232,7 +232,7 @@ var Camera = {
Camera.cameraObj.addEventListener('configurationchanged', Camera.onConfigChange);
Camera.cameraObj.addEventListener('shutter', Camera.shutter);
Camera.cameraObj.addEventListener('picture', Camera.takePictureEvent.bind(Camera));
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
SimpleTest.expectAssertions(0);
ok(true, "Camera Control object has been successfully initialized");
@ -245,7 +245,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});

View File

@ -179,7 +179,7 @@ var Camera = {
Camera.cameraObj = d.camera;
Camera.cameraObj.addEventListener('previewstatechange', Camera.onPreviewStateChange);
Camera.cameraObj.addEventListener('shutter', Camera.shutter);
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
SimpleTest.expectAssertions(0);
};
@ -190,7 +190,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});

View File

@ -54,7 +54,7 @@ var Camera = {
function onSuccess(d) {
Camera.cameraObj = d.camera;
Camera.cameraObj.addEventListener('previewstatechange', Camera.onPreviewStateChange);
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
};
navigator.mozCameras.getCamera(whichCamera, options).then(onSuccess, onError);
@ -64,7 +64,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});

View File

@ -357,15 +357,10 @@ public:
private:
WebGL2Context();
JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) override;
virtual bool IsTexParamValid(GLenum pname) const override;
void UpdateBoundQuery(GLenum target, WebGLQuery* query);
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info);
// CreateVertexArrayImpl is assumed to be infallible.
virtual WebGLVertexArray* CreateVertexArrayImpl() override;
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;

View File

@ -10,485 +10,126 @@
namespace mozilla {
bool
WebGL2Context::ValidateSizedInternalFormat(GLenum internalformat, const char* info)
{
switch (internalformat) {
// Sized Internal Formats
// https://www.khronos.org/opengles/sdk/docs/man3/html/glTexStorage2D.xhtml
case LOCAL_GL_R8:
case LOCAL_GL_R8_SNORM:
case LOCAL_GL_R16F:
case LOCAL_GL_R32F:
case LOCAL_GL_R8UI:
case LOCAL_GL_R8I:
case LOCAL_GL_R16UI:
case LOCAL_GL_R16I:
case LOCAL_GL_R32UI:
case LOCAL_GL_R32I:
case LOCAL_GL_RG8:
case LOCAL_GL_RG8_SNORM:
case LOCAL_GL_RG16F:
case LOCAL_GL_RG32F:
case LOCAL_GL_RG8UI:
case LOCAL_GL_RG8I:
case LOCAL_GL_RG16UI:
case LOCAL_GL_RG16I:
case LOCAL_GL_RG32UI:
case LOCAL_GL_RG32I:
case LOCAL_GL_RGB8:
case LOCAL_GL_SRGB8:
case LOCAL_GL_RGB565:
case LOCAL_GL_RGB8_SNORM:
case LOCAL_GL_R11F_G11F_B10F:
case LOCAL_GL_RGB9_E5:
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGB8UI:
case LOCAL_GL_RGB8I:
case LOCAL_GL_RGB16UI:
case LOCAL_GL_RGB16I:
case LOCAL_GL_RGB32UI:
case LOCAL_GL_RGB32I:
case LOCAL_GL_RGBA8:
case LOCAL_GL_SRGB8_ALPHA8:
case LOCAL_GL_RGBA8_SNORM:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB10_A2:
case LOCAL_GL_RGBA16F:
case LOCAL_GL_RGBA32F:
case LOCAL_GL_RGBA8UI:
case LOCAL_GL_RGBA8I:
case LOCAL_GL_RGB10_A2UI:
case LOCAL_GL_RGBA16UI:
case LOCAL_GL_RGBA16I:
case LOCAL_GL_RGBA32I:
case LOCAL_GL_RGBA32UI:
case LOCAL_GL_DEPTH_COMPONENT16:
case LOCAL_GL_DEPTH_COMPONENT24:
case LOCAL_GL_DEPTH_COMPONENT32F:
case LOCAL_GL_DEPTH24_STENCIL8:
case LOCAL_GL_DEPTH32F_STENCIL8:
return true;
}
if (IsCompressedTextureFormat(internalformat))
return true;
nsCString name;
EnumName(internalformat, &name);
ErrorInvalidEnum("%s: invalid internal format %s", info, name.get());
return false;
}
/** Validates parameters to texStorage{2D,3D} */
bool
WebGL2Context::ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info)
{
// GL_INVALID_OPERATION is generated if the default texture object is curently bound to target.
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
if (!tex) {
ErrorInvalidOperation("%s: no texture is bound to target %s", info, EnumName(target));
return false;
}
// GL_INVALID_OPERATION is generated if the texture object currently bound to target already has
// GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.
if (tex->IsImmutable()) {
ErrorInvalidOperation("%s: texture bound to target %s is already immutable", info, EnumName(target));
return false;
}
// GL_INVALID_ENUM is generated if internalformat is not a valid sized internal format.
if (!ValidateSizedInternalFormat(internalformat, info))
return false;
// GL_INVALID_VALUE is generated if width, height or levels are less than 1.
if (width < 1) { ErrorInvalidValue("%s: width is < 1", info); return false; }
if (height < 1) { ErrorInvalidValue("%s: height is < 1", info); return false; }
if (depth < 1) { ErrorInvalidValue("%s: depth is < 1", info); return false; }
if (levels < 1) { ErrorInvalidValue("%s: levels is < 1", info); return false; }
// GL_INVALID_OPERATION is generated if levels is greater than floor(log2(max(width, height, depth)))+1.
if (FloorLog2(std::max(std::max(width, height), depth)) + 1 < levels) {
ErrorInvalidOperation("%s: too many levels for given texture dimensions", info);
return false;
}
return true;
}
// -------------------------------------------------------------------------
// Texture objects
void
WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
{
if (IsContextLost())
const char funcName[] = "TexStorage2D";
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_2D && target != LOCAL_GL_TEXTURE_CUBE_MAP)
return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP");
if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage2D(target, levels, internalformat, width, height);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage2D generated error %s", ErrorName(error));
}
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
tex->SetImmutable();
const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
GLsizei w = width;
GLsizei h = height;
for (size_t l = 0; l < size_t(levels); l++) {
for (size_t f = 0; f < facesCount; f++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, f),
l, w, h, 1,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
}
w = std::max(1, w / 2);
h = std::max(1, h / 2);
}
tex->TexStorage2D(texTarget, levels, internalFormat, width, height);
}
void
WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth)
{
if (IsContextLost())
const char funcName[] = "texStorage3D";
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_3D)
return ErrorInvalidEnum("texStorage3D: target is not TEXTURE_3D");
if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage3D generated error %s", ErrorName(error));
}
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
tex->SetImmutable();
GLsizei w = width;
GLsizei h = height;
GLsizei d = depth;
for (size_t l = 0; l < size_t(levels); l++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, 0),
l, w, h, d,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
w = std::max(1, w >> 1);
h = std::max(1, h >> 1);
d = std::max(1, d >> 1);
}
tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
}
void
WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView> &pixels,
ErrorResult& rv)
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
if (IsContextLost())
return;
void* data;
size_t dataLength;
js::Scalar::Type jsArrayType;
if (pixels.IsNull()) {
data = nullptr;
dataLength = 0;
jsArrayType = js::Scalar::MaxTypedArrayViewType;
} else {
const dom::ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
data = view.Data();
dataLength = view.Length();
jsArrayType = view.Type();
}
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
if (!ValidateTexImageTarget(target, func, dims))
return;
TexImageTarget texImageTarget = target;
if (!ValidateTexImage(texImageTarget, level, internalformat,
0, 0, 0,
width, height, depth,
border, format, type, func, dims))
const char funcName[] = "texImage3D";
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
TexInternalFormat effectiveInternalFormat =
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
if (effectiveInternalFormat == LOCAL_GL_NONE) {
return ErrorInvalidOperation("texImage3D: bad combination of internalformat and type");
}
// we need to find the exact sized format of the source data. Slightly abusing
// EffectiveInternalFormatFromInternalFormatAndType for that purpose. Really, an unsized source format
// is the same thing as an unsized internalformat.
TexInternalFormat effectiveSourceFormat =
EffectiveInternalFormatFromInternalFormatAndType(format, type);
MOZ_ASSERT(effectiveSourceFormat != LOCAL_GL_NONE); // should have validated format/type combo earlier
const size_t srcbitsPerTexel = GetBitsPerTexel(effectiveSourceFormat);
MOZ_ASSERT((srcbitsPerTexel % 8) == 0); // should not have compressed formats here.
size_t srcTexelSize = srcbitsPerTexel / 8;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength && dataLength < bytesNeeded)
return ErrorInvalidOperation("texImage3D: not enough data for operation (need %d, have %d)",
bytesNeeded, dataLength);
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex)
return ErrorInvalidOperation("texImage3D: no texture is bound to this target");
if (tex->IsImmutable()) {
return ErrorInvalidOperation(
"texImage3D: disallowed because the texture "
"bound to this target has already been made immutable by texStorage3D");
}
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
effectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
&driverType);
MakeContextCurrent();
GetAndFlushUnderlyingGLErrors();
gl->fTexImage3D(texImageTarget.get(), level,
driverInternalFormat,
width, height, depth,
0, driverFormat, driverType,
data);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texImage3D generated error %s", ErrorName(error));
}
tex->SetImageInfo(texImageTarget, level,
width, height, depth,
effectiveInternalFormat,
data ? WebGLImageDataStatus::InitializedImageData
: WebGLImageDataStatus::UninitializedImageData);
tex->TexImage3D(texImageTarget, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& rv)
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
if (IsContextLost())
return;
if (pixels.IsNull())
return ErrorInvalidValue("texSubImage3D: pixels must not be null!");
const dom::ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
if (!ValidateTexImageTarget(rawTarget, func, dims))
return;
TexImageTarget texImageTarget(rawTarget);
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex) {
return ErrorInvalidOperation("texSubImage3D: no texture bound on active texture unit");
}
if (!tex->HasImageInfoAt(texImageTarget, level)) {
return ErrorInvalidOperation("texSubImage3D: no previously defined texture image");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
TexInternalFormat existingUnsizedInternalFormat = LOCAL_GL_NONE;
TexType existingType = LOCAL_GL_NONE;
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(existingEffectiveInternalFormat,
&existingUnsizedInternalFormat,
&existingType);
if (!ValidateTexImage(texImageTarget, level, existingEffectiveInternalFormat.get(),
xoffset, yoffset, zoffset,
width, height, depth,
0, format, type, func, dims))
const char funcName[] = "texSubImage3D";
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
if (type != existingType) {
return ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
}
js::Scalar::Type jsArrayType = view.Type();
void* data = view.Data();
size_t dataLength = view.Length();
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
const size_t bitsPerTexel = GetBitsPerTexel(existingEffectiveInternalFormat);
MOZ_ASSERT((bitsPerTexel % 8) == 0); // should not have compressed formats here.
size_t srcTexelSize = bitsPerTexel / 8;
if (width == 0 || height == 0 || depth == 0)
return; // no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
if (imageInfo.HasUninitializedImageData()) {
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
zoffset == 0 &&
width == imageInfo.Width() &&
height == imageInfo.Height() &&
depth == imageInfo.Depth();
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
if (!tex->EnsureInitializedImageData(texImageTarget, level))
return;
}
}
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
existingEffectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
&driverType);
MakeContextCurrent();
gl->fTexSubImage3D(texImageTarget.get(), level,
xoffset, yoffset, zoffset,
width, height, depth,
driverFormat, driverType, data);
tex->TexSubImage3D(texImageTarget, level, xOffset, yOffset, zOffset, width, height,
depth, unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, dom::ImageData* data,
ErrorResult& rv)
GLint xOffset, GLint yOffset, GLint zOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv)
{
GenerateWarning("texSubImage3D: Not implemented.");
}
void
WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint xOffset, GLint yOffset, GLint zOffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
GenerateWarning("copyTexSubImage3D: Not implemented.");
}
void
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const dom::ArrayBufferView& data)
GLint border, GLsizei imageSize, const dom::ArrayBufferView& view)
{
GenerateWarning("compressedTexImage3D: Not implemented.");
}
void
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data)
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferView& view)
{
GenerateWarning("compressedTexSubImage3D: Not implemented.");
}
JS::Value
WebGL2Context::GetTexParameterInternal(const TexTarget& target, GLenum pname)
bool
WebGL2Context::IsTexParamValid(GLenum pname) const
{
switch (pname) {
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
case LOCAL_GL_TEXTURE_COMPARE_MODE:
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
case LOCAL_GL_TEXTURE_SWIZZLE_A:
case LOCAL_GL_TEXTURE_SWIZZLE_B:
case LOCAL_GL_TEXTURE_SWIZZLE_G:
case LOCAL_GL_TEXTURE_SWIZZLE_R:
case LOCAL_GL_TEXTURE_WRAP_R:
{
GLint i = 0;
gl->fGetTexParameteriv(target.get(), pname, &i);
return JS::NumberValue(uint32_t(i));
}
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
case LOCAL_GL_TEXTURE_COMPARE_MODE:
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
case LOCAL_GL_TEXTURE_SWIZZLE_A:
case LOCAL_GL_TEXTURE_SWIZZLE_B:
case LOCAL_GL_TEXTURE_SWIZZLE_G:
case LOCAL_GL_TEXTURE_SWIZZLE_R:
case LOCAL_GL_TEXTURE_WRAP_R:
case LOCAL_GL_TEXTURE_MAX_LOD:
case LOCAL_GL_TEXTURE_MIN_LOD:
return true;
case LOCAL_GL_TEXTURE_MAX_LOD:
case LOCAL_GL_TEXTURE_MIN_LOD:
{
GLfloat f = 0.0f;
gl->fGetTexParameterfv(target.get(), pname, &f);
return JS::NumberValue(float(f));
}
default:
return WebGLContext::IsTexParamValid(pname);
}
return WebGLContext::GetTexParameterInternal(target, pname);
}
} // namespace mozilla

View File

@ -1821,158 +1821,6 @@ WebGLContext::DidRefresh()
}
}
bool
WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
GLint level, GLenum internalFormat,
GLenum format, GLenum type,
mozilla::dom::Element& elt)
{
if (type == LOCAL_GL_HALF_FLOAT_OES &&
!gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float))
{
type = LOCAL_GL_HALF_FLOAT;
}
if (!ValidateTexImageFormatAndType(format, type,
WebGLTexImageFunc::TexImage,
WebGLTexDimensions::Tex2D))
{
return false;
}
HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
if (!video)
return false;
uint16_t readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)
{
//No frame inside, just return
return false;
}
// If it doesn't have a principal, just bail
nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
if (!principal)
return false;
mozilla::layers::ImageContainer* container = video->GetImageContainer();
if (!container)
return false;
if (video->GetCORSMode() == CORS_NONE) {
bool subsumes;
nsresult rv = mCanvasElement->NodePrincipal()->Subsumes(principal, &subsumes);
if (NS_FAILED(rv) || !subsumes) {
GenerateWarning("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
"See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
return false;
}
}
AutoLockImage lockedImage(container);
Image* srcImage = lockedImage.GetImage();
if (!srcImage) {
return false;
}
gl->MakeCurrent();
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
const WebGLTexture::ImageInfo& info = tex->ImageInfoAt(texImageTarget, 0);
bool dimensionsMatch = info.Width() == srcImage->GetSize().width &&
info.Height() == srcImage->GetSize().height;
if (!dimensionsMatch) {
// we need to allocation
gl->fTexImage2D(texImageTarget.get(), level, internalFormat,
srcImage->GetSize().width, srcImage->GetSize().height,
0, format, type, nullptr);
}
const gl::OriginPos destOrigin = mPixelStoreFlipY ? gl::OriginPos::BottomLeft
: gl::OriginPos::TopLeft;
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage,
srcImage->GetSize(),
tex->mGLName,
texImageTarget.get(),
destOrigin);
if (ok) {
TexInternalFormat effectiveInternalFormat =
EffectiveInternalFormatFromInternalFormatAndType(internalFormat,
type);
MOZ_ASSERT(effectiveInternalFormat != LOCAL_GL_NONE);
tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width,
srcImage->GetSize().height, 1,
effectiveInternalFormat,
WebGLImageDataStatus::InitializedImageData);
tex->Bind(TexImageTargetToTexTarget(texImageTarget));
}
return ok;
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLenum format, GLenum type,
dom::Element* elt, ErrorResult* const out_rv)
{
// TODO: Consolidate all the parameter validation
// checks. Instead of spreading out the cheks in multple
// places, consolidate into one spot.
if (IsContextLost())
return;
if (!ValidateTexImageTarget(rawTexImageTarget,
WebGLTexImageFunc::TexSubImage,
WebGLTexDimensions::Tex2D))
{
ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
return;
}
const TexImageTarget texImageTarget(rawTexImageTarget);
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel) {
ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d",
level, maxLevel);
return;
}
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex)
return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat internalFormat = imageInfo.EffectiveInternalFormat();
// Trying to handle the video by GPU directly first
if (TexImageFromVideoElement(texImageTarget, level,
internalFormat.get(), format, type, *elt))
{
return;
}
RefPtr<gfx::DataSourceSurface> data;
WebGLTexelFormat srcFormat;
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(*elt);
*out_rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
if (out_rv->Failed() || !data)
return;
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
TexSubImage2D_base(texImageTarget.get(), level, xoffset, yoffset, size.width,
size.height, data->Stride(), format, type, data->GetData(),
byteLength, js::Scalar::MaxTypedArrayViewType, srcFormat,
res.mIsPremultiplied);
}
size_t
RoundUpToMultipleOf(size_t value, size_t multiple)
{
@ -1980,6 +1828,12 @@ RoundUpToMultipleOf(size_t value, size_t multiple)
return overshoot - (overshoot % multiple);
}
CheckedUint32
RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y)
{
return ((x + y - 1) / y) * y;
}
////////////////////////////////////////////////////////////////////////////////
WebGLContext::ScopedMaskWorkaround::ScopedMaskWorkaround(WebGLContext& webgl)

View File

@ -282,9 +282,6 @@ public:
// Returns hex formatted version of glenum if glenum is unknown.
static void EnumName(GLenum glenum, nsACString* out_name);
bool IsCompressedTextureFormat(GLenum format);
bool IsTextureFormatCompressed(TexInternalFormat format);
void DummyFramebufferOperation(const char* funcName);
WebGLTexture* ActiveBoundTextureForTarget(const TexTarget texTarget) const {
@ -374,13 +371,11 @@ public:
dom::Nullable< nsTArray<nsString> >& retval);
void GetExtension(JSContext* cx, const nsAString& name,
JS::MutableHandle<JSObject*> retval, ErrorResult& rv);
void ActiveTexture(GLenum texture);
void AttachShader(WebGLProgram* prog, WebGLShader* shader);
void BindAttribLocation(WebGLProgram* prog, GLuint location,
const nsAString& name);
void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
void BindTexture(GLenum target, WebGLTexture* tex);
void BindVertexArray(WebGLVertexArray* vao);
void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
void BlendEquation(GLenum mode);
@ -397,24 +392,9 @@ public:
void CompileShader(WebGLShader* shader);
void CompileShaderANGLE(WebGLShader* shader);
void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource);
void CompressedTexImage2D(GLenum target, GLint level,
GLenum internalformat, GLsizei width,
GLsizei height, GLint border,
const dom::ArrayBufferView& view);
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level,
GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format,
const dom::ArrayBufferView& view);
void CopyTexImage2D(GLenum texImageTarget, GLint level,
GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border);
void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLint x, GLint y, GLsizei width,
GLsizei height);
already_AddRefed<WebGLFramebuffer> CreateFramebuffer();
already_AddRefed<WebGLProgram> CreateProgram();
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
already_AddRefed<WebGLTexture> CreateTexture();
already_AddRefed<WebGLShader> CreateShader(GLenum type);
already_AddRefed<WebGLVertexArray> CreateVertexArray();
void CullFace(GLenum face);
@ -423,7 +403,6 @@ public:
void DeleteRenderbuffer(WebGLRenderbuffer* rb);
void DeleteShader(WebGLShader* shader);
void DeleteVertexArray(WebGLVertexArray* vao);
void DeleteTexture(WebGLTexture* tex);
void DepthFunc(GLenum func);
void DepthMask(WebGLboolean b);
void DepthRange(GLclampf zNear, GLclampf zFar);
@ -442,7 +421,6 @@ public:
GLenum attachment, const char* funcName);
void FrontFace(GLenum mode);
void GenerateMipmap(GLenum target);
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
GLuint index);
already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram* prog,
@ -508,13 +486,6 @@ public:
void GetShaderInfoLog(WebGLShader* shader, nsAString& retval);
void GetShaderSource(WebGLShader* shader, nsAString& retval);
void GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval);
JS::Value GetTexParameter(GLenum target, GLenum pname);
void GetTexParameter(JSContext*, GLenum target, GLenum pname,
JS::MutableHandle<JS::Value> retval)
{
retval.set(GetTexParameter(target, pname));
}
JS::Value GetUniform(JSContext* cx, WebGLProgram* prog,
WebGLUniformLocation* loc);
@ -534,7 +505,6 @@ public:
bool IsProgram(WebGLProgram* prog);
bool IsRenderbuffer(WebGLRenderbuffer* rb);
bool IsShader(WebGLShader* shader);
bool IsTexture(WebGLTexture* tex);
bool IsVertexArray(WebGLVertexArray* vao);
void LineWidth(GLfloat width);
void LinkProgram(WebGLProgram* prog);
@ -561,105 +531,6 @@ public:
void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
GLenum dppass);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum format,
GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum format, GLenum type, dom::ImageData* pixels,
ErrorResult& rv);
// Allow whatever element types the bindings are willing to pass
// us in TexImage2D
bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLenum format,
GLenum type, mozilla::dom::Element& image);
template<class ElementType>
void TexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLenum format, GLenum type,
ElementType& elt, ErrorResult& rv)
{
if (IsContextLost())
return;
if (!ValidateTexImageTarget(rawTexImageTarget,
WebGLTexImageFunc::TexImage,
WebGLTexDimensions::Tex2D))
{
ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
return;
}
const TexImageTarget texImageTarget(rawTexImageTarget);
if (level < 0)
return ErrorInvalidValue("texImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel) {
ErrorInvalidValue("texImage2D: level %d is too large, max is %d",
level, maxLevel);
return;
}
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex)
return ErrorInvalidOperation("no texture is bound to this target");
// Trying to handle the video by GPU directly first
if (TexImageFromVideoElement(texImageTarget, level, internalFormat,
format, type, elt))
{
return;
}
RefPtr<gfx::DataSourceSurface> data;
WebGLTexelFormat srcFormat;
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
if (rv.Failed() || !data)
return;
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
return TexImage2D_base(texImageTarget, level, internalFormat,
size.width, size.height, data->Stride(), 0,
format, type, data->GetData(), byteLength,
js::Scalar::MaxTypedArrayViewType, srcFormat,
res.mIsPremultiplied);
}
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
TexParameter_base(target, pname, nullptr, &param);
}
void TexParameteri(GLenum target, GLenum pname, GLint param) {
TexParameter_base(target, pname, &param, nullptr);
}
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLenum format, GLenum type,
dom::ImageData* pixels, ErrorResult& rv);
void TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLenum format, GLenum type,
dom::Element* elt, ErrorResult* const out_rv);
// Allow whatever element types the bindings are willing to pass
// us in TexSubImage2D
template<class ElementType>
void TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
GLint yoffset, GLenum format, GLenum type,
ElementType& elt, ErrorResult& out_rv)
{
TexSubImage2D(rawTexImageTarget, level, xoffset, yoffset, format, type, &elt,
&out_rv);
}
void Uniform1i(WebGLUniformLocation* loc, GLint x);
void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
@ -940,6 +811,97 @@ private:
bool ValidateCapabilityEnum(GLenum cap, const char* info);
realGLboolean* GetStateTrackingSlot(GLenum cap);
// -----------------------------------------------------------------------------
// Texture funcions (WebGLContextTextures.cpp)
public:
void ActiveTexture(GLenum texUnit);
void BindTexture(GLenum texTarget, WebGLTexture* tex);
already_AddRefed<WebGLTexture> CreateTexture();
void DeleteTexture(WebGLTexture* tex);
void GenerateMipmap(GLenum texTarget);
void GetTexParameter(JSContext*, GLenum texTarget, GLenum pname,
JS::MutableHandle<JS::Value> retval)
{
retval.set(GetTexParameter(texTarget, pname));
}
bool IsTexture(WebGLTexture* tex);
void TexParameterf(GLenum texTarget, GLenum pname, GLfloat param) {
TexParameter_base(texTarget, pname, nullptr, &param);
}
void TexParameteri(GLenum texTarget, GLenum pname, GLint param) {
TexParameter_base(texTarget, pname, &param, nullptr);
}
protected:
JS::Value GetTexParameter(GLenum texTarget, GLenum pname);
void TexParameter_base(GLenum texTarget, GLenum pname, GLint* maybeIntParam,
GLfloat* maybeFloatParam);
virtual bool IsTexParamValid(GLenum pname) const;
// Upload funcs
public:
void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border,
const dom::ArrayBufferView& view);
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, const dom::ArrayBufferView& view);
void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_rv);
// Allow whatever element unpackTypes the bindings are willing to pass
// us in Tex(Sub)Image2D
template<typename ElementT>
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
ErrorResult& out_rv)
{
TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, &elem,
&out_rv);
}
template<typename ElementT>
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
ErrorResult& out_rv)
{
TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
&elem, &out_rv);
}
// -----------------------------------------------------------------------------
// Vertices Feature (WebGLContextVertices.cpp)
public:
@ -1057,14 +1019,6 @@ protected:
GLsizei depth, uint32_t pixelSize,
uint32_t alignment);
virtual JS::Value GetTexParameterInternal(const TexTarget& target,
GLenum pname);
// Returns x rounded to the next highest multiple of y.
static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
return ((x + y - 1) / y) * y;
}
inline void InvalidateBufferFetching()
{
mBufferFetchingIsVerified = false;
@ -1227,8 +1181,6 @@ protected:
GLint width, GLint height, GLint depth,
GLint border, GLenum format, GLenum type,
WebGLTexImageFunc func, WebGLTexDimensions dims);
bool ValidateTexImageTarget(GLenum texImageTarget, WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
@ -1272,24 +1224,6 @@ protected:
// helpers
// If jsArrayType is MaxTypedArrayViewType, it means no array.
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei srcStrideOrZero, GLint border,
GLenum format, GLenum type, void* data,
uint32_t byteLength, js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexSubImage2D_base(GLenum texImageTarget, GLint level,
GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLsizei srcStrideOrZero,
GLenum format, GLenum type, void* pixels,
uint32_t byteLength, js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexParameter_base(GLenum target, GLenum pname,
GLint* const out_intParam,
GLfloat* const out_floatParam);
bool ConvertImage(size_t width, size_t height, size_t srcStride,
size_t dstStride, const uint8_t* src, uint8_t* dst,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
@ -1321,11 +1255,6 @@ protected:
RefPtr<gfx::DataSourceSurface>& imageOut,
WebGLTexelFormat* format);
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level, TexInternalFormat internalFormat,
GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height, bool isSub);
// Returns false if `object` is null or not valid.
template<class ObjectType>
bool ValidateObject(const char* info, ObjectType* object);
@ -1382,14 +1311,6 @@ protected:
GLenum CheckedBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
GLenum usage);
/** Like glTexImage2D, but if the call may change the texture size, checks
* any GL error generated by this glTexImage2D call and returns it.
*/
GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
TexInternalFormat internalFormat, GLsizei width,
GLsizei height, GLint border, TexFormat format,
TexType type, const GLvoid* data);
void ForceLoseContext(bool simulateLoss = false);
void ForceRestoreContext();
@ -1691,6 +1612,17 @@ private:
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
bool
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
TexTarget* const out_texTarget, WebGLTexture** const out_tex);
bool
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
const char* funcName, TexImageTarget* const out_texImageTarget,
WebGLTexture** const out_tex);
// Returns x rounded to the next highest multiple of y.
CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
} // namespace mozilla
#endif

View File

@ -25,9 +25,8 @@ static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
bool
WebGLContext::DrawInstanced_check(const char* info)
{
// This restriction was removed in GLES3, so WebGL2 shouldn't have it.
if (!IsWebGL2() &&
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays) &&
if ((IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays)) &&
!mBufferFetchingHasPerVertex)
{
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,469 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLBuffer.h"
#include "WebGLVertexAttribData.h"
#include "WebGLShader.h"
#include "WebGLProgram.h"
#include "WebGLUniformLocation.h"
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLShaderPrecisionFormat.h"
#include "WebGLTexture.h"
#include "WebGLExtensions.h"
#include "WebGLVertexArray.h"
#include "nsString.h"
#include "nsDebug.h"
#include "nsReadableUtils.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "GLContext.h"
#include "nsContentUtils.h"
#include "nsError.h"
#include "nsLayoutUtils.h"
#include "CanvasUtils.h"
#include "gfxUtils.h"
#include "jsfriendapi.h"
#include "WebGLTexelConversions.h"
#include "WebGLValidateStrings.h"
#include <algorithm>
// needed to check if current OS is lower than 10.7
#if defined(MOZ_WIDGET_COCOA)
#include "nsCocoaFeatures.h"
#endif
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/Endian.h"
namespace mozilla {
static bool
IsValidTexTarget(WebGLContext* webgl, GLenum rawTexTarget, TexTarget* const out)
{
switch (rawTexTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP:
break;
case LOCAL_GL_TEXTURE_3D:
if (!webgl->IsWebGL2())
return false;
break;
default:
return false;
}
*out = rawTexTarget;
return true;
}
static bool
IsValidTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
TexImageTarget* const out)
{
switch (rawTexImageTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
case LOCAL_GL_TEXTURE_3D:
if (!webgl->IsWebGL2())
return false;
break;
default:
return false;
}
*out = rawTexImageTarget;
return true;
}
bool
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
TexTarget* const out_texTarget, WebGLTexture** const out_tex)
{
if (webgl->IsContextLost())
return false;
TexTarget texTarget;
if (!IsValidTexTarget(webgl, rawTexTarget, &texTarget)) {
webgl->ErrorInvalidEnum("%s: Invalid texTarget.", funcName);
return false;
}
WebGLTexture* tex = webgl->ActiveBoundTextureForTarget(texTarget);
if (!tex) {
webgl->ErrorInvalidOperation("%s: No texture is bound to this target.", funcName);
return false;
}
*out_texTarget = texTarget;
*out_tex = tex;
return true;
}
bool
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
const char* funcName, TexImageTarget* const out_texImageTarget,
WebGLTexture** const out_tex)
{
if (webgl->IsContextLost())
return false;
TexImageTarget texImageTarget;
if (!IsValidTexImageTarget(webgl, rawTexImageTarget, &texImageTarget)) {
webgl->ErrorInvalidEnum("%s: Invalid texImageTarget.", funcName);
return false;
}
WebGLTexture* tex = webgl->ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex) {
webgl->ErrorInvalidOperation("%s: No texture is bound to this target.", funcName);
return false;
}
*out_texImageTarget = texImageTarget;
*out_tex = tex;
return true;
}
bool
WebGLContext::IsTexParamValid(GLenum pname) const
{
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
case LOCAL_GL_TEXTURE_MAG_FILTER:
case LOCAL_GL_TEXTURE_WRAP_S:
case LOCAL_GL_TEXTURE_WRAP_T:
return true;
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
return IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic);
default:
return false;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// GL calls
void
WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
{
if (IsContextLost())
return;
if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
return;
// Need to check rawTarget first before comparing against newTex->Target() as
// newTex->Target() returns a TexTarget, which will assert on invalid value.
WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
switch (rawTarget) {
case LOCAL_GL_TEXTURE_2D:
currentTexPtr = &mBound2DTextures[mActiveTexture];
break;
case LOCAL_GL_TEXTURE_CUBE_MAP:
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
break;
case LOCAL_GL_TEXTURE_3D:
if (!IsWebGL2())
return ErrorInvalidEnum("bindTexture: target TEXTURE_3D is only available in WebGL version 2.0 or newer");
currentTexPtr = &mBound3DTextures[mActiveTexture];
break;
default:
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
}
const TexTarget texTarget(rawTarget);
MakeContextCurrent();
if (newTex && !newTex->BindTexture(texTarget))
return;
if (!newTex) {
gl->fBindTexture(texTarget.get(), 0);
}
*currentTexPtr = newTex;
}
void
WebGLContext::GenerateMipmap(GLenum rawTexTarget)
{
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return;
tex->GenerateMipmap(texTarget);
}
JS::Value
WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
{
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return JS::NullValue();
if (!IsTexParamValid(pname)) {
ErrorInvalidEnumInfo("getTexParameter: pname", pname);
return JS::NullValue();
}
return tex->GetTexParameter(texTarget, pname);
}
bool
WebGLContext::IsTexture(WebGLTexture* tex)
{
if (IsContextLost())
return false;
if (!ValidateObjectAllowDeleted("isTexture", tex))
return false;
return tex->IsTexture();
}
void
WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeIntParam,
GLfloat* maybeFloatParam)
{
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return;
tex->TexParameter(texTarget, pname, maybeIntParam, maybeFloatParam);
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Uploads
//////////////////////////////////////////////////////////////////////////////////////////
// TexImage
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, elem,
out_rv);
}
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexImage2D(texImageTarget, level, internalFormat, width, height, border,
unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType,
dom::ImageData* imageData, ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
imageData, &out_rv);
}
//////////////////////////////////////////////////////////////////////////////////////////
// TexSubImage
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
elem, out_rv);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
imageData, &out_rv);
}
//////////////////////////////////////////////////////////////////////////////////////////
// CopyTex(Sub)Image
void
WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexImage2D",
&texImageTarget, &tex))
{
return;
}
tex->CopyTexImage2D(texImageTarget, level, internalFormat, x, y, width, height,
border);
}
void
WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexSubImage2D",
&texImageTarget, &tex))
{
return;
}
tex->CopyTexSubImage2D(texImageTarget, level, xOffset, yOffset, x, y, width, height);
}
//////////////////////////////////////////////////////////////////////////////////////////
// CompressedTex(Sub)Image
void
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferView& view)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexImage2D",
&texImageTarget, &tex))
{
return;
}
tex->CompressedTexImage2D(texImageTarget, level, internalFormat, width, height,
border, view);
}
void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum unpackFormat,
const dom::ArrayBufferView& view)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexSubImage2D",
&texImageTarget, &tex))
{
return;
}
tex->CompressedTexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
unpackFormat, view);
}
} // namespace mozilla

View File

@ -1001,7 +1001,7 @@ WebGLContext::EnumName(GLenum glenum, nsACString* out_name)
}
bool
WebGLContext::IsCompressedTextureFormat(GLenum format)
IsCompressedTextureFormat(GLenum format)
{
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@ -1034,7 +1034,7 @@ WebGLContext::IsCompressedTextureFormat(GLenum format)
bool
WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
IsTextureFormatCompressed(TexInternalFormat format)
{
return IsCompressedTextureFormat(format.get());
}

View File

@ -61,6 +61,9 @@ TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
// Helper function to create a JS::Value from a C string
JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv);
bool IsCompressedTextureFormat(GLenum format);
bool IsTextureFormatCompressed(TexInternalFormat format);
struct GLComponents
{
unsigned char mComponents;

View File

@ -607,40 +607,6 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func,
return false;
}
/**
* Check if the given texture target is valid for TexImage.
*/
bool
WebGLContext::ValidateTexImageTarget(GLenum target, WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
switch (dims) {
case WebGLTexDimensions::Tex2D:
if (target == LOCAL_GL_TEXTURE_2D ||
IsTexImageCubemapTarget(target))
{
return true;
}
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
return false;
case WebGLTexDimensions::Tex3D:
if (target == LOCAL_GL_TEXTURE_3D)
{
return true;
}
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
return false;
default:
MOZ_ASSERT(false, "ValidateTexImageTarget: Invalid dims");
}
return false;
}
/**
* Return true if type is a valid texture image type for source,
* taking into account enabled WebGL extensions.

View File

@ -8,13 +8,13 @@
#include <algorithm>
#include "GLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Scoped.h"
#include "ScopedGLHelpers.h"
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLTexelConversions.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
@ -730,6 +730,289 @@ WebGLTexture::SetFakeBlackStatus(WebGLTextureFakeBlackStatus x)
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
}
//////////////////////////////////////////////////////////////////////////////////////////
// GL calls
bool
WebGLTexture::BindTexture(TexTarget texTarget)
{
// silently ignore a deleted texture
if (IsDeleted())
return false;
if (HasEverBeenBound() && mTarget != texTarget) {
mContext->ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target");
return false;
}
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
Bind(texTarget);
return true;
}
void
WebGLTexture::GenerateMipmap(TexTarget texTarget)
{
const TexImageTarget imageTarget = (texTarget == LOCAL_GL_TEXTURE_2D)
? LOCAL_GL_TEXTURE_2D
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
if (!IsMipmapRangeValid())
{
return mContext->ErrorInvalidOperation("generateMipmap: Texture does not have a valid mipmap range.");
}
if (!HasImageInfoAt(imageTarget, EffectiveBaseMipmapLevel()))
{
return mContext->ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
}
if (!mContext->IsWebGL2() && !IsFirstImagePowerOfTwo())
return mContext->ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
TexInternalFormat internalformat = ImageInfoAt(imageTarget, 0).EffectiveInternalFormat();
if (IsTextureFormatCompressed(internalformat))
return mContext->ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
if (mContext->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
(IsGLDepthFormat(internalformat) || IsGLDepthStencilFormat(internalformat)))
{
return mContext->ErrorInvalidOperation("generateMipmap: "
"A texture that has a base internal format of "
"DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
}
if (!AreAllLevel0ImageInfosEqual())
return mContext->ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type.");
SetGeneratedMipmap();
mContext->MakeContextCurrent();
gl::GLContext* gl = mContext->gl;
if (gl->WorkAroundDriverBugs()) {
// bug 696495 - to work around failures in the texture-mips.html test on various drivers, we
// set the minification filter before calling glGenerateMipmap. This should not carry a significant performance
// overhead so we do it unconditionally.
//
// note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See Chromium bug 101105.
gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST_MIPMAP_NEAREST);
gl->fGenerateMipmap(texTarget.get());
gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, MinFilter().get());
} else {
gl->fGenerateMipmap(texTarget.get());
}
}
JS::Value
WebGLTexture::GetTexParameter(TexTarget texTarget, GLenum pname)
{
mContext->MakeContextCurrent();
GLint i = 0;
GLfloat f = 0.0f;
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
case LOCAL_GL_TEXTURE_MAG_FILTER:
case LOCAL_GL_TEXTURE_WRAP_S:
case LOCAL_GL_TEXTURE_WRAP_T:
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
case LOCAL_GL_TEXTURE_COMPARE_MODE:
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
case LOCAL_GL_TEXTURE_SWIZZLE_A:
case LOCAL_GL_TEXTURE_SWIZZLE_B:
case LOCAL_GL_TEXTURE_SWIZZLE_G:
case LOCAL_GL_TEXTURE_SWIZZLE_R:
case LOCAL_GL_TEXTURE_WRAP_R:
mContext->gl->fGetTexParameteriv(texTarget.get(), pname, &i);
return JS::NumberValue(uint32_t(i));
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
case LOCAL_GL_TEXTURE_MAX_LOD:
case LOCAL_GL_TEXTURE_MIN_LOD:
mContext->gl->fGetTexParameterfv(texTarget.get(), pname, &f);
return JS::NumberValue(float(f));
default:
MOZ_CRASH("Unhandled pname.");
}
}
bool
WebGLTexture::IsTexture() const
{
return HasEverBeenBound() && !IsDeleted();
}
// Here we have to support all pnames with both int and float params.
// See this discussion:
// https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
void
WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam,
GLfloat* maybeFloatParam)
{
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
GLint intParam = maybeIntParam ? *maybeIntParam : GLint(*maybeFloatParam);
GLfloat floatParam = maybeFloatParam ? *maybeFloatParam : GLfloat(*maybeIntParam);
bool paramBadEnum = false;
bool paramBadValue = false;
switch (pname) {
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
if (!mContext->IsWebGL2())
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
if (intParam < 0) {
paramBadValue = true;
break;
}
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
if (pname == LOCAL_GL_TEXTURE_BASE_LEVEL)
mBaseMipmapLevel = intParam;
else
mMaxMipmapLevel = intParam;
break;
case LOCAL_GL_TEXTURE_COMPARE_MODE:
if (!mContext->IsWebGL2())
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
paramBadValue = (intParam != LOCAL_GL_NONE &&
intParam != LOCAL_GL_COMPARE_REF_TO_TEXTURE);
break;
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
if (!mContext->IsWebGL2())
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
switch (intParam) {
case LOCAL_GL_LEQUAL:
case LOCAL_GL_GEQUAL:
case LOCAL_GL_LESS:
case LOCAL_GL_GREATER:
case LOCAL_GL_EQUAL:
case LOCAL_GL_NOTEQUAL:
case LOCAL_GL_ALWAYS:
case LOCAL_GL_NEVER:
break;
default:
paramBadValue = true;
}
break;
case LOCAL_GL_TEXTURE_MIN_FILTER:
switch (intParam) {
case LOCAL_GL_NEAREST:
case LOCAL_GL_LINEAR:
case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
case LOCAL_GL_NEAREST_MIPMAP_LINEAR:
case LOCAL_GL_LINEAR_MIPMAP_LINEAR:
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
mMinFilter = intParam;
break;
default:
paramBadEnum = true;
}
break;
case LOCAL_GL_TEXTURE_MAG_FILTER:
switch (intParam) {
case LOCAL_GL_NEAREST:
case LOCAL_GL_LINEAR:
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
mMagFilter = intParam;
break;
default:
paramBadEnum = true;
}
break;
case LOCAL_GL_TEXTURE_WRAP_S:
switch (intParam) {
case LOCAL_GL_CLAMP_TO_EDGE:
case LOCAL_GL_MIRRORED_REPEAT:
case LOCAL_GL_REPEAT:
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
mWrapS = intParam;
break;
default:
paramBadEnum = true;
}
break;
case LOCAL_GL_TEXTURE_WRAP_T:
switch (intParam) {
case LOCAL_GL_CLAMP_TO_EDGE:
case LOCAL_GL_MIRRORED_REPEAT:
case LOCAL_GL_REPEAT:
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
mWrapT = intParam;
break;
default:
paramBadEnum = true;
}
break;
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
if (!mContext->IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic))
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
if (maybeFloatParam && floatParam < 1.0f)
paramBadValue = true;
else if (maybeIntParam && intParam < 1)
paramBadValue = true;
break;
default:
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
}
if (paramBadEnum) {
if (maybeIntParam) {
mContext->ErrorInvalidEnum("texParameteri: pname 0x%04x: Invalid param"
" 0x%04x.",
pname, intParam);
} else {
mContext->ErrorInvalidEnum("texParameterf: pname 0x%04x: Invalid param %g.",
pname, floatParam);
}
return;
}
if (paramBadValue) {
if (maybeIntParam) {
mContext->ErrorInvalidValue("texParameteri: pname 0x%04x: Invalid param %i"
" (0x%x).",
pname, intParam, intParam);
} else {
mContext->ErrorInvalidValue("texParameterf: pname 0x%04x: Invalid param %g.",
pname, floatParam);
}
return;
}
mContext->MakeContextCurrent();
if (maybeIntParam)
mContext->gl->fTexParameteri(texTarget.get(), pname, intParam);
else
mContext->gl->fTexParameterf(texTarget.get(), pname, floatParam);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTexture, AddRef)

View File

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/LinkedList.h"
#include "nsWrapperCache.h"
@ -18,6 +19,12 @@
#include "WebGLStrongTypes.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class Element;
class ImageData;
} // namespace dom
// Zero is not an integer power of two.
inline bool
@ -27,6 +34,10 @@ IsPOTAssumingNonnegative(GLsizei x)
return x && (x & (x-1)) == 0;
}
bool
DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target, uint8_t dims,
const char* funcName);
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
class WebGLTexture final
@ -36,7 +47,35 @@ class WebGLTexture final
, public WebGLContextBoundObject
, public WebGLFramebufferAttachable
{
friend class WebGLContext;
friend class WebGLFramebuffer;
public:
class ImageInfo;
const GLuint mGLName;
protected:
GLenum mTarget;
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS, mWrapT;
size_t mFacesCount, mMaxLevelWithCustomImages;
nsTArray<ImageInfo> mImageInfos;
bool mHaveGeneratedMipmap; // Set by generateMipmap
bool mImmutable; // Set by texStorage*
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
WebGLTextureFakeBlackStatus mFakeBlackStatus;
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
explicit WebGLTexture(WebGLContext* webgl, GLuint tex);
void Delete();
@ -50,27 +89,156 @@ public:
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
protected:
~WebGLTexture() {
DeleteOnce();
}
friend class WebGLContext;
friend class WebGLFramebuffer;
// We store information about the various images that are part of this
// texture. (cubemap faces, mipmap levels)
public:
const GLuint mGLName;
////////////////////////////////////
// GL calls
bool BindTexture(TexTarget texTarget);
void GenerateMipmap(TexTarget texTarget);
JS::Value GetTexParameter(TexTarget texTarget, GLenum pname);
bool IsTexture() const;
void TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam,
GLfloat* maybeFloatParam);
////////////////////////////////////
// WebGLTextureUpload.cpp
void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferView& view);
void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border, GLsizei imageSize,
const dom::ArrayBufferView& view);
void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum unpackFormat,
const dom::ArrayBufferView& view);
void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLsizei imageSize,
const dom::ArrayBufferView& view);
void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void CopyTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height);
void CopyTexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width,
GLsizei height);
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult* const out_rv);
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_rv);
void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexStorage2D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height);
void TexStorage3D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth);
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
dom::ImageData* imageData, ErrorResult* const out_rv);
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_rv);
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::ImageData* imageData,
ErrorResult* const out_rv);
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::Element* elem, ErrorResult* const out_rv);
protected:
GLenum mTarget;
/** Like glTexImage2D, but if the call may change the texture size, checks
* any GL error generated by this glTexImage2D call and returns it.
*/
GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
TexInternalFormat internalFormat, GLsizei width,
GLsizei height, GLint border, TexFormat format,
TexType type, const GLvoid* data);
bool ValidateTexStorage(TexImageTarget texImageTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
const char* funcName);
void SpecifyTexStorage(GLsizei levels, TexInternalFormat internalFormat,
GLsizei width, GLsizei height, GLsizei depth);
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level, TexInternalFormat internalFormat,
GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height, bool isSub);
bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLenum unpackFormat,
GLenum unpackType, dom::Element* elem);
// If jsArrayType is MaxTypedArrayViewType, it means no array.
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei srcStrideOrZero, GLint border, GLenum unpackFormat,
GLenum unpackType, void* data, uint32_t byteLength,
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
bool srcPremultiplied);
void TexSubImage2D_base(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLsizei srcStrideOrZero, GLenum unpackFormat,
GLenum unpackType, void* pixels, uint32_t byteLength,
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
bool srcPremultiplied);
bool ValidateTexStorage(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info);
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
public:
// We store information about the various images that are part of this
// texture. (cubemap faces, mipmap levels)
class ImageInfo
: public WebGLRectangleObject
{
@ -216,20 +384,6 @@ public:
bool EnsureInitializedImageData(TexImageTarget imageTarget, GLint level);
protected:
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS, mWrapT;
size_t mFacesCount, mMaxLevelWithCustomImages;
nsTArray<ImageInfo> mImageInfos;
bool mHaveGeneratedMipmap; // Set by generateMipmap
bool mImmutable; // Set by texStorage*
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
WebGLTextureFakeBlackStatus mFakeBlackStatus;
void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) {
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages,

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,7 @@ UNIFIED_SOURCES += [
'WebGLContextGL.cpp',
'WebGLContextLossHandler.cpp',
'WebGLContextState.cpp',
'WebGLContextTextures.cpp',
'WebGLContextUnchecked.cpp',
'WebGLContextUtils.cpp',
'WebGLContextValidate.cpp',
@ -125,6 +126,7 @@ UNIFIED_SOURCES += [
'WebGLSync.cpp',
'WebGLTexelConversions.cpp',
'WebGLTexture.cpp',
'WebGLTextureUpload.cpp',
'WebGLTimerQuery.cpp',
'WebGLTransformFeedback.cpp',
'WebGLUniformLocation.cpp',

View File

@ -35,7 +35,7 @@ CaptureStreamTestHelper.prototype = {
/* Request a frame from the stream played by |video|. */
requestFrame: function (video) {
info("Requesting frame from " + video.id);
video.mozSrcObject.requestFrame();
video.srcObject.requestFrame();
},
/* Tests the top left pixel of |video| against |refData|. Format [R,G,B,A]. */

View File

@ -19,7 +19,7 @@ function runTest() {
context.fillRect(0, 0, canvas.width, canvas.height);
var video = document.getElementById('video');
video.mozSrcObject = canvas.captureStream(0);
video.srcObject = canvas.captureStream(0);
video.play();
video.onloadeddata = finished;
video.onerror = finished;

View File

@ -33,7 +33,7 @@ function runTest() {
gl.clear(gl.COLOR_BUFFER_BIT);
var video = document.getElementById('video');
video.mozSrcObject = canvas.captureStream(0);
video.srcObject = canvas.captureStream(0);
video.play();
video.onloadeddata = finished;
video.onerror = finished;

View File

@ -19,9 +19,9 @@ function checkDrawColorInitialRed() {
h.drawColor(c, h.red);
vauto.mozSrcObject = c.captureStream();
vmanual.mozSrcObject = c.captureStream(0);
vrate.mozSrcObject = c.captureStream(10);
vauto.srcObject = c.captureStream();
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "vauto hould not be drawn to before stable state");
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "vrate Should not be drawn to before stable state");

View File

@ -50,9 +50,9 @@ function checkClearColorInitialRed() {
h.clearColor(c, h.red);
vauto.mozSrcObject = c.captureStream();
vmanual.mozSrcObject = c.captureStream(0);
vrate.mozSrcObject = c.captureStream(10);
vauto.srcObject = c.captureStream();
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");

View File

@ -744,7 +744,8 @@ IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aNewValue)
{
nsIContent *content = GetContentBR(aElement);
mPreAttrChangeLength = content ?
@ -756,7 +757,8 @@ IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
mEndOfAddedTextCache.Clear();
mStartOfRemovingTextRangeCache.Clear();

View File

@ -493,7 +493,7 @@ HTMLButtonElement::DoneCreatingElement()
nsresult
HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&

View File

@ -80,7 +80,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed

View File

@ -375,7 +375,7 @@ HTMLImageElement::GetAttributeMappingFunction() const
nsresult
HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{

View File

@ -334,7 +334,7 @@ protected:
void UpdateFormOwner();
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,

View File

@ -1020,7 +1020,7 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co
nsresult
HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {

View File

@ -865,7 +865,7 @@ protected:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed

View File

@ -527,6 +527,30 @@ HTMLMediaElement::GetMozMediaSourceObject() const
return source.forget();
}
already_AddRefed<DOMMediaStream>
HTMLMediaElement::GetSrcObject() const
{
NS_ASSERTION(!mSrcAttrStream || mSrcAttrStream->GetStream(),
"MediaStream should have been set up properly");
nsRefPtr<DOMMediaStream> stream = mSrcAttrStream;
return stream.forget();
}
void
HTMLMediaElement::SetSrcObject(DOMMediaStream& aValue)
{
SetMozSrcObject(&aValue);
}
void
HTMLMediaElement::SetSrcObject(DOMMediaStream* aValue)
{
mSrcAttrStream = aValue;
DoLoad();
}
// TODO: Remove prefixed versions soon (1183495)
already_AddRefed<DOMMediaStream>
HTMLMediaElement::GetMozSrcObject() const
{

View File

@ -547,8 +547,12 @@ public:
}
already_AddRefed<MediaSource> GetMozMediaSourceObject() const;
already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
already_AddRefed<DOMMediaStream> GetSrcObject() const;
void SetSrcObject(DOMMediaStream& aValue);
void SetSrcObject(DOMMediaStream* aValue);
// TODO: remove prefixed versions soon (1183495).
already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
void SetMozSrcObject(DOMMediaStream& aValue);
void SetMozSrcObject(DOMMediaStream* aValue);

View File

@ -182,7 +182,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult
HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName,

View File

@ -47,7 +47,7 @@ public:
int32_t aModType) const override;
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;

View File

@ -153,7 +153,8 @@ HTMLPropertiesCollection::NamedItem(const nsAString& aName)
void
HTMLPropertiesCollection::AttributeChanged(nsIDocument *aDocument, Element* aElement,
int32_t aNameSpaceID, nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
mIsDirty = true;
}
@ -427,7 +428,8 @@ PropertyNodeList::GetValues(JSContext* aCx, nsTArray<JS::Value >& aResult,
void
PropertyNodeList::AttributeChanged(nsIDocument* aDocument, Element* aElement,
int32_t aNameSpaceID, nsIAtom* aAttribute,
int32_t aModType)
int32_t aModType,
const nsAttrValue* aOldValue)
{
mIsDirty = true;
}

View File

@ -1325,7 +1325,7 @@ HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&

View File

@ -372,7 +372,7 @@ public:
bool aCompileEventHandlers) override;
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;

View File

@ -954,7 +954,7 @@ HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {

View File

@ -190,7 +190,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed

View File

@ -1212,7 +1212,7 @@ HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&

View File

@ -140,7 +140,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
nsAttrValueOrString* aValue,
bool aNotify) override;
// nsIMutationObserver

Some files were not shown because too many files have changed in this diff Show More