зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
0260e6f13c
4
CLOBBER
4
CLOBBER
|
@ -1,4 +1,4 @@
|
|||
# To Trigger a clobber replace ALL of the textual description below,
|
||||
# To trigger a clobber replace ALL of the textual description below,
|
||||
# giving a bug number and a one line description of why a clobber is
|
||||
# required. Modifying this file will make configure check that a
|
||||
# clobber has been performed before the build can continue.
|
||||
|
@ -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 1003702 - ICU is unhappy.
|
||||
Bug 1003702 - Relanding ICU changes with a clobber
|
||||
|
|
|
@ -16,6 +16,7 @@ Cu.import("resource://gre/modules/AppsUtils.jsm");
|
|||
Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
|
||||
Cu.import('resource://gre/modules/Keyboard.jsm');
|
||||
Cu.import('resource://gre/modules/ErrorPage.jsm');
|
||||
Cu.import('resource://gre/modules/AlertsHelper.jsm');
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
Cu.import('resource://gre/modules/NetworkStatsService.jsm');
|
||||
#endif
|
||||
|
@ -343,8 +344,6 @@ var shell = {
|
|||
window.addEventListener('unload', this);
|
||||
this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
|
||||
|
||||
SystemAppProxy.registerFrame(this.contentBrowser);
|
||||
|
||||
CustomEventManager.init();
|
||||
WebappsHelper.init();
|
||||
UserAgentOverrides.init();
|
||||
|
@ -358,7 +357,6 @@ var shell = {
|
|||
ppmm.addMessageListener("dial-handler", this);
|
||||
ppmm.addMessageListener("sms-handler", this);
|
||||
ppmm.addMessageListener("mail-handler", this);
|
||||
ppmm.addMessageListener("app-notification-send", AlertsHelper);
|
||||
ppmm.addMessageListener("file-picker", this);
|
||||
ppmm.addMessageListener("getProfD", function(message) {
|
||||
return Services.dirsvc.get("ProfD", Ci.nsIFile).path;
|
||||
|
@ -653,6 +651,8 @@ var shell = {
|
|||
|
||||
this.reportCrash(true);
|
||||
|
||||
SystemAppProxy.registerFrame(shell.contentBrowser);
|
||||
|
||||
this.sendEvent(window, 'ContentStart');
|
||||
|
||||
Services.obs.notifyObservers(null, 'content-start', null);
|
||||
|
@ -752,11 +752,6 @@ var CustomEventManager = {
|
|||
dump('XXX FIXME : Got a mozContentEvent: ' + detail.type + "\n");
|
||||
|
||||
switch(detail.type) {
|
||||
case 'desktop-notification-show':
|
||||
case 'desktop-notification-click':
|
||||
case 'desktop-notification-close':
|
||||
AlertsHelper.handleEvent(detail);
|
||||
break;
|
||||
case 'webapps-install-granted':
|
||||
case 'webapps-install-denied':
|
||||
WebappsHelper.handleEvent(detail);
|
||||
|
@ -787,190 +782,6 @@ var CustomEventManager = {
|
|||
}
|
||||
}
|
||||
|
||||
var AlertsHelper = {
|
||||
_listeners: {},
|
||||
_count: 0,
|
||||
|
||||
handleEvent: function alert_handleEvent(detail) {
|
||||
if (!detail || !detail.id)
|
||||
return;
|
||||
|
||||
let uid = detail.id;
|
||||
let listener = this._listeners[uid];
|
||||
if (!listener)
|
||||
return;
|
||||
|
||||
let topic;
|
||||
if (detail.type == "desktop-notification-click") {
|
||||
topic = "alertclickcallback";
|
||||
} else if (detail.type == "desktop-notification-show") {
|
||||
topic = "alertshow";
|
||||
} else {
|
||||
/* desktop-notification-close */
|
||||
topic = "alertfinished";
|
||||
}
|
||||
|
||||
if (uid.startsWith("alert")) {
|
||||
try {
|
||||
listener.observer.observe(null, topic, listener.cookie);
|
||||
} catch (e) { }
|
||||
} else {
|
||||
try {
|
||||
listener.mm.sendAsyncMessage("app-notification-return", {
|
||||
uid: uid,
|
||||
topic: topic,
|
||||
target: listener.target
|
||||
});
|
||||
} catch (e) {
|
||||
// we get an exception if the app is not launched yet
|
||||
gSystemMessenger.sendMessage("notification", {
|
||||
clicked: (detail.type === "desktop-notification-click"),
|
||||
title: listener.title,
|
||||
body: listener.text,
|
||||
imageURL: listener.imageURL,
|
||||
lang: listener.lang,
|
||||
dir: listener.dir,
|
||||
id: listener.id,
|
||||
tag: listener.tag
|
||||
},
|
||||
Services.io.newURI(listener.target, null, null),
|
||||
Services.io.newURI(listener.manifestURL, null, null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// we're done with this notification
|
||||
if (topic === "alertfinished") {
|
||||
delete this._listeners[uid];
|
||||
}
|
||||
},
|
||||
|
||||
registerListener: function alert_registerListener(alertId, cookie, alertListener) {
|
||||
this._listeners[alertId] = { observer: alertListener, cookie: cookie };
|
||||
},
|
||||
|
||||
registerAppListener: function alert_registerAppListener(uid, listener) {
|
||||
this._listeners[uid] = listener;
|
||||
|
||||
let app = DOMApplicationRegistry.getAppByManifestURL(listener.manifestURL);
|
||||
DOMApplicationRegistry.getManifestFor(app.manifestURL).then((manifest) => {
|
||||
let helper = new ManifestHelper(manifest, app.origin);
|
||||
let getNotificationURLFor = function(messages) {
|
||||
if (!messages)
|
||||
return null;
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
let message = messages[i];
|
||||
if (message === "notification") {
|
||||
return helper.fullLaunchPath();
|
||||
} else if (typeof message == "object" && "notification" in message) {
|
||||
return helper.resolveFromOrigin(message["notification"]);
|
||||
}
|
||||
}
|
||||
|
||||
// No message found...
|
||||
return null;
|
||||
}
|
||||
|
||||
listener.target = getNotificationURLFor(manifest.messages);
|
||||
|
||||
// Bug 816944 - Support notification messages for entry_points.
|
||||
});
|
||||
},
|
||||
|
||||
showNotification: function alert_showNotification(imageURL,
|
||||
title,
|
||||
text,
|
||||
textClickable,
|
||||
cookie,
|
||||
uid,
|
||||
bidi,
|
||||
lang,
|
||||
manifestURL) {
|
||||
function send(appName, appIcon) {
|
||||
shell.sendChromeEvent({
|
||||
type: "desktop-notification",
|
||||
id: uid,
|
||||
icon: imageURL,
|
||||
title: title,
|
||||
text: text,
|
||||
bidi: bidi,
|
||||
lang: lang,
|
||||
appName: appName,
|
||||
appIcon: appIcon,
|
||||
manifestURL: manifestURL
|
||||
});
|
||||
}
|
||||
|
||||
if (!manifestURL || !manifestURL.length) {
|
||||
send(null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a manifest URL, get the icon and title from the manifest
|
||||
// to prevent spoofing.
|
||||
let app = DOMApplicationRegistry.getAppByManifestURL(manifestURL);
|
||||
DOMApplicationRegistry.getManifestFor(manifestURL).then((aManifest) => {
|
||||
let helper = new ManifestHelper(aManifest, app.origin);
|
||||
send(helper.name, helper.iconURLForSize(128));
|
||||
});
|
||||
},
|
||||
|
||||
showAlertNotification: function alert_showAlertNotification(imageURL,
|
||||
title,
|
||||
text,
|
||||
textClickable,
|
||||
cookie,
|
||||
alertListener,
|
||||
name,
|
||||
bidi,
|
||||
lang) {
|
||||
let currentListener = this._listeners[name];
|
||||
if (currentListener) {
|
||||
currentListener.observer.observe(null, "alertfinished", currentListener.cookie);
|
||||
}
|
||||
|
||||
this.registerListener(name, cookie, alertListener);
|
||||
this.showNotification(imageURL, title, text, textClickable, cookie,
|
||||
name, bidi, lang, null);
|
||||
},
|
||||
|
||||
closeAlert: function alert_closeAlert(name) {
|
||||
shell.sendChromeEvent({
|
||||
type: "desktop-notification-close",
|
||||
id: name
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function alert_receiveMessage(aMessage) {
|
||||
if (!aMessage.target.assertAppHasPermission("desktop-notification")) {
|
||||
Cu.reportError("Desktop-notification message " + aMessage.name +
|
||||
" from a content process with no desktop-notification privileges.");
|
||||
return;
|
||||
}
|
||||
|
||||
let data = aMessage.data;
|
||||
let details = data.details;
|
||||
let listener = {
|
||||
mm: aMessage.target,
|
||||
title: data.title,
|
||||
text: data.text,
|
||||
manifestURL: details.manifestURL,
|
||||
imageURL: data.imageURL,
|
||||
lang: details.lang || undefined,
|
||||
id: details.id || undefined,
|
||||
dir: details.dir || undefined,
|
||||
tag: details.tag || undefined
|
||||
};
|
||||
this.registerAppListener(data.uid, listener);
|
||||
|
||||
this.showNotification(data.imageURL, data.title, data.text,
|
||||
details.textClickable, null,
|
||||
data.uid, details.dir,
|
||||
details.lang, details.manifestURL);
|
||||
},
|
||||
}
|
||||
|
||||
var WebappsHelper = {
|
||||
_installers: {},
|
||||
_count: 0,
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
|
||||
"resource://gre/modules/SystemAppProxy.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
});
|
||||
|
||||
function debug(str) {
|
||||
//dump("=*= AlertsHelper.jsm : " + str + "\n");
|
||||
}
|
||||
|
||||
const kNotificationIconSize = 128;
|
||||
|
||||
const kDesktopNotificationPerm = "desktop-notification";
|
||||
|
||||
const kNotificationSystemMessageName = "notification";
|
||||
|
||||
const kDesktopNotification = "desktop-notification";
|
||||
const kDesktopNotificationShow = "desktop-notification-show";
|
||||
const kDesktopNotificationClick = "desktop-notification-click";
|
||||
const kDesktopNotificationClose = "desktop-notification-close";
|
||||
|
||||
const kTopicAlertClickCallback = "alertclickcallback";
|
||||
const kTopicAlertShow = "alertshow";
|
||||
const kTopicAlertFinished = "alertfinished";
|
||||
|
||||
const kMozChromeNotificationEvent = "mozChromeNotificationEvent";
|
||||
const kMozContentNotificationEvent = "mozContentNotificationEvent";
|
||||
|
||||
const kMessageAppNotificationSend = "app-notification-send";
|
||||
const kMessageAppNotificationReturn = "app-notification-return";
|
||||
const kMessageAlertNotificationSend = "alert-notification-send";
|
||||
const kMessageAlertNotificationClose = "alert-notification-close";
|
||||
|
||||
const kMessages = [
|
||||
kMessageAppNotificationSend,
|
||||
kMessageAlertNotificationSend,
|
||||
kMessageAlertNotificationClose
|
||||
];
|
||||
|
||||
let AlertsHelper = {
|
||||
|
||||
_listeners: {},
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
for (let message of kMessages) {
|
||||
ppmm.addMessageListener(message, this);
|
||||
}
|
||||
SystemAppProxy.addEventListener(kMozContentNotificationEvent, this);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
for (let message of kMessages) {
|
||||
ppmm.removeMessageListener(message, this);
|
||||
}
|
||||
SystemAppProxy.removeEventListener(kMozContentNotificationEvent, this);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(evt) {
|
||||
let detail = evt.detail;
|
||||
|
||||
switch(detail.type) {
|
||||
case kDesktopNotificationShow:
|
||||
case kDesktopNotificationClick:
|
||||
case kDesktopNotificationClose:
|
||||
this.handleNotificationEvent(detail);
|
||||
break;
|
||||
default:
|
||||
debug("FIXME: Unhandled notification event: " + detail.type);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleNotificationEvent: function(detail) {
|
||||
if (!detail || !detail.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let uid = detail.id;
|
||||
let listener = this._listeners[uid];
|
||||
if (!listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
let topic;
|
||||
if (detail.type === kDesktopNotificationClick) {
|
||||
topic = kTopicAlertClickCallback;
|
||||
} else if (detail.type === kDesktopNotificationShow) {
|
||||
topic = kTopicAlertShow;
|
||||
} else {
|
||||
/* kDesktopNotificationClose */
|
||||
topic = kTopicAlertFinished;
|
||||
}
|
||||
|
||||
if (listener.cookie) {
|
||||
try {
|
||||
listener.observer.observe(null, topic, listener.cookie);
|
||||
} catch (e) { }
|
||||
} else {
|
||||
try {
|
||||
listener.mm.sendAsyncMessage(kMessageAppNotificationReturn, {
|
||||
uid: uid,
|
||||
topic: topic,
|
||||
target: listener.target
|
||||
});
|
||||
} catch (e) {
|
||||
// we get an exception if the app is not launched yet
|
||||
gSystemMessenger.sendMessage(kNotificationSystemMessageName, {
|
||||
clicked: (detail.type === kDesktopNotificationClick),
|
||||
title: listener.title,
|
||||
body: listener.text,
|
||||
imageURL: listener.imageURL,
|
||||
lang: listener.lang,
|
||||
dir: listener.dir,
|
||||
id: listener.id,
|
||||
tag: listener.tag
|
||||
},
|
||||
Services.io.newURI(listener.target, null, null),
|
||||
Services.io.newURI(listener.manifestURL, null, null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// we"re done with this notification
|
||||
if (topic === kTopicAlertFinished) {
|
||||
delete this._listeners[uid];
|
||||
}
|
||||
},
|
||||
|
||||
registerListener: function(alertId, cookie, alertListener) {
|
||||
this._listeners[alertId] = { observer: alertListener, cookie: cookie };
|
||||
},
|
||||
|
||||
registerAppListener: function(uid, listener) {
|
||||
this._listeners[uid] = listener;
|
||||
|
||||
appsService.getManifestFor(listener.manifestURL).then((manifest) => {
|
||||
let helper = new ManifestHelper(manifest, listener.manifestURL);
|
||||
let getNotificationURLFor = function(messages) {
|
||||
if (!messages) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
let message = messages[i];
|
||||
if (message === kNotificationSystemMessageName) {
|
||||
return helper.fullLaunchPath();
|
||||
} else if (typeof message === "object" &&
|
||||
kNotificationSystemMessageName in message) {
|
||||
return
|
||||
helper.resolveFromOrigin(message[kNotificationSystemMessageName]);
|
||||
}
|
||||
}
|
||||
|
||||
// No message found...
|
||||
return null;
|
||||
}
|
||||
|
||||
listener.target = getNotificationURLFor(manifest.messages);
|
||||
|
||||
// Bug 816944 - Support notification messages for entry_points.
|
||||
});
|
||||
},
|
||||
|
||||
showNotification: function(imageURL, title, text, textClickable, cookie,
|
||||
uid, bidi, lang, manifestURL) {
|
||||
function send(appName, appIcon) {
|
||||
SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, {
|
||||
type: kDesktopNotification,
|
||||
id: uid,
|
||||
icon: imageURL,
|
||||
title: title,
|
||||
text: text,
|
||||
bidi: bidi,
|
||||
lang: lang,
|
||||
appName: appName,
|
||||
appIcon: appIcon,
|
||||
manifestURL: manifestURL
|
||||
});
|
||||
}
|
||||
|
||||
if (!manifestURL || !manifestURL.length) {
|
||||
send(null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a manifest URL, get the icon and title from the manifest
|
||||
// to prevent spoofing.
|
||||
appsService.getManifestFor(manifestURL).then((manifest) => {
|
||||
let helper = new ManifestHelper(manifest, manifestURL);
|
||||
send(helper.name, helper.iconURLForSize(kNotificationIconSize));
|
||||
});
|
||||
},
|
||||
|
||||
showAlertNotification: function(aMessage) {
|
||||
let data = aMessage.data;
|
||||
let currentListener = this._listeners[data.name];
|
||||
if (currentListener && currentListener.observer) {
|
||||
currentListener.observer.observe(null, kTopicAlertFinished, currentListener.cookie);
|
||||
}
|
||||
|
||||
this.registerListener(data.name, data.cookie, data.alertListener);
|
||||
this.showNotification(data.imageURL, data.title, data.text,
|
||||
data.textClickable, data.cookie, data.name, data.bidi,
|
||||
data.lang, null);
|
||||
},
|
||||
|
||||
showAppNotification: function(aMessage) {
|
||||
let data = aMessage.data;
|
||||
let details = data.details;
|
||||
let listener = {
|
||||
mm: aMessage.target,
|
||||
title: data.title,
|
||||
text: data.text,
|
||||
manifestURL: details.manifestURL,
|
||||
imageURL: data.imageURL,
|
||||
lang: details.lang || undefined,
|
||||
id: details.id || undefined,
|
||||
dir: details.dir || undefined,
|
||||
tag: details.tag || undefined
|
||||
};
|
||||
this.registerAppListener(data.uid, listener);
|
||||
this.showNotification(data.imageURL, data.title, data.text,
|
||||
details.textClickable, null, data.uid, details.dir,
|
||||
details.lang, details.manifestURL);
|
||||
},
|
||||
|
||||
closeAlert: function(name) {
|
||||
SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, {
|
||||
type: kDesktopNotificationClose,
|
||||
id: name
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (!aMessage.target.assertAppHasPermission(kDesktopNotificationPerm)) {
|
||||
Cu.reportError("Desktop-notification message " + aMessage.name +
|
||||
" from a content process with no " + kDesktopNotificationPerm +
|
||||
" privileges.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(aMessage.name) {
|
||||
case kMessageAppNotificationSend:
|
||||
this.showAppNotification(aMessage);
|
||||
break;
|
||||
|
||||
case kMessageAlertNotificationSend:
|
||||
this.showAlertNotification(aMessage);
|
||||
break;
|
||||
|
||||
case kMessageAlertNotificationClose:
|
||||
this.closeAlert(aMessage.data.name);
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
AlertsHelper.init();
|
|
@ -35,43 +35,61 @@ function debug(str) {
|
|||
// Alerts Service
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
const kNotificationSystemMessageName = "notification";
|
||||
|
||||
const kMessageAppNotificationSend = "app-notification-send";
|
||||
const kMessageAppNotificationReturn = "app-notification-return";
|
||||
const kMessageAlertNotificationSend = "alert-notification-send";
|
||||
const kMessageAlertNotificationClose = "alert-notification-close";
|
||||
|
||||
const kTopicAlertFinished = "alertfinished";
|
||||
|
||||
function AlertsService() {
|
||||
cpmm.addMessageListener("app-notification-return", this);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
cpmm.addMessageListener(kMessageAppNotificationReturn, this);
|
||||
}
|
||||
|
||||
AlertsService.prototype = {
|
||||
classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService,
|
||||
Ci.nsIAppNotificationService]),
|
||||
Ci.nsIAppNotificationService,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
cpmm.removeMessageListener(kMessageAppNotificationReturn, this);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIAlertsService
|
||||
showAlertNotification: function showAlertNotification(aImageUrl,
|
||||
aTitle,
|
||||
aText,
|
||||
aTextClickable,
|
||||
aCookie,
|
||||
aAlertListener,
|
||||
aName,
|
||||
aBidi,
|
||||
aLang) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText,
|
||||
aTextClickable, aCookie,
|
||||
aAlertListener, aName, aBidi,
|
||||
aLang);
|
||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
||||
aCookie, aAlertListener, aName, aBidi,
|
||||
aLang) {
|
||||
cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
|
||||
imageURL: aImageUrl,
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
clickable: aTextClickable,
|
||||
cookie: aCookie,
|
||||
listener: aAlertListener,
|
||||
id: aName,
|
||||
dir: aBidi,
|
||||
lang: aLang
|
||||
});
|
||||
},
|
||||
|
||||
closeAlert: function(aName) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browser.AlertsHelper.closeAlert(aName);
|
||||
cpmm.sendAsyncMessage(kMessageAlertNotificationClose, {
|
||||
name: aName
|
||||
});
|
||||
},
|
||||
|
||||
// nsIAppNotificationService
|
||||
showAppNotification: function showAppNotification(aImageURL,
|
||||
aTitle,
|
||||
aText,
|
||||
aAlertListener,
|
||||
aDetails) {
|
||||
showAppNotification: function(aImageURL, aTitle, aText, aAlertListener,
|
||||
aDetails) {
|
||||
let uid = (aDetails.id == "") ?
|
||||
"app-notif-" + uuidGenerator.generateUUID() : aDetails.id;
|
||||
|
||||
|
@ -88,7 +106,7 @@ AlertsService.prototype = {
|
|||
tag: aDetails.tag || undefined
|
||||
};
|
||||
|
||||
cpmm.sendAsyncMessage("app-notification-send", {
|
||||
cpmm.sendAsyncMessage(kMessageAppNotificationSend, {
|
||||
imageURL: aImageURL,
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
|
@ -100,10 +118,10 @@ AlertsService.prototype = {
|
|||
// AlertsService.js custom implementation
|
||||
_listeners: [],
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
receiveMessage: function(aMessage) {
|
||||
let data = aMessage.data;
|
||||
let listener = this._listeners[data.uid];
|
||||
if (aMessage.name !== "app-notification-return" || !listener) {
|
||||
if (aMessage.name !== kMessageAppNotificationReturn || !listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -116,7 +134,7 @@ AlertsService.prototype = {
|
|||
// notification via a system message containing the title/text/icon of
|
||||
// the notification so the app get a change to react.
|
||||
if (data.target) {
|
||||
gSystemMessenger.sendMessage("notification", {
|
||||
gSystemMessenger.sendMessage(kNotificationSystemMessageName, {
|
||||
title: listener.title,
|
||||
body: listener.text,
|
||||
imageURL: listener.imageURL,
|
||||
|
@ -127,12 +145,13 @@ AlertsService.prototype = {
|
|||
dbId: listener.dbId
|
||||
},
|
||||
Services.io.newURI(data.target, null, null),
|
||||
Services.io.newURI(listener.manifestURL, null, null));
|
||||
Services.io.newURI(listener.manifestURL, null, null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// we're done with this notification
|
||||
if (topic === "alertfinished") {
|
||||
if (topic === kTopicAlertFinished) {
|
||||
if (listener.dbId) {
|
||||
notificationStorage.delete(listener.manifestURL, listener.dbId);
|
||||
}
|
||||
|
|
|
@ -48,20 +48,16 @@ this.FxAccountsMgmtService = {
|
|||
},
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "content-start", false);
|
||||
Services.obs.addObserver(this, ONLOGIN_NOTIFICATION, false);
|
||||
Services.obs.addObserver(this, ONVERIFIED_NOTIFICATION, false);
|
||||
Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION, false);
|
||||
SystemAppProxy.addEventListener("mozFxAccountsContentEvent",
|
||||
FxAccountsMgmtService);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
log.debug("Observed " + aTopic);
|
||||
switch (aTopic) {
|
||||
case "content-start":
|
||||
SystemAppProxy.addEventListener("mozFxAccountsContentEvent",
|
||||
FxAccountsMgmtService);
|
||||
Services.obs.removeObserver(this, "content-start");
|
||||
break;
|
||||
case ONLOGIN_NOTIFICATION:
|
||||
case ONVERIFIED_NOTIFICATION:
|
||||
case ONLOGOUT_NOTIFICATION:
|
||||
|
|
|
@ -41,6 +41,7 @@ if CONFIG['MOZ_UPDATER']:
|
|||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AlertsHelper.jsm',
|
||||
'ErrorPage.jsm',
|
||||
'SignInToWebsite.jsm',
|
||||
'SystemAppProxy.jsm',
|
||||
|
|
|
@ -52,11 +52,12 @@ function init(aEvent)
|
|||
#ifdef MOZ_UPDATER
|
||||
gAppUpdater = new appUpdater();
|
||||
|
||||
#if MOZ_UPDATE_CHANNEL != release
|
||||
let defaults = Services.prefs.getDefaultBranch("");
|
||||
let channelLabel = document.getElementById("currentChannel");
|
||||
let currentChannelText = document.getElementById("currentChannelText");
|
||||
channelLabel.value = defaults.getCharPref("app.update.channel");
|
||||
#endif
|
||||
if (channelLabel.value == "release")
|
||||
currentChannelText.hidden = true;
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -108,12 +108,10 @@
|
|||
#endif
|
||||
</vbox>
|
||||
|
||||
#if MOZ_UPDATE_CHANNEL != release
|
||||
#ifdef MOZ_UPDATER
|
||||
<description class="text-blurb" id="currentChannelText">
|
||||
&channel.description.start;<label id="currentChannel"/>&channel.description.end;
|
||||
</description>
|
||||
#endif
|
||||
#endif
|
||||
<vbox id="experimental" hidden="true">
|
||||
<description class="text-blurb" id="warningDesc">
|
||||
|
|
|
@ -6352,6 +6352,7 @@ MOZ_ARG_DISABLE_BOOL(tests,
|
|||
|
||||
if test -n "$ENABLE_TESTS"; then
|
||||
GTEST_HAS_RTTI=0
|
||||
AC_DEFINE(ENABLE_TESTS)
|
||||
AC_DEFINE_UNQUOTED(GTEST_HAS_RTTI, 0)
|
||||
AC_SUBST(GTEST_HAS_RTTI)
|
||||
if test -n "$_WIN32_MSVC"; then
|
||||
|
|
|
@ -1490,13 +1490,7 @@ CanvasRenderingContext2D::CreatePattern(const HTMLImageOrCanvasOrVideoElement& e
|
|||
return pat.forget();
|
||||
}
|
||||
} else if (element.IsHTMLImageElement()) {
|
||||
HTMLImageElement* img = &element.GetAsHTMLImageElement();
|
||||
if (img->IntrinsicState().HasState(NS_EVENT_STATE_BROKEN)) {
|
||||
error.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
htmlElement = img;
|
||||
htmlElement = &element.GetAsHTMLImageElement();
|
||||
} else {
|
||||
htmlElement = &element.GetAsHTMLVideoElement();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "GLContext.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLProgram.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
|
@ -630,7 +631,7 @@ WebGLContext::BindFakeBlackTexturesHelper(
|
|||
}
|
||||
|
||||
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
|
||||
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().InternalFormat());
|
||||
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().WebGLFormat());
|
||||
ScopedDeletePtr<FakeBlackTexture>&
|
||||
blackTexturePtr = alpha
|
||||
? transparentTextureScopedPtr
|
||||
|
|
|
@ -53,7 +53,6 @@ using namespace mozilla::gl;
|
|||
using namespace mozilla::gfx;
|
||||
|
||||
static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
|
||||
static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLContext::CurValidFBRectObject() const
|
||||
|
@ -453,12 +452,13 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
|||
|
||||
// copyTexImage2D only generates textures with type = UNSIGNED_BYTE
|
||||
const WebGLTexImageFunc func = WebGLTexImageFunc::CopyTexImage;
|
||||
GLenum type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
const GLenum format = internalformat; // WebGL/ES Format
|
||||
const GLenum type = LOCAL_GL_UNSIGNED_BYTE; // WebGL/ES Format
|
||||
|
||||
if (!ValidateTexImage(2, target, level, internalformat,
|
||||
if (!ValidateTexImage(2, target, level, format,
|
||||
0, 0, 0,
|
||||
width, height, 0,
|
||||
border, internalformat, type,
|
||||
border, format, type,
|
||||
func))
|
||||
{
|
||||
return;
|
||||
|
@ -477,9 +477,9 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
|||
ClearBackbufferIfNeeded();
|
||||
}
|
||||
|
||||
bool texFormatRequiresAlpha = internalformat == LOCAL_GL_RGBA ||
|
||||
internalformat == LOCAL_GL_ALPHA ||
|
||||
internalformat == LOCAL_GL_LUMINANCE_ALPHA;
|
||||
bool texFormatRequiresAlpha = format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA;
|
||||
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
|
||||
: bool(gl->GetPixelFormat().alpha > 0);
|
||||
if (texFormatRequiresAlpha && !fboFormatHasAlpha)
|
||||
|
@ -494,14 +494,14 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
|||
|
||||
sizeMayChange = width != imageInfo.Width() ||
|
||||
height != imageInfo.Height() ||
|
||||
internalformat != imageInfo.InternalFormat() ||
|
||||
type != imageInfo.Type();
|
||||
format != imageInfo.WebGLFormat() ||
|
||||
type != imageInfo.WebGLType();
|
||||
}
|
||||
|
||||
if (sizeMayChange)
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
|
||||
CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
|
||||
CopyTexSubImage2D_base(target, level, format, 0, 0, x, y, width, height, false);
|
||||
|
||||
if (sizeMayChange) {
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
|
@ -511,7 +511,7 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
|||
}
|
||||
}
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, type,
|
||||
tex->SetImageInfo(target, level, width, height, format, type,
|
||||
WebGLImageDataStatus::InitializedImageData);
|
||||
}
|
||||
|
||||
|
@ -571,12 +571,9 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||
if (yoffset + height > texHeight || yoffset + height < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
|
||||
|
||||
GLenum internalFormat = imageInfo.InternalFormat();
|
||||
if (IsGLDepthFormat(internalFormat) ||
|
||||
IsGLDepthStencilFormat(internalFormat))
|
||||
{
|
||||
GLenum webGLFormat = imageInfo.WebGLFormat();
|
||||
if (IsGLDepthFormat(webGLFormat) || IsGLDepthStencilFormat(webGLFormat))
|
||||
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
|
||||
}
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
|
@ -591,9 +588,7 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||
ClearBackbufferIfNeeded();
|
||||
}
|
||||
|
||||
bool texFormatRequiresAlpha = (internalFormat == LOCAL_GL_RGBA ||
|
||||
internalFormat == LOCAL_GL_ALPHA ||
|
||||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA);
|
||||
bool texFormatRequiresAlpha = FormatHasAlpha(webGLFormat);
|
||||
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
|
||||
: bool(gl->GetPixelFormat().alpha > 0);
|
||||
|
||||
|
@ -605,7 +600,7 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
return CopyTexSubImage2D_base(target, level, internalFormat, xoffset, yoffset, x, y, width, height, true);
|
||||
return CopyTexSubImage2D_base(target, level, webGLFormat, xoffset, yoffset, x, y, width, height, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -900,12 +895,12 @@ WebGLContext::GenerateMipmap(GLenum target)
|
|||
if (!tex->IsFirstImagePowerOfTwo())
|
||||
return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
|
||||
|
||||
GLenum internalFormat = tex->ImageInfoAt(imageTarget, 0).InternalFormat();
|
||||
if (IsTextureFormatCompressed(internalFormat))
|
||||
GLenum webGLFormat = tex->ImageInfoAt(imageTarget, 0).WebGLFormat();
|
||||
if (IsTextureFormatCompressed(webGLFormat))
|
||||
return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
|
||||
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
|
||||
(IsGLDepthFormat(internalFormat) || IsGLDepthStencilFormat(internalFormat)))
|
||||
(IsGLDepthFormat(webGLFormat) || IsGLDepthStencilFormat(webGLFormat)))
|
||||
{
|
||||
return ErrorInvalidOperation("generateMipmap: "
|
||||
"A texture that has a base internal format of "
|
||||
|
@ -1177,11 +1172,11 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
|||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
|
||||
const GLenum internalFormat =
|
||||
fba.Texture()->ImageInfoBase().InternalFormat();
|
||||
return (internalFormat == LOCAL_GL_SRGB_EXT ||
|
||||
internalFormat == LOCAL_GL_SRGB_ALPHA_EXT) ?
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
|
||||
const GLenum webGLFormat =
|
||||
fba.Texture()->ImageInfoBase().WebGLFormat();
|
||||
return (webGLFormat == LOCAL_GL_SRGB ||
|
||||
webGLFormat == LOCAL_GL_SRGB_ALPHA) ?
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_SRGB)) :
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
|
||||
}
|
||||
break;
|
||||
|
@ -1220,7 +1215,7 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
|||
|
||||
uint32_t ret = LOCAL_GL_NONE;
|
||||
GLenum type = fba.Texture()->ImageInfoAt(fba.TexImageTarget(),
|
||||
fba.TexImageLevel()).Type();
|
||||
fba.TexImageLevel()).WebGLType();
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
|
@ -3523,6 +3518,7 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
|||
GLenum type,
|
||||
const GLvoid *data)
|
||||
{
|
||||
MOZ_ASSERT(internalFormat == format);
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
MOZ_ASSERT(tex != nullptr, "no texture bound");
|
||||
|
||||
|
@ -3532,28 +3528,28 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
|||
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(target, level);
|
||||
sizeMayChange = width != imageInfo.Width() ||
|
||||
height != imageInfo.Height() ||
|
||||
format != imageInfo.InternalFormat() ||
|
||||
type != imageInfo.Type();
|
||||
format != imageInfo.WebGLFormat() ||
|
||||
type != imageInfo.WebGLType();
|
||||
}
|
||||
|
||||
// convert type for half float if not on GLES2
|
||||
GLenum realType = type;
|
||||
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES()) {
|
||||
realType = LOCAL_GL_HALF_FLOAT;
|
||||
}
|
||||
// Convert to format and type required by OpenGL 'driver'.
|
||||
GLenum driverType = DriverTypeFromType(gl, type);
|
||||
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||
GLenum driverFormat = LOCAL_GL_NONE;
|
||||
DriverFormatsFromFormatAndType(gl, format, type, &driverInternalFormat, &driverFormat);
|
||||
|
||||
if (sizeMayChange) {
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
|
||||
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
|
||||
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
return error;
|
||||
}
|
||||
|
||||
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
|
||||
gl->fTexImage2D(target, level, driverInternalFormat, width, height, border, driverFormat, driverType, data);
|
||||
|
||||
return LOCAL_GL_NO_ERROR;
|
||||
GLenum error = LOCAL_GL_NO_ERROR;
|
||||
if (sizeMayChange) {
|
||||
error = GetAndFlushUnderlyingGLErrors();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3561,7 +3557,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
|
||||
GLint border,
|
||||
GLenum format, GLenum type,
|
||||
void *data, uint32_t byteLength,
|
||||
void* data, uint32_t byteLength,
|
||||
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied)
|
||||
{
|
||||
|
@ -3598,7 +3594,6 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
|
||||
|
||||
CheckedUint32 checked_alignedRowSize =
|
||||
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
|
||||
|
||||
|
@ -3618,38 +3613,16 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
// Handle ES2 and GL differences in floating point internal formats. Note that
|
||||
// format == internalformat, as checked above and as required by ES.
|
||||
internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES());
|
||||
|
||||
// Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
|
||||
// requires that format == internalformat, but GL will fail in this case.
|
||||
// GL requires:
|
||||
// format -> internalformat
|
||||
// GL_RGB GL_SRGB_EXT
|
||||
// GL_RGBA GL_SRGB_ALPHA_EXT
|
||||
if (!gl->IsGLES()) {
|
||||
switch (internalformat) {
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
format = LOCAL_GL_RGB;
|
||||
break;
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
format = LOCAL_GL_RGBA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum error = LOCAL_GL_NO_ERROR;
|
||||
|
||||
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::NoImageData;
|
||||
nsAutoArrayPtr<uint8_t> convertedData;
|
||||
void* pixels = nullptr;
|
||||
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
|
||||
|
||||
if (byteLength) {
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
uint32_t dstTexelSize = GetBitsPerTexel(format, type) / 8;
|
||||
size_t dstPlainRowSize = dstTexelSize * width;
|
||||
size_t unpackAlignment = mPixelStoreUnpackAlignment;
|
||||
size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
|
||||
size_t dstPlainRowSize = dstTexelSize * width;
|
||||
size_t unpackAlignment = mPixelStoreUnpackAlignment;
|
||||
size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
|
||||
|
||||
if (actualSrcFormat == dstFormat &&
|
||||
srcPremultiplied == mPixelStorePremultiplyAlpha &&
|
||||
|
@ -3657,27 +3630,24 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
!mPixelStoreFlipY)
|
||||
{
|
||||
// no conversion, no flipping, so we avoid copying anything and just pass the source pointer
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, data);
|
||||
pixels = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t convertedDataSize = height * dstStride;
|
||||
nsAutoArrayPtr<uint8_t> convertedData(new uint8_t[convertedDataSize]);
|
||||
convertedData = new uint8_t[convertedDataSize];
|
||||
ConvertImage(width, height, srcStride, dstStride,
|
||||
static_cast<uint8_t*>(data), convertedData,
|
||||
actualSrcFormat, srcPremultiplied,
|
||||
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, convertedData);
|
||||
pixels = reinterpret_cast<void*>(convertedData.get());
|
||||
}
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::InitializedImageData;
|
||||
} else {
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, nullptr);
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
|
||||
GLenum error = CheckedTexImage2D(target, level, internalformat, width,
|
||||
height, border, format, type, pixels);
|
||||
|
||||
if (error) {
|
||||
GenerateWarning("texImage2D generated error %s", ErrorName(error));
|
||||
return;
|
||||
|
@ -3688,7 +3658,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
// have NoImageData at this point.
|
||||
MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, type, imageInfoStatusIfSuccess);
|
||||
tex->SetImageInfo(target, level, width, height, format, type, imageInfoStatusIfSuccess);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3733,7 +3703,7 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
|||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
|
||||
GLenum format, GLenum type,
|
||||
void *pixels, uint32_t byteLength,
|
||||
void* data, uint32_t byteLength,
|
||||
int jsArrayType,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied)
|
||||
{
|
||||
|
@ -3782,42 +3752,37 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
uint32_t dstTexelSize = GetBitsPerTexel(format, type) / 8;
|
||||
size_t dstPlainRowSize = dstTexelSize * width;
|
||||
size_t dstPlainRowSize = dstTexelSize * width;
|
||||
// There are checks above to ensure that this won't overflow.
|
||||
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
|
||||
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
|
||||
|
||||
// convert type for half float if not on GLES2
|
||||
GLenum realType = type;
|
||||
if (realType == LOCAL_GL_HALF_FLOAT_OES) {
|
||||
if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
|
||||
realType = LOCAL_GL_HALF_FLOAT;
|
||||
} else {
|
||||
MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
|
||||
}
|
||||
}
|
||||
void* pixels = data;
|
||||
nsAutoArrayPtr<uint8_t> convertedData;
|
||||
|
||||
if (actualSrcFormat == dstFormat &&
|
||||
srcPremultiplied == mPixelStorePremultiplyAlpha &&
|
||||
srcStride == dstStride &&
|
||||
!mPixelStoreFlipY)
|
||||
{
|
||||
// no conversion, no flipping, so we avoid copying anything and just pass the source pointer
|
||||
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, realType, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no conversion, no flipping, so we avoid copying anything and just pass the source pointer
|
||||
bool noConversion = (actualSrcFormat == dstFormat &&
|
||||
srcPremultiplied == mPixelStorePremultiplyAlpha &&
|
||||
srcStride == dstStride &&
|
||||
!mPixelStoreFlipY);
|
||||
|
||||
if (!noConversion) {
|
||||
size_t convertedDataSize = height * dstStride;
|
||||
nsAutoArrayPtr<uint8_t> convertedData(new uint8_t[convertedDataSize]);
|
||||
convertedData = new uint8_t[convertedDataSize];
|
||||
ConvertImage(width, height, srcStride, dstStride,
|
||||
static_cast<const uint8_t*>(pixels), convertedData,
|
||||
static_cast<const uint8_t*>(data), convertedData,
|
||||
actualSrcFormat, srcPremultiplied,
|
||||
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
|
||||
|
||||
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, realType, convertedData);
|
||||
pixels = reinterpret_cast<void*>(convertedData.get());
|
||||
}
|
||||
|
||||
GLenum driverType = DriverTypeFromType(gl, type);
|
||||
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||
GLenum driverFormat = LOCAL_GL_NONE;
|
||||
DriverFormatsFromFormatAndType(gl, format, type, &driverInternalFormat, &driverFormat);
|
||||
|
||||
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, driverFormat, driverType, pixels);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4071,72 +4036,6 @@ WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum internalformat, GLenum type
|
|||
MOZ_CRASH("Invalid WebGL texture format/type?");
|
||||
}
|
||||
|
||||
GLenum
|
||||
InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2)
|
||||
{
|
||||
// ES2 requires that format == internalformat; floating-point is
|
||||
// indicated purely by the type that's loaded. For desktop GL, we
|
||||
// have to specify a floating point internal format.
|
||||
if (isGLES2)
|
||||
return format;
|
||||
|
||||
if (format == LOCAL_GL_DEPTH_COMPONENT) {
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT)
|
||||
return LOCAL_GL_DEPTH_COMPONENT16;
|
||||
else if (type == LOCAL_GL_UNSIGNED_INT)
|
||||
return LOCAL_GL_DEPTH_COMPONENT32;
|
||||
}
|
||||
|
||||
if (format == LOCAL_GL_DEPTH_STENCIL) {
|
||||
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
|
||||
return LOCAL_GL_DEPTH24_STENCIL8;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
return format;
|
||||
|
||||
case LOCAL_GL_FLOAT:
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
return LOCAL_GL_RGBA32F_ARB;
|
||||
case LOCAL_GL_RGB:
|
||||
return LOCAL_GL_RGB32F_ARB;
|
||||
case LOCAL_GL_ALPHA:
|
||||
return LOCAL_GL_ALPHA32F_ARB;
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
return LOCAL_GL_LUMINANCE32F_ARB;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
return LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_HALF_FLOAT_OES:
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
return LOCAL_GL_RGBA16F;
|
||||
case LOCAL_GL_RGB:
|
||||
return LOCAL_GL_RGB16F;
|
||||
case LOCAL_GL_ALPHA:
|
||||
return LOCAL_GL_ALPHA16F_ARB;
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
return LOCAL_GL_LUMINANCE16F_ARB;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
return LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ASSERTION(false, "Coding mistake -- bad format/type passed?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
|
||||
if (IsContextLost())
|
||||
|
|
|
@ -25,19 +25,172 @@ using namespace mozilla;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gl;
|
||||
|
||||
bool
|
||||
IsGLDepthFormat(GLenum internalFormat)
|
||||
IsGLDepthFormat(GLenum webGLFormat)
|
||||
{
|
||||
return (internalFormat == LOCAL_GL_DEPTH_COMPONENT ||
|
||||
internalFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
|
||||
internalFormat == LOCAL_GL_DEPTH_COMPONENT32);
|
||||
return (webGLFormat == LOCAL_GL_DEPTH_COMPONENT ||
|
||||
webGLFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
|
||||
webGLFormat == LOCAL_GL_DEPTH_COMPONENT32);
|
||||
}
|
||||
|
||||
bool
|
||||
IsGLDepthStencilFormat(GLenum internalFormat)
|
||||
IsGLDepthStencilFormat(GLenum webGLFormat)
|
||||
{
|
||||
return (internalFormat == LOCAL_GL_DEPTH_STENCIL ||
|
||||
internalFormat == LOCAL_GL_DEPTH24_STENCIL8);
|
||||
return (webGLFormat == LOCAL_GL_DEPTH_STENCIL ||
|
||||
webGLFormat == LOCAL_GL_DEPTH24_STENCIL8);
|
||||
}
|
||||
|
||||
bool
|
||||
FormatHasAlpha(GLenum webGLFormat)
|
||||
{
|
||||
return webGLFormat == LOCAL_GL_RGBA ||
|
||||
webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
webGLFormat == LOCAL_GL_ALPHA ||
|
||||
webGLFormat == LOCAL_GL_RGBA4 ||
|
||||
webGLFormat == LOCAL_GL_RGB5_A1 ||
|
||||
webGLFormat == LOCAL_GL_SRGB_ALPHA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert WebGL/ES format and type into GL format and GL internal
|
||||
* format valid for underlying driver.
|
||||
*/
|
||||
void
|
||||
DriverFormatsFromFormatAndType(GLContext* gl, GLenum webGLFormat, GLenum webGLType,
|
||||
GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
|
||||
{
|
||||
MOZ_ASSERT(out_driverInternalFormat, "out_driverInternalFormat can't be nullptr.");
|
||||
MOZ_ASSERT(out_driverFormat, "out_driverFormat can't be nullptr.");
|
||||
if (!out_driverInternalFormat || !out_driverFormat)
|
||||
return;
|
||||
|
||||
// ES2 requires that format == internalformat; floating-point is
|
||||
// indicated purely by the type that's loaded. For desktop GL, we
|
||||
// have to specify a floating point internal format.
|
||||
if (gl->IsGLES()) {
|
||||
*out_driverInternalFormat = webGLFormat;
|
||||
*out_driverFormat = webGLFormat;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum format = webGLFormat;
|
||||
GLenum internalFormat = LOCAL_GL_NONE;
|
||||
|
||||
if (format == LOCAL_GL_DEPTH_COMPONENT) {
|
||||
if (webGLType == LOCAL_GL_UNSIGNED_SHORT)
|
||||
internalFormat = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
else if (webGLType == LOCAL_GL_UNSIGNED_INT)
|
||||
internalFormat = LOCAL_GL_DEPTH_COMPONENT32;
|
||||
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
|
||||
if (webGLType == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
|
||||
internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
} else {
|
||||
switch (webGLType) {
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
internalFormat = format;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_FLOAT:
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
internalFormat = LOCAL_GL_RGBA32F;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_RGB:
|
||||
internalFormat = LOCAL_GL_RGB32F;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_ALPHA:
|
||||
internalFormat = LOCAL_GL_ALPHA32F_ARB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_HALF_FLOAT_OES:
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
internalFormat = LOCAL_GL_RGBA16F;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_RGB:
|
||||
internalFormat = LOCAL_GL_RGB16F;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_ALPHA:
|
||||
internalFormat = LOCAL_GL_ALPHA16F_ARB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
|
||||
// requires that format == internalformat, but GL will fail in this case.
|
||||
// GL requires:
|
||||
// format -> internalformat
|
||||
// GL_RGB GL_SRGB_EXT
|
||||
// GL_RGBA GL_SRGB_ALPHA_EXT
|
||||
switch (format) {
|
||||
case LOCAL_GL_SRGB:
|
||||
internalFormat = format;
|
||||
format = LOCAL_GL_RGB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_SRGB_ALPHA:
|
||||
internalFormat = format;
|
||||
format = LOCAL_GL_RGBA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(format != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
|
||||
"Coding mistake -- bad format/type passed?");
|
||||
|
||||
*out_driverInternalFormat = internalFormat;
|
||||
*out_driverFormat = format;
|
||||
}
|
||||
|
||||
GLenum
|
||||
DriverTypeFromType(GLContext* gl, GLenum webGLType)
|
||||
{
|
||||
if (gl->IsGLES())
|
||||
return webGLType;
|
||||
|
||||
// convert type for half float if not on GLES2
|
||||
GLenum type = webGLType;
|
||||
if (type == LOCAL_GL_HALF_FLOAT_OES) {
|
||||
if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
|
||||
return LOCAL_GL_HALF_FLOAT;
|
||||
} else {
|
||||
MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
|
||||
}
|
||||
}
|
||||
|
||||
return webGLType;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -12,8 +12,12 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
bool IsGLDepthFormat(GLenum internalFormat);
|
||||
bool IsGLDepthStencilFormat(GLenum internalFormat);
|
||||
bool IsGLDepthFormat(GLenum webGLFormat);
|
||||
bool IsGLDepthStencilFormat(GLenum webGLFormat);
|
||||
bool FormatHasAlpha(GLenum webGLFormat);
|
||||
void DriverFormatsFromFormatAndType(gl::GLContext* gl, GLenum webGLFormat, GLenum webGLType,
|
||||
GLenum* out_driverInternalFormat, GLenum* out_driverFormat);
|
||||
GLenum DriverTypeFromType(gl::GLContext* gl, GLenum webGLType);
|
||||
|
||||
template <typename WebGLObjectType>
|
||||
JS::Value
|
||||
|
|
|
@ -1389,8 +1389,8 @@ WebGLContext::ValidateTexImage(GLuint dims, GLenum target,
|
|||
/* Require the format and type to match that of the existing
|
||||
* texture as created
|
||||
*/
|
||||
if (imageInfo.InternalFormat() != format ||
|
||||
imageInfo.Type() != type)
|
||||
if (imageInfo.WebGLFormat() != format ||
|
||||
imageInfo.WebGLType() != type)
|
||||
{
|
||||
ErrorInvalidOperation("%s: format or type doesn't match the existing texture",
|
||||
info);
|
||||
|
|
|
@ -55,7 +55,7 @@ WebGLFramebuffer::Attachment::HasAlpha() const
|
|||
|
||||
GLenum format = 0;
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).InternalFormat();
|
||||
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
|
||||
else if (Renderbuffer())
|
||||
format = Renderbuffer()->InternalFormat();
|
||||
return FormatHasAlpha(format);
|
||||
|
@ -65,7 +65,7 @@ bool
|
|||
WebGLFramebuffer::Attachment::IsReadableFloat() const
|
||||
{
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
|
||||
GLenum type = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Type();
|
||||
GLenum type = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
|
||||
switch (type) {
|
||||
case LOCAL_GL_FLOAT:
|
||||
case LOCAL_GL_HALF_FLOAT_OES:
|
||||
|
@ -282,19 +282,19 @@ WebGLFramebuffer::Attachment::IsComplete() const
|
|||
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
||||
const WebGLTexture::ImageInfo& imageInfo =
|
||||
Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
|
||||
GLenum internalFormat = imageInfo.InternalFormat();
|
||||
GLenum webGLFormat = imageInfo.WebGLFormat();
|
||||
|
||||
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
|
||||
return IsValidFBOTextureDepthFormat(internalFormat);
|
||||
return IsValidFBOTextureDepthFormat(webGLFormat);
|
||||
|
||||
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
||||
return IsValidFBOTextureDepthStencilFormat(internalFormat);
|
||||
return IsValidFBOTextureDepthStencilFormat(webGLFormat);
|
||||
|
||||
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
|
||||
WebGLContext::kMaxColorAttachments))
|
||||
{
|
||||
return IsValidFBOTextureColorFormat(internalFormat);
|
||||
return IsValidFBOTextureColorFormat(webGLFormat);
|
||||
}
|
||||
MOZ_ASSERT(false, "Invalid WebGL attachment point?");
|
||||
return false;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/Scoped.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLTexelConversions.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -52,7 +53,7 @@ int64_t
|
|||
WebGLTexture::ImageInfo::MemoryUsage() const {
|
||||
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
|
||||
return 0;
|
||||
int64_t bitsPerTexel = WebGLContext::GetBitsPerTexel(mInternalFormat, mType);
|
||||
int64_t bitsPerTexel = WebGLContext::GetBitsPerTexel(mWebGLFormat, mWebGLType);
|
||||
return int64_t(mWidth) * int64_t(mHeight) * bitsPerTexel/8;
|
||||
}
|
||||
|
||||
|
@ -336,7 +337,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
|
||||
if (ImageInfoBase().mWebGLType == LOCAL_GL_FLOAT &&
|
||||
!Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_float_linear))
|
||||
{
|
||||
if (mMinFilter == LOCAL_GL_LINEAR ||
|
||||
|
@ -356,7 +357,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
|||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
} else if (ImageInfoBase().mType == LOCAL_GL_HALF_FLOAT_OES &&
|
||||
} else if (ImageInfoBase().mWebGLType == LOCAL_GL_HALF_FLOAT_OES &&
|
||||
!Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float_linear))
|
||||
{
|
||||
if (mMinFilter == LOCAL_GL_LINEAR ||
|
||||
|
@ -543,8 +544,9 @@ WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
|
|||
mContext->MakeContextCurrent();
|
||||
|
||||
// Try to clear with glCLear.
|
||||
WebGLTexelFormat texelformat = GetWebGLTexelFormat(imageInfo.mInternalFormat, imageInfo.mType);
|
||||
GLenum format = WebGLTexelConversions::GLFormatForTexelFormat(texelformat);
|
||||
GLenum format = imageInfo.mWebGLFormat;
|
||||
GLenum type = imageInfo.mWebGLType;
|
||||
WebGLTexelFormat texelformat = GetWebGLTexelFormat(format, type);
|
||||
|
||||
bool cleared = ClearWithTempFB(mContext, GLName(),
|
||||
imageTarget, level,
|
||||
|
@ -568,11 +570,17 @@ WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
|
|||
ScopedFreePtr<void> zeros;
|
||||
zeros = calloc(1, checked_byteLength.value());
|
||||
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
GLenum driverType = DriverTypeFromType(gl, type);
|
||||
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||
GLenum driverFormat = LOCAL_GL_NONE;
|
||||
DriverFormatsFromFormatAndType(gl, format, type, &driverInternalFormat, &driverFormat);
|
||||
|
||||
mContext->GetAndFlushUnderlyingGLErrors();
|
||||
mContext->gl->fTexImage2D(imageTarget, level, imageInfo.mInternalFormat,
|
||||
imageInfo.mWidth, imageInfo.mHeight,
|
||||
0, format, imageInfo.mType,
|
||||
zeros);
|
||||
gl->fTexImage2D(imageTarget, level, driverInternalFormat,
|
||||
imageInfo.mWidth, imageInfo.mHeight,
|
||||
0, driverFormat, driverType,
|
||||
zeros);
|
||||
GLenum error = mContext->GetAndFlushUnderlyingGLErrors();
|
||||
if (error) {
|
||||
// Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover from this here.
|
||||
|
|
|
@ -23,15 +23,6 @@ inline bool is_pot_assuming_nonnegative(GLsizei x)
|
|||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
inline bool FormatHasAlpha(GLenum format)
|
||||
{
|
||||
return format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_RGB5_A1;
|
||||
}
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
class WebGLTexture MOZ_FINAL
|
||||
|
@ -82,16 +73,19 @@ public:
|
|||
{
|
||||
public:
|
||||
ImageInfo()
|
||||
: mInternalFormat(0)
|
||||
, mType(0)
|
||||
: mWebGLFormat(LOCAL_GL_NONE)
|
||||
, mWebGLType(LOCAL_GL_NONE)
|
||||
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
|
||||
{}
|
||||
|
||||
ImageInfo(GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, WebGLImageDataStatus status)
|
||||
ImageInfo(GLsizei width,
|
||||
GLsizei height,
|
||||
GLenum webGLFormat,
|
||||
GLenum webGLType,
|
||||
WebGLImageDataStatus status)
|
||||
: WebGLRectangleObject(width, height)
|
||||
, mInternalFormat(format)
|
||||
, mType(type)
|
||||
, mWebGLFormat(webGLFormat)
|
||||
, mWebGLType(webGLType)
|
||||
, mImageDataStatus(status)
|
||||
{
|
||||
// shouldn't use this constructor to construct a null ImageInfo
|
||||
|
@ -100,10 +94,10 @@ public:
|
|||
|
||||
bool operator==(const ImageInfo& a) const {
|
||||
return mImageDataStatus == a.mImageDataStatus &&
|
||||
mWidth == a.mWidth &&
|
||||
mWidth == a.mWidth &&
|
||||
mHeight == a.mHeight &&
|
||||
mInternalFormat == a.mInternalFormat &&
|
||||
mType == a.mType;
|
||||
mWebGLFormat == a.mWebGLFormat &&
|
||||
mWebGLType == a.mWebGLType;
|
||||
}
|
||||
bool operator!=(const ImageInfo& a) const {
|
||||
return !(*this == a);
|
||||
|
@ -122,10 +116,20 @@ public:
|
|||
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
int64_t MemoryUsage() const;
|
||||
GLenum InternalFormat() const { return mInternalFormat; }
|
||||
GLenum Type() const { return mType; }
|
||||
/*! This is the format passed from JS to WebGL.
|
||||
* It can be converted to a value to be passed to driver with
|
||||
* DriverFormatsFromFormatAndType().
|
||||
*/
|
||||
GLenum WebGLFormat() const { return mWebGLFormat; }
|
||||
/*! This is the type passed from JS to WebGL.
|
||||
* It can be converted to a value to be passed to driver with
|
||||
* DriverTypeFromType().
|
||||
*/
|
||||
GLenum WebGLType() const { return mWebGLType; }
|
||||
|
||||
protected:
|
||||
GLenum mInternalFormat, mType;
|
||||
GLenum mWebGLFormat; //!< This is the WebGL/GLES format
|
||||
GLenum mWebGLType; //!< This is the WebGL/GLES type
|
||||
WebGLImageDataStatus mImageDataStatus;
|
||||
|
||||
friend class WebGLTexture;
|
||||
|
|
|
@ -213,4 +213,3 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
|
|||
[test_toDataURL_parameters.html]
|
||||
[test_windingRuleUndefined.html]
|
||||
[test_2d.fillText.gradient.html]
|
||||
[test_createPattern_broken.html]
|
||||
|
|
|
@ -15093,6 +15093,27 @@ var _thrown = undefined; try {
|
|||
</script>
|
||||
<img src="image_broken.png" id="broken_2.png" class="resource">
|
||||
|
||||
<!-- [[[ test_2d.pattern.image.incomplete.html ]]] -->
|
||||
|
||||
<p>Canvas test: 2d.pattern.image.incomplete</p>
|
||||
<canvas id="c466" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||
<script>
|
||||
|
||||
function test_2d_pattern_image_incomplete() {
|
||||
|
||||
var canvas = document.getElementById('c466');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var img = new Image();
|
||||
todo(img.complete === false, "img.complete === false");
|
||||
var _thrown = undefined; try {
|
||||
ctx.createPattern(img, 'repeat');
|
||||
} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "InvalidStateError" && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw InvalidStateError");
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- [[[ test_2d.pattern.image.null.html ]]] -->
|
||||
|
||||
<p>Canvas test: 2d.pattern.image.null</p>
|
||||
|
@ -23768,6 +23789,11 @@ function runTests() {
|
|||
} catch (e) {
|
||||
ok(false, "unexpected exception thrown in: test_2d_pattern_image_broken");
|
||||
}
|
||||
try {
|
||||
test_2d_pattern_image_incomplete();
|
||||
} catch (e) {
|
||||
ok(false, "unexpected exception thrown in: test_2d_pattern_image_incomplete");
|
||||
}
|
||||
try {
|
||||
test_2d_pattern_image_null();
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for createPattern with a broken image</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="file_drawWindow_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.addEventListener("load", function(){
|
||||
var _thrown = undefined;
|
||||
|
||||
try{
|
||||
var img = document.getElementById('broken.png');
|
||||
var ctx = document.getElementById('c').getContext('2d');
|
||||
var p = ctx.createPattern(img, 'repeat');
|
||||
} catch (e) {
|
||||
_thrown = e
|
||||
};
|
||||
|
||||
ok(_thrown && _thrown.name == "InvalidStateError" && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw InvalidStateError");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c" class="output" width="100" height="50"></canvas>
|
||||
<img src="/images/broken.png" id="broken.png" class="resource"/>
|
||||
</body>
|
||||
</html>
|
|
@ -11,6 +11,7 @@ support-files =
|
|||
[test_no_arr_points.html]
|
||||
[test_noprog_draw.html]
|
||||
[test_privileged_exts.html]
|
||||
[test_texsubimage_float.html]
|
||||
[test_webgl_available.html]
|
||||
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
|
||||
[test_webgl_conformance.html]
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>WebGL test: bug 1003607</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="driver-info.js"></script>
|
||||
<script src="webgl-util.js"></script>
|
||||
<body>
|
||||
<canvas id="c"></canvas>
|
||||
<script>
|
||||
|
||||
// Give ourselves a scope to return early from:
|
||||
(function() {
|
||||
var gl = WebGLUtil.getWebGL('c');
|
||||
if (!gl) {
|
||||
todo(false, 'WebGL is unavailable.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Catch actual WebGLUtil errors, not GL errors.
|
||||
function errorFunc(str) {
|
||||
ok(false, 'Error: ' + str);
|
||||
}
|
||||
WebGLUtil.setErrorFunc(errorFunc);
|
||||
|
||||
function checkGLError(func, info, reference) {
|
||||
var error = gl.getError();
|
||||
var prefix = info ? ('[' + info + '] ') : '';
|
||||
var text = 'gl.getError should be 0x' + reference.toString(16) +
|
||||
', was 0x' + error.toString(16) + '.';
|
||||
func(error == reference, prefix + text);
|
||||
}
|
||||
|
||||
// Begin test:
|
||||
if (!gl.getExtension('OES_texture_float')) {
|
||||
todo(false, 'Not having this extension is fine.');
|
||||
return;
|
||||
}
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
checkGLError(ok, 'texture parameter setup should succeed', gl.NO_ERROR);
|
||||
|
||||
// Generate data
|
||||
var width = 2;
|
||||
var height = 2;
|
||||
var numChannels = 4;
|
||||
var data = new Float32Array(width * height * numChannels);
|
||||
for (var ii = 0; ii < data.length; ++ii) {
|
||||
data[ii] = 10000;
|
||||
}
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, data);
|
||||
checkGLError(ok, 'floating-point texture allocation should succeed', gl.NO_ERROR);
|
||||
|
||||
// Try respecifying data
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.FLOAT, data);
|
||||
checkGLError(ok, 'floating-point texture sub image should succeed', gl.NO_ERROR);
|
||||
})();
|
||||
|
||||
</script>
|
|
@ -548,17 +548,12 @@ HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
|
|||
}
|
||||
} else {
|
||||
// the row count was 0, so
|
||||
// find the first row group and insert there as first child
|
||||
// find the last row group and insert there as first child
|
||||
nsCOMPtr<nsIContent> rowGroup;
|
||||
for (nsIContent* child = nsINode::GetFirstChild();
|
||||
for (nsIContent* child = nsINode::GetLastChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
nsINodeInfo *childInfo = child->NodeInfo();
|
||||
nsIAtom *localName = childInfo->NameAtom();
|
||||
if (childInfo->NamespaceID() == kNameSpaceID_XHTML &&
|
||||
(localName == nsGkAtoms::thead ||
|
||||
localName == nsGkAtoms::tbody ||
|
||||
localName == nsGkAtoms::tfoot)) {
|
||||
child = child->GetPreviousSibling()) {
|
||||
if (child->IsHTML(nsGkAtoms::tbody)) {
|
||||
rowGroup = child;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -410,6 +410,7 @@ skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
|
|||
[test_bug885024.html]
|
||||
[test_bug893537.html]
|
||||
[test_bug969346.html]
|
||||
[test_bug1003539.html]
|
||||
[test_change_crossorigin.html]
|
||||
[test_checked.html]
|
||||
[test_dir_attributes_reflection.html]
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1003539
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1003539</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1003539 **/
|
||||
// Refering to this specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#dom-table-insertrow
|
||||
var tab;
|
||||
tab = document.createElement("table");
|
||||
tab.createTHead();
|
||||
tab.insertRow();
|
||||
is(tab.innerHTML, '<thead></thead><tbody><tr></tr></tbody>', "Row should be inserted in the tbody.");
|
||||
|
||||
tab = document.createElement("table");
|
||||
tab.createTBody();
|
||||
tab.createTBody();
|
||||
tab.insertRow();
|
||||
is(tab.innerHTML, '<tbody></tbody><tbody><tr></tr></tbody>', "Row should be inserted in the last tbody.");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1003539">Mozilla Bug 1003539</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -422,7 +422,7 @@ public:
|
|||
// Not owned:
|
||||
// - mDecoder
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mContentType.SizeOfIncludingThisIfUnshared(aMallocSizeOf);
|
||||
size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -14,17 +14,18 @@ const Cu = Components.utils;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
|
||||
|
||||
function AppsService()
|
||||
{
|
||||
debug("AppsService Constructor");
|
||||
let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
debug("inParent: " + inParent);
|
||||
Cu.import(inParent ? "resource://gre/modules/Webapps.jsm" :
|
||||
"resource://gre/modules/AppsServiceChild.jsm");
|
||||
this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
debug("inParent: " + this.inParent);
|
||||
Cu.import(this.inParent ? "resource://gre/modules/Webapps.jsm" :
|
||||
"resource://gre/modules/AppsServiceChild.jsm");
|
||||
}
|
||||
|
||||
AppsService.prototype = {
|
||||
|
@ -39,6 +40,16 @@ AppsService.prototype = {
|
|||
return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
|
||||
},
|
||||
|
||||
getManifestFor: function getManifestFor(aManifestURL) {
|
||||
debug("getManifestFor(" + aManifestURL + ")");
|
||||
if (this.inParent) {
|
||||
return DOMApplicationRegistry.getManifestFor(aManifestURL);
|
||||
} else {
|
||||
return Promise.reject(
|
||||
new Error("Calling getManifestFor() from child is not supported"));
|
||||
}
|
||||
},
|
||||
|
||||
getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
|
||||
debug("getAppLocalIdByManifestURL( " + aManifestURL + " )");
|
||||
return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
|
||||
|
|
|
@ -126,6 +126,11 @@ this.AppsUtils = {
|
|||
return null;
|
||||
},
|
||||
|
||||
getManifestFor: function getManifestFor(aManifestURL) {
|
||||
debug("getManifestFor(" + aManifestURL + ")");
|
||||
return DOMApplicationRegistry.getManifestFor(aManifestURL);
|
||||
},
|
||||
|
||||
getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aApps, aManifestURL) {
|
||||
debug("getAppLocalIdByManifestURL " + aManifestURL);
|
||||
for (let id in aApps) {
|
||||
|
|
|
@ -31,6 +31,8 @@ function runTest() {
|
|||
|
||||
var highPriorityIframe = null;
|
||||
var childID = null;
|
||||
var lock = null;
|
||||
var p = null;
|
||||
|
||||
expectProcessCreated().then(function(chid) {
|
||||
childID = chid;
|
||||
|
@ -44,23 +46,34 @@ function runTest() {
|
|||
highPriorityIframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
highPriorityIframe.src = browserElementTestHelpers.emptyPage2;
|
||||
|
||||
var p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
|
||||
|
||||
document.body.appendChild(highPriorityIframe);
|
||||
|
||||
return p;
|
||||
}).then(function() {
|
||||
return expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
|
||||
}).then(function() {
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
|
||||
lock = navigator.requestWakeLock('high-priority');
|
||||
return p;
|
||||
}).then(function() {
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
|
||||
lock.unlock();
|
||||
return p;
|
||||
}).then(SimpleTest.finish);
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
addEventListener('testready', function() {
|
||||
// Cause the CPU wake lock taken on behalf of the high-priority process to
|
||||
// time out after 1s.
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{set: [["dom.ipc.systemMessageCPULockTimeoutSec", 1]]},
|
||||
{set: [
|
||||
/* Cause the CPU wake lock taken on behalf of the high-priority process
|
||||
* to time out after 1s. */
|
||||
["dom.ipc.systemMessageCPULockTimeoutSec", 1],
|
||||
["dom.wakelock.enabled", true]
|
||||
]},
|
||||
runTest);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
{
|
||||
"insertRow should not copy prefixes": true,
|
||||
"insertRow should insert into a tbody, not into a thead, if table.rows is empty": true,
|
||||
"insertRow should insert into a tbody, not into a tfoot, if table.rows is empty": true
|
||||
"insertRow should not copy prefixes": true
|
||||
}
|
||||
|
|
|
@ -17,11 +17,18 @@ interface nsIURI;
|
|||
* This service allows accessing some DOMApplicationRegistry methods from
|
||||
* non-javascript code.
|
||||
*/
|
||||
[scriptable, uuid(93cde78d-56f6-4322-b707-9b23eb80d90d)]
|
||||
[scriptable, uuid(2e884bbe-7a3d-4b01-ad92-fcd65a449043)]
|
||||
interface nsIAppsService : nsISupports
|
||||
{
|
||||
mozIApplication getAppByManifestURL(in DOMString manifestURL);
|
||||
|
||||
/**
|
||||
* Returns a Promise for the manifest for a given manifestURL.
|
||||
* This is only supported in the parent process: the promise will be rejected
|
||||
* in content processes.
|
||||
*/
|
||||
jsval getManifestFor(in DOMString manifestURL);
|
||||
|
||||
/**
|
||||
* Returns the |localId| of the app associated with the |manifestURL| passed
|
||||
* in parameter.
|
||||
|
|
|
@ -109,6 +109,7 @@ class ParticularProcessPriorityManager;
|
|||
*/
|
||||
class ProcessPriorityManagerImpl MOZ_FINAL
|
||||
: public nsIObserver
|
||||
, public WakeLockObserver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -157,6 +158,12 @@ public:
|
|||
ParticularProcessPriorityManager* aParticularManager,
|
||||
hal::ProcessPriority aOldPriority);
|
||||
|
||||
/**
|
||||
* Implements WakeLockObserver, used to monitor wake lock changes in the
|
||||
* main process.
|
||||
*/
|
||||
virtual void Notify(const WakeLockInformation& aInfo) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
static bool sPrefListenersRegistered;
|
||||
static bool sInitialized;
|
||||
|
@ -165,7 +172,7 @@ private:
|
|||
static void PrefChangedCallback(const char* aPref, void* aClosure);
|
||||
|
||||
ProcessPriorityManagerImpl();
|
||||
~ProcessPriorityManagerImpl() {}
|
||||
~ProcessPriorityManagerImpl();
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManagerImpl);
|
||||
|
||||
void Init();
|
||||
|
@ -175,10 +182,12 @@ private:
|
|||
|
||||
void ObserveContentParentCreated(nsISupports* aContentParent);
|
||||
void ObserveContentParentDestroyed(nsISupports* aSubject);
|
||||
void ResetAllCPUPriorities();
|
||||
|
||||
nsDataHashtable<nsUint64HashKey, nsRefPtr<ParticularProcessPriorityManager> >
|
||||
mParticularManagers;
|
||||
|
||||
bool mHighPriority;
|
||||
nsTHashtable<nsUint64HashKey> mHighPriorityChildIDs;
|
||||
};
|
||||
|
||||
|
@ -411,8 +420,15 @@ ProcessPriorityManagerImpl::GetSingleton()
|
|||
}
|
||||
|
||||
ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
|
||||
: mHighPriority(false)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
RegisterWakeLockObserver(this);
|
||||
}
|
||||
|
||||
ProcessPriorityManagerImpl::~ProcessPriorityManagerImpl()
|
||||
{
|
||||
UnregisterWakeLockObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -526,14 +542,20 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
|||
mHighPriorityChildIDs.RemoveEntry(childID);
|
||||
|
||||
// We just lost a high-priority process; reset everyone's CPU priorities.
|
||||
nsTArray<nsRefPtr<ParticularProcessPriorityManager> > pppms;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&EnumerateParticularProcessPriorityManagers,
|
||||
&pppms);
|
||||
ResetAllCPUPriorities();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pppms.Length(); i++) {
|
||||
pppms[i]->ResetCPUPriorityNow();
|
||||
}
|
||||
void
|
||||
ProcessPriorityManagerImpl::ResetAllCPUPriorities( void )
|
||||
{
|
||||
nsTArray<nsRefPtr<ParticularProcessPriorityManager> > pppms;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&EnumerateParticularProcessPriorityManagers,
|
||||
&pppms);
|
||||
|
||||
for (uint32_t i = 0; i < pppms.Length(); i++) {
|
||||
pppms[i]->ResetCPUPriorityNow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +563,9 @@ bool
|
|||
ProcessPriorityManagerImpl::OtherProcessHasHighPriority(
|
||||
ParticularProcessPriorityManager* aParticularManager)
|
||||
{
|
||||
if (mHighPriorityChildIDs.Contains(aParticularManager->ChildID())) {
|
||||
if (mHighPriority) {
|
||||
return true;
|
||||
} else if (mHighPriorityChildIDs.Contains(aParticularManager->ChildID())) {
|
||||
return mHighPriorityChildIDs.Count() > 1;
|
||||
}
|
||||
return mHighPriorityChildIDs.Count() > 0;
|
||||
|
@ -587,6 +611,29 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
|
|||
}
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
ProcessPriorityManagerImpl::Notify(const WakeLockInformation& aInfo)
|
||||
{
|
||||
/* The main process always has an ID of 0, if it is present in the wake-lock
|
||||
* information then we explicitly requested a high-priority wake-lock for the
|
||||
* main process. */
|
||||
if (aInfo.topic().EqualsLiteral("high-priority")) {
|
||||
if (aInfo.lockingProcesses().Contains((uint64_t)0)) {
|
||||
mHighPriority = true;
|
||||
} else {
|
||||
mHighPriority = false;
|
||||
}
|
||||
|
||||
/* The main process got a high-priority wakelock change; reset everyone's
|
||||
* CPU priorities. */
|
||||
ResetAllCPUPriorities();
|
||||
|
||||
LOG("Got wake lock changed event. "
|
||||
"Now mHighPriorityParent = %d\n", mHighPriority);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(ParticularProcessPriorityManager,
|
||||
nsIObserver,
|
||||
nsITimerCallback,
|
||||
|
|
|
@ -130,7 +130,6 @@ for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'):
|
|||
DEFINES[var] = True
|
||||
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
DEFINES['ENABLE_TESTS'] = 1
|
||||
LOCAL_INCLUDES += [
|
||||
'ipc/glue',
|
||||
]
|
||||
|
|
|
@ -1116,6 +1116,9 @@ function PeerConnectionWrapper(label, configuration) {
|
|||
|
||||
this.dataChannels = [ ];
|
||||
|
||||
this.onAddStreamFired = false;
|
||||
this.addStreamCallbacks = {};
|
||||
|
||||
info("Creating " + this);
|
||||
this._pc = new mozRTCPeerConnection(this.configuration);
|
||||
is(this._pc.iceConnectionState, "new", "iceConnectionState starts at 'new'");
|
||||
|
@ -1152,6 +1155,8 @@ function PeerConnectionWrapper(label, configuration) {
|
|||
*/
|
||||
this._pc.onaddstream = function (event) {
|
||||
info(self + ": 'onaddstream' event fired for " + JSON.stringify(event.stream));
|
||||
// TODO: remove this once Bugs 998552 and 998546 are closed
|
||||
self.onAddStreamFired = true;
|
||||
|
||||
var type = '';
|
||||
if (event.stream.getAudioTracks().length > 0) {
|
||||
|
@ -1161,6 +1166,11 @@ function PeerConnectionWrapper(label, configuration) {
|
|||
type += 'video';
|
||||
}
|
||||
self.attachMedia(event.stream, type, 'remote');
|
||||
|
||||
Object.keys(self.addStreamCallbacks).forEach(function(name) {
|
||||
info(this + " calling addStreamCallback " + name);
|
||||
self.addStreamCallbacks[name]();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1324,8 +1334,14 @@ PeerConnectionWrapper.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
info("Get " + this.constraints.length + " local streams");
|
||||
_getAllUserMedia(this.constraints, 0);
|
||||
if (this.constraints.length === 0) {
|
||||
info("Skipping GUM: no UserMedia requested");
|
||||
onSuccess();
|
||||
}
|
||||
else {
|
||||
info("Get " + this.constraints.length + " local streams");
|
||||
_getAllUserMedia(this.constraints, 0);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1562,18 +1578,150 @@ PeerConnectionWrapper.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Checks that we are getting the media streams we expect.
|
||||
* Counts the amount of audio tracks in a given media constraint.
|
||||
*
|
||||
* @param constraints
|
||||
* The contraint to be examined.
|
||||
*/
|
||||
countAudioTracksInMediaConstraint : function
|
||||
PCW_countAudioTracksInMediaConstraint(constraints) {
|
||||
if ((!constraints) || (constraints.length === 0)) {
|
||||
return 0;
|
||||
}
|
||||
var audioTracks = 0;
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
if (constraints[i].audio) {
|
||||
audioTracks++;
|
||||
}
|
||||
}
|
||||
return audioTracks;
|
||||
},
|
||||
|
||||
/**
|
||||
* Counts the amount of video tracks in a given media constraint.
|
||||
*
|
||||
* @param constraint
|
||||
* The contraint to be examined.
|
||||
*/
|
||||
countVideoTracksInMediaConstraint : function
|
||||
PCW_countVideoTracksInMediaConstraint(constraints) {
|
||||
if ((!constraints) || (constraints.length === 0)) {
|
||||
return 0;
|
||||
}
|
||||
var videoTracks = 0;
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
if (constraints[i].video) {
|
||||
videoTracks++;
|
||||
}
|
||||
}
|
||||
return videoTracks;
|
||||
},
|
||||
|
||||
/*
|
||||
* Counts the amount of audio tracks in a given set of streams.
|
||||
*
|
||||
* @param streams
|
||||
* An array of streams (as returned by getLocalStreams()) to be
|
||||
* examined.
|
||||
*/
|
||||
countAudioTracksInStreams : function PCW_countAudioTracksInStreams(streams) {
|
||||
if (!streams || (streams.length === 0)) {
|
||||
return 0;
|
||||
}
|
||||
var audioTracks = 0;
|
||||
streams.forEach(function(st) {
|
||||
audioTracks += st.getAudioTracks().length;
|
||||
});
|
||||
return audioTracks;
|
||||
},
|
||||
|
||||
/*
|
||||
* Counts the amount of video tracks in a given set of streams.
|
||||
*
|
||||
* @param streams
|
||||
* An array of streams (as returned by getLocalStreams()) to be
|
||||
* examined.
|
||||
*/
|
||||
countVideoTracksInStreams: function PCW_countVideoTracksInStreams(streams) {
|
||||
if (!streams || (streams.length === 0)) {
|
||||
return 0;
|
||||
}
|
||||
var videoTracks = 0;
|
||||
streams.forEach(function(st) {
|
||||
videoTracks += st.getVideoTracks().length;
|
||||
});
|
||||
return videoTracks;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks that we are getting the media tracks we expect.
|
||||
*
|
||||
* @param {object} constraintsRemote
|
||||
* The media constraints of the remote peer connection object
|
||||
* The media constraints of the local and remote peer connection object
|
||||
*/
|
||||
checkMediaStreams : function PCW_checkMediaStreams(constraintsRemote) {
|
||||
is(this._pc.getLocalStreams().length, this.constraints.length,
|
||||
this + ' has ' + this.constraints.length + ' local streams');
|
||||
checkMediaTracks : function PCW_checkMediaTracks(constraintsRemote, onSuccess) {
|
||||
var self = this;
|
||||
var addStreamTimeout = null;
|
||||
|
||||
// TODO: change this when multiple incoming streams are supported (bug 834835)
|
||||
is(this._pc.getRemoteStreams().length, 1,
|
||||
this + ' has ' + 1 + ' remote streams');
|
||||
function _checkMediaTracks(constraintsRemote, onSuccess) {
|
||||
if (self.addStreamTimeout === null) {
|
||||
clearTimeout(self.addStreamTimeout);
|
||||
}
|
||||
|
||||
var localConstraintAudioTracks =
|
||||
self.countAudioTracksInMediaConstraint(self.constraints);
|
||||
var localStreams = self._pc.getLocalStreams();
|
||||
var localAudioTracks = self.countAudioTracksInStreams(localStreams, false);
|
||||
is(localAudioTracks, localConstraintAudioTracks, self + ' has ' +
|
||||
localAudioTracks + ' local audio tracks');
|
||||
|
||||
var localConstraintVideoTracks =
|
||||
self.countVideoTracksInMediaConstraint(self.constraints);
|
||||
var localVideoTracks = self.countVideoTracksInStreams(localStreams, false);
|
||||
is(localVideoTracks, localConstraintVideoTracks, self + ' has ' +
|
||||
localVideoTracks + ' local video tracks');
|
||||
|
||||
var remoteConstraintAudioTracks =
|
||||
self.countAudioTracksInMediaConstraint(constraintsRemote);
|
||||
var remoteStreams = self._pc.getRemoteStreams();
|
||||
var remoteAudioTracks = self.countAudioTracksInStreams(remoteStreams, false);
|
||||
is(remoteAudioTracks, remoteConstraintAudioTracks, self + ' has ' +
|
||||
remoteAudioTracks + ' remote audio tracks');
|
||||
|
||||
var remoteConstraintVideoTracks =
|
||||
self.countVideoTracksInMediaConstraint(constraintsRemote);
|
||||
var remoteVideoTracks = self.countVideoTracksInStreams(remoteStreams, false);
|
||||
is(remoteVideoTracks, remoteConstraintVideoTracks, self + ' has ' +
|
||||
remoteVideoTracks + ' remote video tracks');
|
||||
|
||||
onSuccess();
|
||||
}
|
||||
|
||||
function __checkMediaTracksTimeout(onSuccess) {
|
||||
ok(false, self + " checkMediaTracks() timed out waiting for onaddstream event to fire");
|
||||
onSuccess();
|
||||
}
|
||||
|
||||
// we have to do this check as the onaddstream never fires if the remote
|
||||
// stream has no track at all!
|
||||
var expectedRemoteTracks =
|
||||
self.countAudioTracksInMediaConstraint(constraintsRemote) +
|
||||
self.countVideoTracksInMediaConstraint(constraintsRemote);
|
||||
|
||||
// TODO: remove this once Bugs 998552 and 998546 are closed
|
||||
if ((self.onAddStreamFired) || (expectedRemoteTracks == 0)) {
|
||||
_checkMediaTracks(constraintsRemote, onSuccess);
|
||||
} else {
|
||||
info(self + " checkMediaTracks() got called before onAddStream fired");
|
||||
// we rely on the outer mochitest timeout to catch the case where
|
||||
// onaddstream never fires
|
||||
self.addStreamCallbacks.checkMediaTracks = function() {
|
||||
_checkMediaTracks(constraintsRemote, onSuccess);
|
||||
};
|
||||
addStreamTimeout = setTimeout(function () {
|
||||
self._checkMediaTracksTimeout(onSuccess);
|
||||
}, 60000);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -203,17 +203,19 @@ var commandsPeerConnection = [
|
|||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_CHECK_MEDIA_STREAMS',
|
||||
'PC_LOCAL_CHECK_MEDIA_TRACKS',
|
||||
function (test) {
|
||||
test.pcLocal.checkMediaStreams(test._remote_constraints);
|
||||
test.next();
|
||||
test.pcLocal.checkMediaTracks(test._remote_constraints, function () {
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_CHECK_MEDIA_STREAMS',
|
||||
'PC_REMOTE_CHECK_MEDIA_TRACKS',
|
||||
function (test) {
|
||||
test.pcRemote.checkMediaStreams(test._local_constraints);
|
||||
test.next();
|
||||
test.pcRemote.checkMediaTracks(test._local_constraints, function () {
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -374,17 +376,19 @@ var commandsDataChannel = [
|
|||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_CHECK_MEDIA_STREAMS',
|
||||
'PC_LOCAL_CHECK_MEDIA_TRACKS',
|
||||
function (test) {
|
||||
test.pcLocal.checkMediaStreams(test.pcRemote.constraints);
|
||||
test.next();
|
||||
test.pcLocal.checkMediaTracks(test.pcRemote.constraints, function () {
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_CHECK_MEDIA_STREAMS',
|
||||
'PC_REMOTE_CHECK_MEDIA_TRACKS',
|
||||
function (test) {
|
||||
test.pcRemote.checkMediaStreams(test.pcLocal.constraints);
|
||||
test.next();
|
||||
test.pcRemote.checkMediaTracks(test.pcLocal.constraints, function () {
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
var test;
|
||||
runTest(function () {
|
||||
test = new DataChannelTest();
|
||||
|
||||
// TODO: Add back once bug 873049 has been fixed
|
||||
test.chain.remove("PC_LOCAL_CHECK_MEDIA_STREAMS");
|
||||
test.chain.remove("PC_REMOTE_CHECK_MEDIA_STREAMS");
|
||||
|
||||
test.run();
|
||||
}, true);
|
||||
|
||||
|
|
|
@ -798,10 +798,10 @@ interface WebGLExtensionCompressedTextureETC1
|
|||
[NoInterfaceObject]
|
||||
interface WebGLExtensionCompressedTexturePVRTC
|
||||
{
|
||||
const GLenum COMPRESSED_RGB_PVRTC_4BPPV1 = 0x8C00;
|
||||
const GLenum COMPRESSED_RGB_PVRTC_2BPPV1 = 0x8C01;
|
||||
const GLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
|
||||
const GLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
|
||||
const GLenum COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
|
||||
const GLenum COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
|
||||
const GLenum COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
|
||||
const GLenum COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
|
|
|
@ -399,9 +399,12 @@ NS_IMETHODIMP
|
|||
StopSyncLoopRunnable::Cancel()
|
||||
{
|
||||
nsresult rv = Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Run() failed");
|
||||
|
||||
return NS_OK;
|
||||
nsresult rv2 = WorkerSyncRunnable::Cancel();
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv2), "Cancel() failed");
|
||||
|
||||
return NS_FAILED(rv) ? rv : rv2;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -665,6 +665,10 @@ ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
ceilf(bounds.height * mResolution)),
|
||||
gfx::ImageFormatToSurfaceFormat(format));
|
||||
|
||||
if (!mSinglePaintDrawTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctxt = new gfxContext(mSinglePaintDrawTarget);
|
||||
|
||||
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
|
||||
|
|
|
@ -895,7 +895,7 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
fprintf(aFile, "%s", string.BeginReading());
|
||||
fprintf_stderr(aFile, "%s", string.BeginReading());
|
||||
} else {
|
||||
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
|
||||
if (clipboard) {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
diff --git a/intl/icu/source/acinclude.m4 b/intl/icu/source/acinclude.m4
|
||||
--- a/intl/icu/source/acinclude.m4
|
||||
+++ b/intl/icu/source/acinclude.m4
|
||||
@@ -466,30 +466,36 @@ AC_DEFUN([AC_CHECK_STRICT_COMPILE],
|
||||
*)
|
||||
# Do not use -ansi. It limits us to C90, and it breaks some platforms.
|
||||
# We use -std=c99 to disable the gnu99 defaults and its associated warnings
|
||||
CFLAGS="$CFLAGS -std=c99"
|
||||
;;
|
||||
esac
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings"
|
||||
+
|
||||
+ # Suppress clang C warnings:
|
||||
+ CFLAGS="$CFLAGS -Wno-sign-compare -Wno-unused"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
if test "`$CC /help 2>&1 | head -c9`" = "Microsoft"
|
||||
then
|
||||
CFLAGS="$CFLAGS /W4"
|
||||
fi ;;
|
||||
*-*-mingw32|*-*-mingw64)
|
||||
CFLAGS="$CFLAGS -W4" ;;
|
||||
esac
|
||||
fi
|
||||
if test "$GXX" = yes
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -W -Wall -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||
+
|
||||
+ # Suppress clang C++ warnings:
|
||||
+ CXXFLAGS="$CXXFLAGS -Wno-unused -Wno-unused-parameter"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
if test "`$CXX /help 2>&1 | head -c9`" = "Microsoft"
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS /W4"
|
||||
fi ;;
|
||||
*-*-mingw32|*-*-mingw64)
|
||||
diff --git a/intl/icu/source/configure b/intl/icu/source/configure
|
||||
--- a/intl/icu/source/configure
|
||||
+++ b/intl/icu/source/configure
|
||||
@@ -4089,30 +4089,36 @@ fi
|
||||
*)
|
||||
# Do not use -ansi. It limits us to C90, and it breaks some platforms.
|
||||
# We use -std=c99 to disable the gnu99 defaults and its associated warnings
|
||||
CFLAGS="$CFLAGS -std=c99"
|
||||
;;
|
||||
esac
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings"
|
||||
+
|
||||
+ # Suppress clang C warnings:
|
||||
+ CFLAGS="$CFLAGS -Wno-sign-compare -Wno-unused"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
if test "`$CC /help 2>&1 | head -c9`" = "Microsoft"
|
||||
then
|
||||
CFLAGS="$CFLAGS /W4"
|
||||
fi ;;
|
||||
*-*-mingw32|*-*-mingw64)
|
||||
CFLAGS="$CFLAGS -W4" ;;
|
||||
esac
|
||||
fi
|
||||
if test "$GXX" = yes
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -W -Wall -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||
+
|
||||
+ # Suppress clang C++ warnings:
|
||||
+ CXXFLAGS="$CXXFLAGS -Wno-unused -Wno-unused-parameter"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
if test "`$CXX /help 2>&1 | head -c9`" = "Microsoft"
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS /W4"
|
||||
fi ;;
|
||||
*-*-mingw32|*-*-mingw64)
|
|
@ -471,6 +471,9 @@ AC_DEFUN([AC_CHECK_STRICT_COMPILE],
|
|||
esac
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings"
|
||||
|
||||
# Suppress clang C warnings:
|
||||
CFLAGS="$CFLAGS -Wno-sign-compare -Wno-unused"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
|
@ -485,6 +488,9 @@ AC_DEFUN([AC_CHECK_STRICT_COMPILE],
|
|||
if test "$GXX" = yes
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -W -Wall -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||
|
||||
# Suppress clang C++ warnings:
|
||||
CXXFLAGS="$CXXFLAGS -Wno-unused -Wno-unused-parameter"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
|
|
|
@ -4094,6 +4094,9 @@ $as_echo "$ac_use_strict_options" >&6; }
|
|||
esac
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings"
|
||||
|
||||
# Suppress clang C warnings:
|
||||
CFLAGS="$CFLAGS -Wno-sign-compare -Wno-unused"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
|
@ -4108,6 +4111,9 @@ $as_echo "$ac_use_strict_options" >&6; }
|
|||
if test "$GXX" = yes
|
||||
then
|
||||
CXXFLAGS="$CXXFLAGS -W -Wall -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||
|
||||
# Suppress clang C++ warnings:
|
||||
CXXFLAGS="$CXXFLAGS -Wno-unused -Wno-unused-parameter"
|
||||
else
|
||||
case "${host}" in
|
||||
*-*-cygwin)
|
||||
|
|
|
@ -55,5 +55,6 @@ patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-899722-4
|
|||
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-915735
|
||||
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/genrb-omitCollationRules.diff
|
||||
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/qualify-uinitonce-windows.diff
|
||||
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/suppress-warnings.diff
|
||||
|
||||
hg addremove ${icu_dir}
|
||||
|
|
|
@ -41,10 +41,10 @@ const size_t CellSize = size_t(1) << CellShift;
|
|||
const size_t CellMask = CellSize - 1;
|
||||
|
||||
/* These are magic constants derived from actual offsets in gc/Heap.h. */
|
||||
const size_t ChunkMarkBitmapOffset = 1032352;
|
||||
const size_t ChunkMarkBitmapOffset = 1032360;
|
||||
const size_t ChunkMarkBitmapBits = 129024;
|
||||
const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
|
||||
const size_t ChunkLocationOffset = ChunkSize - 2 * sizeof(void*) - sizeof(uint64_t);
|
||||
const size_t ChunkLocationOffset = ChunkSize - sizeof(void*) - sizeof(uintptr_t);
|
||||
|
||||
/*
|
||||
* Live objects are marked black. How many other additional colors are available
|
||||
|
|
|
@ -42,12 +42,12 @@ HeapSlot::preconditionForSet(Zone *zone, JSObject *owner, Kind kind, uint32_t sl
|
|||
return ok && owner->zone() == zone;
|
||||
}
|
||||
|
||||
bool
|
||||
HeapSlot::preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target) const
|
||||
void
|
||||
HeapSlot::preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
return kind == Slot
|
||||
? obj->getSlotAddressUnchecked(slot)->get() == target
|
||||
: static_cast<HeapSlot *>(obj->getDenseElements() + slot)->get() == target;
|
||||
JS_ASSERT_IF(kind == Slot, obj->getSlotAddressUnchecked(slot)->get() == target);
|
||||
JS_ASSERT_IF(kind == Element,
|
||||
static_cast<HeapSlot *>(obj->getDenseElements() + slot)->get() == target);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -233,9 +233,9 @@ class BarrieredCell : public gc::Cell
|
|||
#endif
|
||||
}
|
||||
|
||||
static void writeBarrierPost(T *thing, void *cellp) {}
|
||||
static void writeBarrierPostRelocate(T *thing, void *cellp) {}
|
||||
static void writeBarrierPostRemove(T *thing, void *cellp) {}
|
||||
static void writeBarrierPost(T *thing, void *addr) {}
|
||||
static void writeBarrierPostRelocate(T *thing, void *addr) {}
|
||||
static void writeBarrierPostRemove(T *thing, void *addr) {}
|
||||
};
|
||||
|
||||
} // namespace gc
|
||||
|
@ -339,7 +339,6 @@ struct InternalGCMethods<Value>
|
|||
preBarrier(ZoneOfValueFromAnyThread(v), v);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void preBarrier(Zone *zone, Value v) {
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (v.isString() && StringIsPermanentAtom(v.toString()))
|
||||
|
@ -353,34 +352,24 @@ struct InternalGCMethods<Value>
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void postBarrier(Value *vp) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (vp->isObject()) {
|
||||
gc::StoreBuffer *sb = reinterpret_cast<gc::Cell *>(&vp->toObject())->storeBuffer();
|
||||
if (sb)
|
||||
sb->putValueFromAnyThread(vp);
|
||||
}
|
||||
if (vp->isObject())
|
||||
shadowRuntimeFromAnyThread(*vp)->gcStoreBufferPtr()->putValue(vp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void postBarrierRelocate(Value *vp) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (vp->isObject()) {
|
||||
gc::StoreBuffer *sb = reinterpret_cast<gc::Cell *>(&vp->toObject())->storeBuffer();
|
||||
if (sb)
|
||||
sb->putRelocatableValueFromAnyThread(vp);
|
||||
}
|
||||
shadowRuntimeFromAnyThread(*vp)->gcStoreBufferPtr()->putRelocatableValue(vp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void postBarrierRemove(Value *vp) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(vp);
|
||||
JS_ASSERT(vp->isMarkable());
|
||||
JSRuntime *rt = static_cast<js::gc::Cell *>(vp->toGCThing())->runtimeFromAnyThread();
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->removeRelocatableValueFromAnyThread(vp);
|
||||
shadowRuntime->gcStoreBufferPtr()->removeRelocatableValue(vp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -862,43 +851,64 @@ class HeapSlot : public BarrieredBase<Value>
|
|||
post(owner, kind, slot, v);
|
||||
}
|
||||
|
||||
void init(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
value = v;
|
||||
post(rt, owner, kind, slot, v);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool preconditionForSet(JSObject *owner, Kind kind, uint32_t slot);
|
||||
bool preconditionForSet(Zone *zone, JSObject *owner, Kind kind, uint32_t slot);
|
||||
bool preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target) const;
|
||||
static void preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot,
|
||||
Value target);
|
||||
#endif
|
||||
|
||||
void set(JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
JS_ASSERT(preconditionForSet(owner, kind, slot));
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
}
|
||||
|
||||
void set(Zone *zone, JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
JS_ASSERT(preconditionForSet(zone, owner, kind, slot));
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone);
|
||||
pre(zone);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
post(shadowZone->runtimeFromAnyThread(), owner, kind, slot, v);
|
||||
}
|
||||
|
||||
/* For users who need to manually barrier the raw types. */
|
||||
static void writeBarrierPost(JSObject *owner, Kind kind, uint32_t slot, const Value &target) {
|
||||
reinterpret_cast<HeapSlot *>(const_cast<Value *>(&target))->post(owner, kind, slot, target);
|
||||
static void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, const Value &target)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
js::gc::Cell *cell = reinterpret_cast<js::gc::Cell*>(obj);
|
||||
writeBarrierPost(cell->runtimeFromAnyThread(), obj, kind, slot, target);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot,
|
||||
const Value &target)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
preconditionForWriteBarrierPost(obj, kind, slot, target);
|
||||
#endif
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (target.isObject()) {
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->putSlot(obj, kind, slot, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void post(JSObject *owner, Kind kind, uint32_t slot, const Value &target) {
|
||||
JS_ASSERT(preconditionForWriteBarrierPost(owner, kind, slot, target));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (this->value.isObject()) {
|
||||
gc::Cell *cell = reinterpret_cast<gc::Cell *>(&this->value.toObject());
|
||||
if (cell->storeBuffer())
|
||||
cell->storeBuffer()->putSlotFromAnyThread(owner, kind, slot, 1);
|
||||
}
|
||||
#endif
|
||||
void post(JSObject *owner, Kind kind, uint32_t slot, Value target) {
|
||||
HeapSlot::writeBarrierPost(owner, kind, slot, target);
|
||||
}
|
||||
|
||||
void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target) {
|
||||
HeapSlot::writeBarrierPost(rt, owner, kind, slot, target);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -111,8 +111,6 @@ struct Cell
|
|||
inline JSRuntime *runtimeFromAnyThread() const;
|
||||
inline JS::shadow::Runtime *shadowRuntimeFromAnyThread() const;
|
||||
|
||||
inline StoreBuffer *storeBuffer() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool isAligned() const;
|
||||
inline bool isTenured() const;
|
||||
|
@ -610,16 +608,15 @@ struct ChunkTrailer
|
|||
{
|
||||
/* The index the chunk in the nursery, or LocationTenuredHeap. */
|
||||
uint32_t location;
|
||||
uint32_t padding;
|
||||
|
||||
/* The store buffer for writes to things in this chunk or nullptr. */
|
||||
StoreBuffer *storeBuffer;
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
uint32_t padding;
|
||||
#endif
|
||||
|
||||
JSRuntime *runtime;
|
||||
};
|
||||
|
||||
static_assert(sizeof(ChunkTrailer) == 2 * sizeof(uintptr_t) + sizeof(uint64_t),
|
||||
"ChunkTrailer size is incorrect.");
|
||||
static_assert(sizeof(ChunkTrailer) == 2 * sizeof(uintptr_t), "ChunkTrailer size is incorrect.");
|
||||
|
||||
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
|
||||
struct ChunkInfo
|
||||
|
@ -868,13 +865,9 @@ static_assert(sizeof(Chunk) == ChunkSize,
|
|||
static_assert(js::gc::ChunkMarkBitmapOffset == offsetof(Chunk, bitmap),
|
||||
"The hardcoded API bitmap offset must match the actual offset.");
|
||||
static_assert(js::gc::ChunkRuntimeOffset == offsetof(Chunk, info) +
|
||||
offsetof(ChunkInfo, trailer) +
|
||||
offsetof(ChunkTrailer, runtime),
|
||||
offsetof(ChunkInfo, trailer) +
|
||||
offsetof(ChunkTrailer, runtime),
|
||||
"The hardcoded API runtime offset must match the actual offset.");
|
||||
static_assert(js::gc::ChunkLocationOffset == offsetof(Chunk, info) +
|
||||
offsetof(ChunkInfo, trailer) +
|
||||
offsetof(ChunkTrailer, location),
|
||||
"The hardcoded API location offset must match the actual offset.");
|
||||
|
||||
inline uintptr_t
|
||||
ArenaHeader::address() const
|
||||
|
@ -1104,12 +1097,6 @@ Cell::chunk() const
|
|||
return reinterpret_cast<Chunk *>(addr);
|
||||
}
|
||||
|
||||
inline StoreBuffer *
|
||||
Cell::storeBuffer() const
|
||||
{
|
||||
return chunk()->info.trailer.storeBuffer;
|
||||
}
|
||||
|
||||
inline bool
|
||||
InFreeList(ArenaHeader *aheader, void *thing)
|
||||
{
|
||||
|
|
|
@ -203,7 +203,6 @@ class Nursery
|
|||
|
||||
MOZ_ALWAYS_INLINE void initChunk(int chunkno) {
|
||||
NurseryChunkLayout &c = chunk(chunkno);
|
||||
c.trailer.storeBuffer = JS::shadow::Runtime::asShadowRuntime(runtime())->gcStoreBufferPtr();
|
||||
c.trailer.location = gc::ChunkLocationNursery;
|
||||
c.trailer.runtime = runtime();
|
||||
}
|
||||
|
|
|
@ -402,10 +402,6 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
return;
|
||||
}
|
||||
|
||||
case ID:
|
||||
MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
|
||||
return;
|
||||
|
||||
case VALVECTOR: {
|
||||
AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
|
||||
MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
|
|
|
@ -335,45 +335,39 @@ StoreBuffer::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSi
|
|||
JS_PUBLIC_API(void)
|
||||
JS::HeapCellPostBarrier(js::gc::Cell **cellp)
|
||||
{
|
||||
JS_ASSERT(cellp);
|
||||
JS_ASSERT(*cellp);
|
||||
StoreBuffer *storeBuffer = (*cellp)->storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putRelocatableCellFromAnyThread(cellp);
|
||||
JSRuntime *runtime = (*cellp)->runtimeFromMainThread();
|
||||
runtime->gc.storeBuffer.putRelocatableCell(cellp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::HeapCellRelocate(js::gc::Cell **cellp)
|
||||
{
|
||||
/* Called with old contents of *cellp before overwriting. */
|
||||
JS_ASSERT(cellp);
|
||||
/* Called with old contents of *pp before overwriting. */
|
||||
JS_ASSERT(*cellp);
|
||||
JSRuntime *runtime = (*cellp)->runtimeFromMainThread();
|
||||
runtime->gc.storeBuffer.removeRelocatableCellFromAnyThread(cellp);
|
||||
runtime->gc.storeBuffer.removeRelocatableCell(cellp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::HeapValuePostBarrier(JS::Value *valuep)
|
||||
{
|
||||
JS_ASSERT(valuep);
|
||||
JS_ASSERT(valuep->isMarkable());
|
||||
if (valuep->isObject()) {
|
||||
StoreBuffer *storeBuffer = valuep->toObject().storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putRelocatableValueFromAnyThread(valuep);
|
||||
}
|
||||
if (valuep->isString() && StringIsPermanentAtom(valuep->toString()))
|
||||
return;
|
||||
JSRuntime *runtime = static_cast<js::gc::Cell *>(valuep->toGCThing())->runtimeFromMainThread();
|
||||
runtime->gc.storeBuffer.putRelocatableValue(valuep);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::HeapValueRelocate(JS::Value *valuep)
|
||||
{
|
||||
/* Called with old contents of *valuep before overwriting. */
|
||||
JS_ASSERT(valuep);
|
||||
JS_ASSERT(valuep->isMarkable());
|
||||
if (valuep->isString() && valuep->toString()->isPermanentAtom())
|
||||
if (valuep->isString() && StringIsPermanentAtom(valuep->toString()))
|
||||
return;
|
||||
JSRuntime *runtime = static_cast<js::gc::Cell *>(valuep->toGCThing())->runtimeFromMainThread();
|
||||
runtime->gc.storeBuffer.removeRelocatableValueFromAnyThread(valuep);
|
||||
runtime->gc.storeBuffer.removeRelocatableValue(valuep);
|
||||
}
|
||||
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
|
||||
|
|
|
@ -244,8 +244,7 @@ class StoreBuffer
|
|||
bool operator!=(const CellPtrEdge &other) const { return edge != other.edge; }
|
||||
|
||||
bool maybeInRememberedSet(const Nursery &nursery) const {
|
||||
JS_ASSERT(nursery.isInside(*edge));
|
||||
return !nursery.isInside(edge);
|
||||
return !nursery.isInside(edge) && nursery.isInside(*edge);
|
||||
}
|
||||
|
||||
void mark(JSTracer *trc);
|
||||
|
@ -268,8 +267,7 @@ class StoreBuffer
|
|||
void *deref() const { return edge->isGCThing() ? edge->toGCThing() : nullptr; }
|
||||
|
||||
bool maybeInRememberedSet(const Nursery &nursery) const {
|
||||
JS_ASSERT(nursery.isInside(deref()));
|
||||
return !nursery.isInside(edge);
|
||||
return !nursery.isInside(edge) && nursery.isInside(deref());
|
||||
}
|
||||
|
||||
void mark(JSTracer *trc);
|
||||
|
@ -364,7 +362,8 @@ class StoreBuffer
|
|||
void *data;
|
||||
};
|
||||
|
||||
bool isOkayToUseBuffer() const {
|
||||
template <typename Edge>
|
||||
bool isOkayToUseBuffer(const Edge &edge) const {
|
||||
/*
|
||||
* Disabled store buffers may not have a valid state; e.g. when stored
|
||||
* inline in the ChunkTrailer.
|
||||
|
@ -383,8 +382,8 @@ class StoreBuffer
|
|||
}
|
||||
|
||||
template <typename Buffer, typename Edge>
|
||||
void putFromAnyThread(Buffer &buffer, const Edge &edge) {
|
||||
if (!isOkayToUseBuffer())
|
||||
void put(Buffer &buffer, const Edge &edge) {
|
||||
if (!isOkayToUseBuffer(edge))
|
||||
return;
|
||||
mozilla::ReentrancyGuard g(*this);
|
||||
if (edge.maybeInRememberedSet(nursery_))
|
||||
|
@ -392,8 +391,8 @@ class StoreBuffer
|
|||
}
|
||||
|
||||
template <typename Buffer, typename Edge>
|
||||
void unputFromAnyThread(Buffer &buffer, const Edge &edge) {
|
||||
if (!isOkayToUseBuffer())
|
||||
void unput(Buffer &buffer, const Edge &edge) {
|
||||
if (!isOkayToUseBuffer(edge))
|
||||
return;
|
||||
mozilla::ReentrancyGuard g(*this);
|
||||
buffer.unput(this, edge);
|
||||
|
@ -433,38 +432,30 @@ class StoreBuffer
|
|||
bool isAboutToOverflow() const { return aboutToOverflow_; }
|
||||
|
||||
/* Insert a single edge into the buffer/remembered set. */
|
||||
void putValueFromAnyThread(JS::Value *valuep) { putFromAnyThread(bufferVal, ValueEdge(valuep)); }
|
||||
void putCellFromAnyThread(Cell **cellp) { putFromAnyThread(bufferCell, CellPtrEdge(cellp)); }
|
||||
void putSlotFromAnyThread(JSObject *obj, int kind, int32_t start, int32_t count) {
|
||||
putFromAnyThread(bufferSlot, SlotsEdge(obj, kind, start, count));
|
||||
void putValue(JS::Value *valuep) { put(bufferVal, ValueEdge(valuep)); }
|
||||
void putCell(Cell **cellp) { put(bufferCell, CellPtrEdge(cellp)); }
|
||||
void putSlot(JSObject *obj, int kind, int32_t start, int32_t count) {
|
||||
put(bufferSlot, SlotsEdge(obj, kind, start, count));
|
||||
}
|
||||
void putWholeCell(Cell *cell) {
|
||||
JS_ASSERT(cell->isTenured());
|
||||
putFromAnyThread(bufferWholeCell, WholeCellEdges(cell));
|
||||
put(bufferWholeCell, WholeCellEdges(cell));
|
||||
}
|
||||
|
||||
/* Insert or update a single edge in the Relocatable buffer. */
|
||||
void putRelocatableValueFromAnyThread(JS::Value *valuep) {
|
||||
putFromAnyThread(bufferRelocVal, ValueEdge(valuep));
|
||||
}
|
||||
void removeRelocatableValueFromAnyThread(JS::Value *valuep) {
|
||||
unputFromAnyThread(bufferRelocVal, ValueEdge(valuep));
|
||||
}
|
||||
void putRelocatableCellFromAnyThread(Cell **cellp) {
|
||||
putFromAnyThread(bufferRelocCell, CellPtrEdge(cellp));
|
||||
}
|
||||
void removeRelocatableCellFromAnyThread(Cell **cellp) {
|
||||
unputFromAnyThread(bufferRelocCell, CellPtrEdge(cellp));
|
||||
}
|
||||
void putRelocatableValue(JS::Value *valuep) { put(bufferRelocVal, ValueEdge(valuep)); }
|
||||
void putRelocatableCell(Cell **cellp) { put(bufferRelocCell, CellPtrEdge(cellp)); }
|
||||
void removeRelocatableValue(JS::Value *valuep) { unput(bufferRelocVal, ValueEdge(valuep)); }
|
||||
void removeRelocatableCell(Cell **cellp) { unput(bufferRelocCell, CellPtrEdge(cellp)); }
|
||||
|
||||
/* Insert an entry into the generic buffer. */
|
||||
template <typename T>
|
||||
void putGeneric(const T &t) { putFromAnyThread(bufferGeneric, t);}
|
||||
void putGeneric(const T &t) { put(bufferGeneric, t);}
|
||||
|
||||
/* Insert or update a callback entry. */
|
||||
template <typename Key>
|
||||
void putCallback(void (*callback)(JSTracer *trc, Key *key, void *data), Key *key, void *data) {
|
||||
putFromAnyThread(bufferGeneric, CallbackRef<Key>(callback, key, data));
|
||||
put(bufferGeneric, CallbackRef<Key>(callback, key, data));
|
||||
}
|
||||
|
||||
/* Methods to mark the source of all edges in the store buffer. */
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Tests that earlier try notes don't interfere with later exception handling.
|
||||
|
||||
var g = newGlobal();
|
||||
g.debuggeeGlobal = this;
|
||||
g.eval("(" + function () {
|
||||
dbg = new Debugger(debuggeeGlobal);
|
||||
} + ")();");
|
||||
var myObj = { p1: 'a', }
|
||||
try {
|
||||
with(myObj) {
|
||||
do {
|
||||
throw value;
|
||||
} while(false);
|
||||
}
|
||||
} catch(e) {
|
||||
// The above is expected to throw.
|
||||
}
|
||||
|
||||
try {
|
||||
if(!(p1 === 1)) { }
|
||||
} catch (e) {
|
||||
// The above is expected to throw.
|
||||
}
|
|
@ -464,7 +464,7 @@ HandleExceptionIon(JSContext *cx, const InlineFrameIterator &frame, ResumeFromEx
|
|||
|
||||
static void
|
||||
HandleExceptionBaseline(JSContext *cx, const JitFrameIterator &frame, ResumeFromException *rfe,
|
||||
bool *calledDebugEpilogue)
|
||||
jsbytecode **unwoundScopeToPc, bool *calledDebugEpilogue)
|
||||
{
|
||||
JS_ASSERT(frame.isBaselineJS());
|
||||
JS_ASSERT(!*calledDebugEpilogue);
|
||||
|
@ -528,17 +528,8 @@ HandleExceptionBaseline(JSContext *cx, const JitFrameIterator &frame, ResumeFrom
|
|||
|
||||
// Unwind scope chain (pop block objects).
|
||||
if (cx->isExceptionPending()) {
|
||||
jsbytecode *unwindPc = script->main() + tn->start;
|
||||
UnwindScope(cx, si, unwindPc);
|
||||
|
||||
// If we still need to call DebugEpilogue, we must remember the pc
|
||||
// we unwound the scope chain to, as it will be out of sync with
|
||||
// the frame's actual pc.
|
||||
if (tn->kind != JSTRY_CATCH && tn->kind != JSTRY_FINALLY &&
|
||||
cx->compartment()->debugMode() && !*calledDebugEpilogue)
|
||||
{
|
||||
frame.baselineFrame()->setUnwoundScopeOverridePc(unwindPc);
|
||||
}
|
||||
*unwoundScopeToPc = script->main() + tn->start;
|
||||
UnwindScope(cx, si, *unwoundScopeToPc);
|
||||
}
|
||||
|
||||
// Compute base pointer and stack pointer.
|
||||
|
@ -670,7 +661,10 @@ HandleException(ResumeFromException *rfe)
|
|||
// It's invalid to call DebugEpilogue twice for the same frame.
|
||||
bool calledDebugEpilogue = false;
|
||||
|
||||
HandleExceptionBaseline(cx, iter, rfe, &calledDebugEpilogue);
|
||||
// Remember the pc we unwound the scope to.
|
||||
jsbytecode *unwoundScopeToPc = nullptr;
|
||||
|
||||
HandleExceptionBaseline(cx, iter, rfe, &unwoundScopeToPc, &calledDebugEpilogue);
|
||||
|
||||
// If we are propagating an exception through a frame with
|
||||
// on-stack recompile info, we should free the allocated
|
||||
|
@ -694,6 +688,12 @@ HandleException(ResumeFromException *rfe)
|
|||
iter.baselineFrame()->unsetPushedSPSFrame();
|
||||
|
||||
if (cx->compartment()->debugMode() && !calledDebugEpilogue) {
|
||||
// If we still need to call the DebugEpilogue, we must
|
||||
// remember the pc we unwound the scope chain to, as it will
|
||||
// be out of sync with the frame's actual pc.
|
||||
if (unwoundScopeToPc)
|
||||
iter.baselineFrame()->setUnwoundScopeOverridePc(unwoundScopeToPc);
|
||||
|
||||
// If DebugEpilogue returns |true|, we have to perform a forced
|
||||
// return, e.g. return frame->returnValue() to the caller.
|
||||
BaselineFrame *frame = iter.baselineFrame();
|
||||
|
|
|
@ -107,7 +107,6 @@ class JS_PUBLIC_API(AutoGCRooter) {
|
|||
SHAPEVECTOR = -4, /* js::AutoShapeVector */
|
||||
IDARRAY = -6, /* js::AutoIdArray */
|
||||
DESCRIPTORS = -7, /* js::AutoPropDescArrayRooter */
|
||||
ID = -9, /* js::AutoIdRooter */
|
||||
VALVECTOR = -10, /* js::AutoValueVector */
|
||||
IDVECTOR = -13, /* js::AutoIdVector */
|
||||
OBJVECTOR = -14, /* js::AutoObjectVector */
|
||||
|
@ -839,31 +838,6 @@ INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str);
|
|||
|
||||
namespace JS {
|
||||
|
||||
class AutoIdRooter : private AutoGCRooter
|
||||
{
|
||||
public:
|
||||
explicit AutoIdRooter(JSContext *cx, jsid aId = INT_TO_JSID(0)
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, ID), id_(aId)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
jsid id() {
|
||||
return id_;
|
||||
}
|
||||
|
||||
jsid * addr() {
|
||||
return &id_;
|
||||
}
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
jsid id_;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
// Container class for passing in script source buffers to the JS engine. This
|
||||
// not only groups the buffer and length values, it also provides a way to
|
||||
// optionally pass ownership of the buffer to the JS engine without copying.
|
||||
|
|
|
@ -789,7 +789,6 @@ Chunk::init(JSRuntime *rt)
|
|||
|
||||
/* Initialize the chunk info. */
|
||||
info.age = 0;
|
||||
info.trailer.storeBuffer = nullptr;
|
||||
info.trailer.location = ChunkLocationTenuredHeap;
|
||||
info.trailer.runtime = rt;
|
||||
|
||||
|
|
|
@ -2293,8 +2293,8 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
|||
* below, in common with the other case.
|
||||
*/
|
||||
for (size_t i = 0; i < a->numFixedSlots(); ++i) {
|
||||
HeapSlot::writeBarrierPost(a, HeapSlot::Slot, i, a->getSlot(i));
|
||||
HeapSlot::writeBarrierPost(b, HeapSlot::Slot, i, b->getSlot(i));
|
||||
HeapSlot::writeBarrierPost(cx->runtime(), a, HeapSlot::Slot, i, a->getSlot(i));
|
||||
HeapSlot::writeBarrierPost(cx->runtime(), b, HeapSlot::Slot, i, b->getSlot(i));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
|
|
@ -187,7 +187,7 @@ DenseRangeWriteBarrierPost(JSRuntime *rt, JSObject *obj, uint32_t start, uint32_
|
|||
#ifdef JSGC_GENERATIONAL
|
||||
if (count > 0) {
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->putSlotFromAnyThread(obj, HeapSlot::Element, start, count);
|
||||
shadowRuntime->gcStoreBufferPtr()->putSlot(obj, HeapSlot::Element, start, count);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -223,13 +223,12 @@ JSObject::ensureDenseInitializedLengthNoPackedCheck(js::ThreadSafeContext *cx, u
|
|||
uint32_t &initlen = getElementsHeader()->initializedLength;
|
||||
|
||||
if (initlen < index + extra) {
|
||||
JSRuntime *rt = runtimeFromAnyThread();
|
||||
size_t offset = initlen;
|
||||
for (js::HeapSlot *sp = elements + initlen;
|
||||
sp != elements + (index + extra);
|
||||
sp++, offset++)
|
||||
{
|
||||
sp->init(this, js::HeapSlot::Element, offset, js::MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
sp->init(rt, this, js::HeapSlot::Element, offset, js::MagicValue(JS_ELEMENTS_HOLE));
|
||||
initlen = index + extra;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,22 +264,24 @@ js::ObjectImpl::initializeSlotRange(uint32_t start, uint32_t length)
|
|||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
|
||||
JSRuntime *rt = runtimeFromAnyThread();
|
||||
uint32_t offset = start;
|
||||
for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
|
||||
sp->init(this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
|
||||
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
|
||||
for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
|
||||
sp->init(this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
|
||||
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
|
||||
}
|
||||
|
||||
void
|
||||
js::ObjectImpl::initSlotRange(uint32_t start, const Value *vector, uint32_t length)
|
||||
{
|
||||
JSRuntime *rt = runtimeFromAnyThread();
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
|
||||
sp->init(this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
|
||||
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
|
||||
for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
|
||||
sp->init(this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
|
||||
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -840,12 +840,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
|||
|
||||
void privateWriteBarrierPost(void **pprivate) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
js::gc::Cell **cellp = reinterpret_cast<js::gc::Cell **>(pprivate);
|
||||
JS_ASSERT(cellp);
|
||||
JS_ASSERT(*cellp);
|
||||
js::gc::StoreBuffer *storeBuffer = (*cellp)->storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putCellFromAnyThread(cellp);
|
||||
shadowRuntimeFromAnyThread()->gcStoreBufferPtr()->putCell(reinterpret_cast<js::gc::Cell **>(pprivate));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -949,43 +944,30 @@ BarrieredCell<ObjectImpl>::isNullLike(ObjectImpl *obj)
|
|||
|
||||
template<>
|
||||
/* static */ inline void
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPost(ObjectImpl *obj, void *cellp)
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPost(ObjectImpl *obj, void *addr)
|
||||
{
|
||||
JS_ASSERT(cellp);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (IsNullTaggedPointer(obj))
|
||||
return;
|
||||
JS_ASSERT(obj == *static_cast<ObjectImpl **>(cellp));
|
||||
gc::StoreBuffer *storeBuffer = obj->storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putCellFromAnyThread(static_cast<Cell **>(cellp));
|
||||
obj->shadowRuntimeFromAnyThread()->gcStoreBufferPtr()->putCell((Cell **)addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
/* static */ inline void
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPostRelocate(ObjectImpl *obj, void *cellp)
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPostRelocate(ObjectImpl *obj, void *addr)
|
||||
{
|
||||
JS_ASSERT(cellp);
|
||||
JS_ASSERT(obj);
|
||||
JS_ASSERT(obj == *static_cast<ObjectImpl **>(cellp));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
gc::StoreBuffer *storeBuffer = obj->storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putRelocatableCellFromAnyThread(static_cast<Cell **>(cellp));
|
||||
obj->shadowRuntimeFromAnyThread()->gcStoreBufferPtr()->putRelocatableCell((Cell **)addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
/* static */ inline void
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPostRemove(ObjectImpl *obj, void *cellp)
|
||||
BarrieredCell<ObjectImpl>::writeBarrierPostRemove(ObjectImpl *obj, void *addr)
|
||||
{
|
||||
JS_ASSERT(cellp);
|
||||
JS_ASSERT(obj);
|
||||
JS_ASSERT(obj == *static_cast<ObjectImpl **>(cellp));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
obj->shadowRuntimeFromAnyThread()->gcStoreBufferPtr()->removeRelocatableCellFromAnyThread(
|
||||
static_cast<Cell **>(cellp));
|
||||
obj->shadowRuntimeFromAnyThread()->gcStoreBufferPtr()->removeRelocatableCell((Cell **)addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -525,12 +525,8 @@ static inline void
|
|||
GetterSetterWriteBarrierPost(JSRuntime *rt, JSObject **objp)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(objp);
|
||||
JS_ASSERT(*objp);
|
||||
gc::Cell **cellp = reinterpret_cast<gc::Cell **>(objp);
|
||||
gc::StoreBuffer *storeBuffer = (*cellp)->storeBuffer();
|
||||
if (storeBuffer)
|
||||
storeBuffer->putRelocatableCellFromAnyThread(cellp);
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->putRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -539,7 +535,7 @@ GetterSetterWriteBarrierPostRemove(JSRuntime *rt, JSObject **objp)
|
|||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->removeRelocatableCellFromAnyThread(reinterpret_cast<gc::Cell **>(objp));
|
||||
shadowRuntime->gcStoreBufferPtr()->removeRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -139,15 +139,15 @@ InterpreterFrame::writeBarrierPost()
|
|||
{
|
||||
/* This needs to follow the same rules as in InterpreterFrame::mark. */
|
||||
if (scopeChain_)
|
||||
JSObject::writeBarrierPost(scopeChain_, &scopeChain_);
|
||||
JSObject::writeBarrierPost(scopeChain_, (void *)&scopeChain_);
|
||||
if (flags_ & HAS_ARGS_OBJ)
|
||||
JSObject::writeBarrierPost(argsObj_, &argsObj_);
|
||||
JSObject::writeBarrierPost(argsObj_, (void *)&argsObj_);
|
||||
if (isFunctionFrame()) {
|
||||
JSFunction::writeBarrierPost(exec.fun, &exec.fun);
|
||||
JSFunction::writeBarrierPost(exec.fun, (void *)&exec.fun);
|
||||
if (isEvalFrame())
|
||||
JSScript::writeBarrierPost(u.evalScript, &u.evalScript);
|
||||
JSScript::writeBarrierPost(u.evalScript, (void *)&u.evalScript);
|
||||
} else {
|
||||
JSScript::writeBarrierPost(exec.script, &exec.script);
|
||||
JSScript::writeBarrierPost(exec.script, (void *)&exec.script);
|
||||
}
|
||||
if (hasReturnValue())
|
||||
HeapValue::writeBarrierPost(rval_, &rval_);
|
||||
|
|
|
@ -1372,6 +1372,9 @@ mozJSComponentLoader::Unload(const nsACString & aLocation)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mReuseLoaderGlobal, "Module unloading not supported when "
|
||||
"compartment sharing is enabled");
|
||||
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -493,45 +493,24 @@ xpc::HasInstance(JSContext *cx, HandleObject objArg, const nsID *iid, bool *bp)
|
|||
if (!obj)
|
||||
return NS_OK;
|
||||
|
||||
if (IsDOMObject(obj)) {
|
||||
// Not all DOM objects implement nsISupports. But if they don't,
|
||||
// there's nothing to do in this HasInstance hook.
|
||||
nsISupports *identity = UnwrapDOMObjectToISupports(obj);
|
||||
if (!identity)
|
||||
return NS_OK;;
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
identity->QueryInterface(*iid, getter_AddRefs(supp));
|
||||
*bp = supp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mozilla::jsipc::JavaScriptParent::IsCPOW(obj))
|
||||
return mozilla::jsipc::JavaScriptParent::InstanceOf(obj, iid, bp);
|
||||
|
||||
MOZ_ASSERT(IS_WN_REFLECTOR(obj));
|
||||
XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
|
||||
if (!other_wrapper)
|
||||
nsISupports *identity = UnwrapReflectorToISupports(obj);
|
||||
if (!identity)
|
||||
return NS_OK;
|
||||
|
||||
// We'll trust the interface set of the wrapper if this is known
|
||||
// to be an interface that the objects *expects* to be able to
|
||||
// handle.
|
||||
if (other_wrapper->HasInterfaceNoQI(*iid)) {
|
||||
*bp = true;
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
identity->QueryInterface(*iid, getter_AddRefs(supp));
|
||||
*bp = supp;
|
||||
|
||||
// Otherwise, we'll end up Querying the native object to be sure.
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
|
||||
AutoMarkingNativeInterfacePtr iface(ccx);
|
||||
iface = XPCNativeInterface::GetNewOrUsed(iid);
|
||||
|
||||
nsresult findResult = NS_OK;
|
||||
if (iface && other_wrapper->FindTearOff(iface, false, &findResult))
|
||||
*bp = true;
|
||||
if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
|
||||
return findResult;
|
||||
// Our old HasInstance implementation operated by invoking FindTearOff on
|
||||
// XPCWrappedNatives, and various bits of chrome JS came to depend on
|
||||
// |instanceof| doing an implicit QI if it succeeds. Do a drive-by QI to
|
||||
// preserve that behavior. This is just a compatibility hack, so we don't
|
||||
// really care if it fails.
|
||||
if (IS_WN_REFLECTOR(obj))
|
||||
(void) XPCWrappedNative::Get(obj)->FindTearOff(*iid);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1431,6 +1431,14 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface,
|
|||
return to;
|
||||
}
|
||||
|
||||
XPCWrappedNativeTearOff*
|
||||
XPCWrappedNative::FindTearOff(const nsIID& iid) {
|
||||
AutoJSContext cx;
|
||||
AutoMarkingNativeInterfacePtr iface(cx);
|
||||
iface = XPCNativeInterface::GetNewOrUsed(&iid);
|
||||
return iface ? FindTearOff(iface) : nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XPCWrappedNative::InitTearOff(XPCWrappedNativeTearOff* aTearOff,
|
||||
XPCNativeInterface* aInterface,
|
||||
|
|
|
@ -628,28 +628,34 @@ nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
xpc::UnwrapReflectorToISupports(JSObject *reflector)
|
||||
{
|
||||
// Unwrap security wrappers, if allowed.
|
||||
reflector = js::CheckedUnwrap(reflector, /* stopAtOuter = */ false);
|
||||
if (!reflector)
|
||||
return nullptr;
|
||||
|
||||
// Try XPCWrappedNatives.
|
||||
if (IS_WN_REFLECTOR(reflector)) {
|
||||
XPCWrappedNative *wn = XPCWrappedNative::Get(reflector);
|
||||
if (!wn)
|
||||
return nullptr;
|
||||
return wn->Native();
|
||||
}
|
||||
|
||||
// Try DOM objects.
|
||||
nsCOMPtr<nsISupports> canonical =
|
||||
do_QueryInterface(mozilla::dom::UnwrapDOMObjectToISupports(reflector));
|
||||
return canonical;
|
||||
}
|
||||
|
||||
/* nsISupports getNativeOfWrapper(in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */
|
||||
NS_IMETHODIMP_(nsISupports*)
|
||||
nsXPConnect::GetNativeOfWrapper(JSContext *aJSContext,
|
||||
JSObject *aJSObj)
|
||||
{
|
||||
MOZ_ASSERT(aJSContext, "bad param");
|
||||
MOZ_ASSERT(aJSObj, "bad param");
|
||||
|
||||
aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtOuter = */ false);
|
||||
if (!aJSObj) {
|
||||
JS_ReportError(aJSContext, "Permission denied to get native of security wrapper");
|
||||
return nullptr;
|
||||
}
|
||||
if (IS_WN_REFLECTOR(aJSObj)) {
|
||||
if (XPCWrappedNative *wn = XPCWrappedNative::Get(aJSObj))
|
||||
return wn->Native();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> canonical =
|
||||
do_QueryInterface(mozilla::dom::UnwrapDOMObjectToISupports(aJSObj));
|
||||
return canonical;
|
||||
return UnwrapReflectorToISupports(aJSObj);
|
||||
}
|
||||
|
||||
/* nsIXPConnectWrappedNative getWrappedNativeOfNativeObject (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
|
||||
|
|
|
@ -2093,6 +2093,8 @@ public:
|
|||
XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
|
||||
bool needJSObject = false,
|
||||
nsresult* pError = nullptr);
|
||||
XPCWrappedNativeTearOff* FindTearOff(const nsIID& iid);
|
||||
|
||||
void Mark() const
|
||||
{
|
||||
mSet->Mark();
|
||||
|
@ -2540,6 +2542,9 @@ public:
|
|||
const nsID* iid,
|
||||
nsISupports* aOuter,
|
||||
nsresult* pErr);
|
||||
|
||||
// Note - This return the XPCWrappedNative, rather than the native itself,
|
||||
// for the WN case. You probably want UnwrapReflectorToISupports.
|
||||
static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
|
||||
|
||||
/**
|
||||
|
|
|
@ -413,6 +413,13 @@ Throw(JSContext *cx, nsresult rv);
|
|||
nsIGlobalObject *
|
||||
GetNativeForGlobal(JSObject *global);
|
||||
|
||||
/**
|
||||
* Returns the nsISupports native behind a given reflector (either DOM or
|
||||
* XPCWN).
|
||||
*/
|
||||
nsISupports *
|
||||
UnwrapReflectorToISupports(JSObject *reflector);
|
||||
|
||||
/**
|
||||
* In some cases a native object does not really belong to any compartment (XBL,
|
||||
* document created from by XHR of a worker, etc.). But when for some reason we
|
||||
|
|
|
@ -4646,26 +4646,26 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
|
|||
}
|
||||
|
||||
nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
|
||||
// Only prerender if the transformed frame's size is <= the
|
||||
// reference frame size (~viewport), allowing a 1/8th fuzz factor
|
||||
// for shadows, borders, etc.
|
||||
// Only prerender if the transformed frame's size (in the reference
|
||||
// frames coordinate space) is <= the reference frame size (~viewport),
|
||||
// allowing a 1/8th fuzz factor for shadows, borders, etc.
|
||||
refSize += nsSize(refSize.width / 8, refSize.height / 8);
|
||||
nsSize frameSize = aFrame->GetVisualOverflowRectRelativeToSelf().Size();
|
||||
if (frameSize <= refSize) {
|
||||
// Bug 717521 - pre-render max 4096 x 4096 device pixels.
|
||||
nscoord max = aFrame->PresContext()->DevPixelsToAppUnits(4096);
|
||||
nsRect visual = aFrame->GetVisualOverflowRect();
|
||||
if (visual.width <= max && visual.height <= max) {
|
||||
return true;
|
||||
}
|
||||
nsRect frameRect = aFrame->GetVisualOverflowRectRelativeToSelf();
|
||||
|
||||
frameRect =
|
||||
nsLayoutUtils::TransformFrameRectToAncestor(aFrame, frameRect,
|
||||
aBuilder->RootReferenceFrame());
|
||||
|
||||
if (frameRect.Size() <= refSize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aLogAnimations) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Performance warning: Async animation disabled because frame size (");
|
||||
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.width));
|
||||
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameRect.width));
|
||||
message.AppendLiteral(", ");
|
||||
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.height));
|
||||
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameRect.height));
|
||||
message.AppendLiteral(") is bigger than the viewport (");
|
||||
message.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.width));
|
||||
message.AppendLiteral(", ");
|
||||
|
|
|
@ -43,10 +43,7 @@ const unsigned int WebrtcAudioConduit::CODEC_PLNAME_SIZE = 32;
|
|||
mozilla::RefPtr<AudioSessionConduit> AudioSessionConduit::Create(AudioSessionConduit *aOther)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// unit tests create their own "main thread"
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
#endif
|
||||
|
||||
WebrtcAudioConduit* obj = new WebrtcAudioConduit();
|
||||
if(obj->Init(static_cast<WebrtcAudioConduit*>(aOther)) != kMediaConduitNoError)
|
||||
|
@ -64,10 +61,7 @@ mozilla::RefPtr<AudioSessionConduit> AudioSessionConduit::Create(AudioSessionCon
|
|||
*/
|
||||
WebrtcAudioConduit::~WebrtcAudioConduit()
|
||||
{
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// unit tests create their own "main thread"
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
#endif
|
||||
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
|
|
|
@ -39,10 +39,7 @@ const unsigned int WebrtcVideoConduit::CODEC_PLNAME_SIZE = 32;
|
|||
*/
|
||||
mozilla::RefPtr<VideoSessionConduit> VideoSessionConduit::Create(VideoSessionConduit *aOther)
|
||||
{
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// unit tests create their own "main thread"
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
#endif
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
WebrtcVideoConduit* obj = new WebrtcVideoConduit();
|
||||
|
@ -58,10 +55,7 @@ mozilla::RefPtr<VideoSessionConduit> VideoSessionConduit::Create(VideoSessionCon
|
|||
|
||||
WebrtcVideoConduit::~WebrtcVideoConduit()
|
||||
{
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// unit tests create their own "main thread"
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
#endif
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
for(std::vector<VideoCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
|
|
|
@ -193,23 +193,14 @@ nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
|
|||
CSF::VcmSIPCCBinding::setMainThread(gMainThread);
|
||||
init_thread_monitor(&thread_ended_dispatcher, &join_waiter);
|
||||
} else {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(gMainThread == mainThread);
|
||||
#endif
|
||||
}
|
||||
|
||||
CSF::VcmSIPCCBinding::setSTSThread(stsThread);
|
||||
|
||||
nsresult res;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// This check fails on the unit tests because they do not
|
||||
// have the right thread behavior.
|
||||
bool on;
|
||||
res = gMainThread->IsOnCurrentThread(&on);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
MOZ_ASSERT(on);
|
||||
#endif
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gInstance) {
|
||||
CSFLogDebug(logTag, "Creating PeerConnectionCtx");
|
||||
|
|
|
@ -193,9 +193,7 @@ public:
|
|||
WrappableJSErrorResult(WrappableJSErrorResult &other) : mRv(), isCopy(true) {}
|
||||
~WrappableJSErrorResult() {
|
||||
if (isCopy) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
operator JSErrorResult &() { return mRv; }
|
||||
|
@ -707,9 +705,7 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
|||
|
||||
// Invariant: we receive configuration one way or the other but not both (XOR)
|
||||
MOZ_ASSERT(!aConfiguration != !aRTCConfiguration);
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
#endif
|
||||
MOZ_ASSERT(aThread);
|
||||
mThread = do_QueryInterface(aThread);
|
||||
|
||||
|
|
|
@ -962,18 +962,18 @@ class SignalingAgent {
|
|||
WrapRunnable(this, &SignalingAgent::Close));
|
||||
}
|
||||
|
||||
void Init_m(nsCOMPtr<nsIThread> thread)
|
||||
void Init_m()
|
||||
{
|
||||
pObserver = new TestObserver(pc->pcImpl(), name);
|
||||
ASSERT_TRUE(pObserver);
|
||||
|
||||
ASSERT_EQ(pc->Initialize(pObserver, nullptr, cfg_, thread), NS_OK);
|
||||
ASSERT_EQ(pc->Initialize(pObserver, nullptr, cfg_, gMainThread), NS_OK);
|
||||
}
|
||||
|
||||
void Init(nsCOMPtr<nsIThread> thread)
|
||||
void Init()
|
||||
{
|
||||
mozilla::SyncRunnable::DispatchToThread(thread,
|
||||
WrapRunnable(this, &SignalingAgent::Init_m, thread));
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnable(this, &SignalingAgent::Init_m));
|
||||
|
||||
ASSERT_TRUE_WAIT(sipcc_state() == PCImplSipccState::Started,
|
||||
kDefaultTimeout);
|
||||
|
@ -1555,7 +1555,7 @@ class SignalingAgentTest : public ::testing::Test {
|
|||
ScopedDeletePtr<SignalingAgent> agent(
|
||||
new SignalingAgent("agent", stun_addr, stun_port));
|
||||
|
||||
agent->Init(gMainThread);
|
||||
agent->Init();
|
||||
|
||||
if (wait_for_gather) {
|
||||
if (!agent->WaitForGatherAllowFail())
|
||||
|
@ -1609,8 +1609,8 @@ public:
|
|||
a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_);
|
||||
a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_);
|
||||
|
||||
a1_->Init(gMainThread);
|
||||
a2_->Init(gMainThread);
|
||||
a1_->Init();
|
||||
a2_->Init();
|
||||
|
||||
if (wait_for_gather_) {
|
||||
WaitForGather();
|
||||
|
|
|
@ -179,12 +179,17 @@ class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
|
|||
}
|
||||
};
|
||||
|
||||
namespace external {
|
||||
|
||||
/**
|
||||
* AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
|
||||
* reference counter.
|
||||
*
|
||||
* NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
|
||||
* instead.
|
||||
*/
|
||||
template<typename T>
|
||||
class AtomicRefCounted : public detail::RefCounted<T, detail::AtomicRefCount>
|
||||
class AtomicRefCounted : public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
|
||||
{
|
||||
public:
|
||||
~AtomicRefCounted() {
|
||||
|
@ -193,6 +198,8 @@ class AtomicRefCounted : public detail::RefCounted<T, detail::AtomicRefCount>
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* RefPtr points to a refcounted thing that has AddRef and Release
|
||||
* methods to increase/decrease the refcount, respectively. After a
|
||||
|
|
|
@ -18,6 +18,8 @@ import org.mozilla.gecko.AndroidGamepadManager;
|
|||
import org.mozilla.gecko.DynamicToolbar.PinReason;
|
||||
import org.mozilla.gecko.DynamicToolbar.VisibilityTransition;
|
||||
import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.animation.PropertyAnimator;
|
||||
import org.mozilla.gecko.animation.ViewHelper;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
|
@ -485,6 +487,8 @@ abstract public class BrowserApp extends GeckoApp
|
|||
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
// Show the target URL immediately in the toolbar.
|
||||
mBrowserToolbar.setTitle(intent.getDataString());
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT);
|
||||
}
|
||||
|
||||
((GeckoApp.MainLayout) mMainLayout).setTouchEventInterceptor(new HideTabsTouchListener());
|
||||
|
@ -643,6 +647,12 @@ abstract public class BrowserApp extends GeckoApp
|
|||
if (isHomePagerVisible()) {
|
||||
mHomePager.onToolbarFocusChange(hasFocus);
|
||||
}
|
||||
|
||||
if (hasFocus) {
|
||||
Telemetry.startUISession(TelemetryContract.Session.URLBAR_FOCUSED);
|
||||
} else {
|
||||
Telemetry.stopUISession(TelemetryContract.Session.URLBAR_FOCUSED);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -751,6 +761,7 @@ abstract public class BrowserApp extends GeckoApp
|
|||
String text = Clipboard.getText();
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
Tabs.getInstance().loadUrl(text);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -942,6 +953,9 @@ abstract public class BrowserApp extends GeckoApp
|
|||
|
||||
GeckoAppShell.openUriExternal(url, "text/plain", "", "",
|
||||
Intent.ACTION_SEND, tab.getDisplayTitle());
|
||||
|
||||
// Context: Sharing via chrome list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1613,6 +1627,8 @@ abstract public class BrowserApp extends GeckoApp
|
|||
// If the URL doesn't look like a search query, just load it.
|
||||
if (!StringUtils.isSearchQuery(url, true)) {
|
||||
Tabs.getInstance().loadUrl(url, Tabs.LOADURL_USER_ENTERED);
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1638,6 +1654,7 @@ abstract public class BrowserApp extends GeckoApp
|
|||
// using the default search engine.
|
||||
if (TextUtils.isEmpty(keywordUrl)) {
|
||||
Tabs.getInstance().loadUrl(url, Tabs.LOADURL_USER_ENTERED);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1646,6 +1663,7 @@ abstract public class BrowserApp extends GeckoApp
|
|||
// Otherwise, construct a search query from the bookmark keyword.
|
||||
final String searchUrl = keywordUrl.replace("%s", URLEncoder.encode(keywordSearch));
|
||||
Tabs.getInstance().loadUrl(searchUrl, Tabs.LOADURL_USER_ENTERED);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, "", "keyword");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2538,9 +2556,11 @@ abstract public class BrowserApp extends GeckoApp
|
|||
return;
|
||||
}
|
||||
|
||||
// Dismiss editing mode if the user is loading a URL from an external app.
|
||||
if (Intent.ACTION_VIEW.equals(action)) {
|
||||
// Dismiss editing mode if the user is loading a URL from an external app.
|
||||
mBrowserToolbar.cancelEdit();
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -607,6 +607,9 @@ public abstract class GeckoApp
|
|||
} else if (event.equals("Share:Text")) {
|
||||
String text = message.getString("text");
|
||||
GeckoAppShell.openUriExternal(text, "text/plain", "", "", Intent.ACTION_SEND, "");
|
||||
|
||||
// Context: Sharing via chrome list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
} else if (event.equals("Image:SetAs")) {
|
||||
String src = message.getString("url");
|
||||
setImageAs(src);
|
||||
|
|
|
@ -30,8 +30,22 @@ public interface TelemetryContract {
|
|||
// Set default panel.
|
||||
public static final String PANEL_SET_DEFAULT = "setdefault.1";
|
||||
|
||||
// Sharing content.
|
||||
public static final String SHARE = "share.1";
|
||||
|
||||
// Sanitizing private data.
|
||||
public static final String SANITIZE = "sanitize.1";
|
||||
|
||||
// Saving a resource (reader, bookmark, etc) for viewing later.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String SAVE = "save.1";
|
||||
|
||||
// Stop holding a resource (reader, bookmark, etc) for viewing later.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String UNSAVE = "unsave.1";
|
||||
|
||||
// Loading a URL.
|
||||
public static final String LOAD_URL = "loadurl.1";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,8 +53,29 @@ public interface TelemetryContract {
|
|||
* Telemetry.sendUIEvent() as the "method" parameter.
|
||||
*/
|
||||
public interface Method {
|
||||
// Action triggered from a list.
|
||||
public static final String LIST = "list";
|
||||
|
||||
// Action triggered from a button.
|
||||
public static final String BUTTON = "button";
|
||||
|
||||
// Action triggered from a dialog.
|
||||
public static final String DIALOG = "dialog";
|
||||
|
||||
// Action occurred via an intent.
|
||||
public static final String INTENT = "intent";
|
||||
|
||||
// Action occurred via a context menu.
|
||||
public static final String CONTEXT_MENU = "contextmenu";
|
||||
|
||||
// Action triggered from a view grid item, like a thumbnail.
|
||||
public static final String GRID_ITEM = "griditem";
|
||||
|
||||
// Action triggered from a view list item, like a row of a list.
|
||||
public static final String LIST_ITEM = "listitem";
|
||||
|
||||
// Action triggered from a suggestion provided to the user.
|
||||
public static final String SUGGESTION = "suggestion";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,6 +89,16 @@ public interface TelemetryContract {
|
|||
// Started when a user enters a given home panel.
|
||||
// Session name is dynamic, encoded as "homepanel.1:<panel_id>"
|
||||
public static final String HOME_PANEL = "homepanel.1:";
|
||||
|
||||
// Started when a Reader viewer becomes active in the foreground.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String READER = "reader.1";
|
||||
|
||||
// URL bar focused.
|
||||
public static final String URLBAR_FOCUSED = "urlbar.1:";
|
||||
|
||||
// Awesomescreen frecency search is active.
|
||||
public static final String FRECENCY = "frecency.1:";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,8 @@ package org.mozilla.gecko.home;
|
|||
import java.util.EnumSet;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
|
@ -91,6 +93,8 @@ public class BookmarksListView extends HomeListView
|
|||
// Otherwise, just open the URL
|
||||
final String url = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
|
||||
// This item is a TwoLinePageRow, so we allow switch-to-tab.
|
||||
getOnUrlOpenListener().onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.mozilla.gecko.PrefsHelper;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.SearchEngine;
|
||||
|
@ -220,6 +222,20 @@ public class BrowserSearch extends HomeFragment
|
|||
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Telemetry.startUISession(TelemetryContract.Session.FRECENCY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
Telemetry.stopUISession(TelemetryContract.Session.FRECENCY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
// All list views are styled to look the same with a global activity theme.
|
||||
|
@ -264,6 +280,11 @@ public class BrowserSearch extends HomeFragment
|
|||
final Cursor c = mAdapter.getCursor(position);
|
||||
final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
|
||||
|
||||
// The "urlbar" and "frecency" sessions can be open at the same time. Use the LIST_ITEM
|
||||
// method to set this LOAD_URL event apart from the case where the user commits what's in
|
||||
// the url bar.
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM);
|
||||
|
||||
// This item is a TwoLinePageRow, so we allow switch-to-tab.
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.mozilla.gecko.GeckoProfile;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ReaderModeUtils;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
|
@ -132,6 +134,9 @@ abstract class HomeFragment extends Fragment {
|
|||
} else {
|
||||
GeckoAppShell.openUriExternal(info.url, SHARE_MIME_TYPE, "", "",
|
||||
Intent.ACTION_SEND, info.getDisplayTitle());
|
||||
|
||||
// Context: Sharing via chrome homepage contextmenu list (home session should be active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +162,8 @@ abstract class HomeFragment extends Fragment {
|
|||
if (item.getItemId() == R.id.home_open_private_tab)
|
||||
flags |= Tabs.LOADURL_PRIVATE;
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU);
|
||||
|
||||
final String url = (info.isInReadingList() ? ReaderModeUtils.getAboutReaderForUrl(info.url) : info.url);
|
||||
|
||||
// Some pinned site items have "user-entered" urls. URLs entered in the PinSiteDialog are wrapped in
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.mozilla.gecko.AboutPages;
|
|||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.SessionParser;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.home.HomePager.OnNewTabsListener;
|
||||
|
||||
|
@ -110,6 +112,8 @@ public class LastTabsPanel extends HomeFragment {
|
|||
return;
|
||||
}
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
|
||||
final String url = c.getString(c.getColumnIndexOrThrow(Combined.URL));
|
||||
mNewTabsListener.onNewTabs(new String[] { url });
|
||||
}
|
||||
|
@ -206,6 +210,8 @@ public class LastTabsPanel extends HomeFragment {
|
|||
urls[c.getPosition()] = c.getString(c.getColumnIndexOrThrow(Combined.URL));
|
||||
} while (c.moveToNext());
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.BUTTON);
|
||||
|
||||
mNewTabsListener.onNewTabs(urls);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Date;
|
|||
import java.util.EnumSet;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
|
@ -98,6 +100,8 @@ public class MostRecentPanel extends HomeFragment {
|
|||
final Cursor c = mAdapter.getCursor(position);
|
||||
final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
|
||||
// This item is a TwoLinePageRow, so we allow switch-to-tab.
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.util.EnumSet;
|
|||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ReaderModeUtils;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
|
@ -105,6 +107,8 @@ public class ReadingListPanel extends HomeFragment {
|
|||
String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
|
||||
url = ReaderModeUtils.getAboutReaderForUrl(url);
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
|
||||
|
||||
// This item is a TwoLinePageRow, so we allow switch-to-tab.
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.home.BrowserSearch.OnEditSuggestionListener;
|
||||
import org.mozilla.gecko.home.BrowserSearch.OnSearchListener;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
|
@ -79,9 +81,16 @@ class SearchEngineRow extends AnimatedHeightLayout {
|
|||
// search for the term.
|
||||
if (v != mUserEnteredView && !StringUtils.isSearchQuery(suggestion, false)) {
|
||||
if (mUrlOpenListener != null) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.SUGGESTION, "url");
|
||||
|
||||
mUrlOpenListener.onUrlOpen(suggestion, EnumSet.noneOf(OnUrlOpenListener.Flags.class));
|
||||
}
|
||||
} else if (mSearchListener != null) {
|
||||
if (v == mUserEnteredView) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.SUGGESTION, "user");
|
||||
} else {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.SUGGESTION, "engine");
|
||||
}
|
||||
mSearchListener.onSearch(mSearchEngine, suggestion);
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +144,7 @@ class SearchEngineRow extends AnimatedHeightLayout {
|
|||
public void performUserEnteredSearch() {
|
||||
String searchTerm = getSuggestionTextFromView(mUserEnteredView);
|
||||
if (mSearchListener != null) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.SUGGESTION, "user");
|
||||
mSearchListener.onSearch(mSearchEngine, searchTerm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ package org.mozilla.gecko.home;
|
|||
import java.util.EnumSet;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.ThumbnailHelper;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.db.TopSitesCursorWrapper;
|
||||
|
@ -110,6 +112,8 @@ public class TopSitesGridView extends GridView {
|
|||
// If not, navigate to the page given by the url.
|
||||
if (!TextUtils.isEmpty(url)) {
|
||||
if (mUrlOpenListener != null) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.GRID_ITEM);
|
||||
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.noneOf(OnUrlOpenListener.Flags.class));
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -181,6 +181,8 @@ public class TopSitesPanel extends HomeFragment {
|
|||
|
||||
final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM);
|
||||
|
||||
// This item is a TwoLinePageRow, so we allow switch-to-tab.
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.menu.MenuItemActionView;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.menu.MenuItemActionView;
|
||||
import org.mozilla.gecko.widget.GeckoActionProvider;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
@ -197,6 +199,9 @@ public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
|
|||
@Override
|
||||
public void onIntentSelected(final Intent intent, final int p) {
|
||||
provider.chooseActivity(p);
|
||||
|
||||
// Context: Sharing via content contextmenu list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 408 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 454 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 532 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 566 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 648 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 666 B |
|
@ -19,6 +19,8 @@ import java.util.List;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.TabsAccessor;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
|
||||
/**
|
||||
* The actual list of synced tabs. This serves as the only child view of {@link RemoteTabsContainer}
|
||||
|
@ -68,6 +70,8 @@ class RemoteTabsList extends ExpandableListView
|
|||
return true;
|
||||
}
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, "", "remote");
|
||||
|
||||
Tabs.getInstance().loadUrl(tab.get("url"), Tabs.LOADURL_NEW_TAB);
|
||||
autoHidePanel();
|
||||
return true;
|
||||
|
|
|
@ -48,7 +48,13 @@ let videoDiscoveryTests = [
|
|||
{ id: "with-sources-mp4", source: "http://mochi.test:8888/simple.mp4", text: "video with mp4 extension source child" },
|
||||
{ id: "with-sources-fail", pass: false, text: "video with no mp4 extension source child" },
|
||||
{ id: "with-sources-mimetype", source: "http://mochi.test:8888/simple-video-mp4", text: "video with mp4 mimetype source child" },
|
||||
{ id: "video-overlay", source: "http://mochi.test:8888/simple.mp4", text: "div overlay covering a simple video with mp4 src" }
|
||||
{ id: "video-overlay", source: "http://mochi.test:8888/simple.mp4", text: "div overlay covering a simple video with mp4 src" },
|
||||
|
||||
{ id: "opt-in-simple-mp4", source: "http://mochi.test:8888/simple.mp4", poster: "http://mochi.test:8888/simple.png", text: "simple video with mp4 src" },
|
||||
{ id: "opt-out-simple-mp4", pass: false, text: "simple video with mp4 src but opt-out" },
|
||||
{ id: "opt-in-simple-fail", pass: false, text: "simple video with opt-in but no mp4 src" },
|
||||
{ id: "opt-in-with-sources-mp4", source: "http://mochi.test:8888/simple.mp4", text: "opt-in video with mp4 extension source child" },
|
||||
{ id: "opt-out-with-sources-mp4", pass: false, text: "video with mp4 extension source child but opt-out" }
|
||||
];
|
||||
|
||||
function execute_video_test(test) {
|
||||
|
|
|
@ -56,5 +56,26 @@
|
|||
<video id="video-player" src="/simple.mp4"></video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PASS: opt-in and src uses a mp4 extension -->
|
||||
<video id="opt-in-simple-mp4" poster="/simple.png" src="/simple.mp4" x-webkit-airplay="allow"></video>
|
||||
|
||||
<!-- FAIL: opt-out and src uses a mp4 extension -->
|
||||
<video id="opt-out-simple-mp4" poster="/simple.png" src="/simple.mp4" x-webkit-airplay="deny"></video>
|
||||
|
||||
<!-- FAIL: opt-in and src uses a ogg extension -->
|
||||
<video id="opt-in-simple-fail" src="/simple.ogg" x-webkit-airplay="allow"></video>
|
||||
|
||||
<!-- PASS: video with opt-in and source list uses a mp4 extension -->
|
||||
<video id="opt-in-with-sources-mp4" x-webkit-airplay="allow">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.mp4">
|
||||
</video>
|
||||
|
||||
<!-- FAIL: video with opt-out and source list uses a mp4 extension -->
|
||||
<video id="opt-out-with-sources-mp4" x-webkit-airplay="deny">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.mp4">
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
package org.mozilla.gecko.widget;
|
||||
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.menu.MenuItemActionView;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -194,6 +196,9 @@ public class GeckoActionProvider {
|
|||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
chooseActivity(item.getItemId());
|
||||
|
||||
// Context: Sharing via chrome mainmenu list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -201,6 +206,9 @@ public class GeckoActionProvider {
|
|||
public void onClick(View view) {
|
||||
Integer index = (Integer) view.getTag();
|
||||
chooseActivity(index);
|
||||
|
||||
// Context: Sharing via chrome mainmenu and content contextmenu quickshare (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.BUTTON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче