Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-05-02 15:01:54 +02:00
Родитель 980facddb8 43960220d1
Коммит 0260e6f13c
169 изменённых файлов: 10030 добавлений и 1202 удалений

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

@ -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

8
content/canvas/src/CanvasRenderingContext2D.cpp Executable file → Normal file
Просмотреть файл

@ -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)

6
intl/icu/source/configure поставляемый
Просмотреть файл

@ -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

Двоичные данные
mobile/android/base/resources/drawable-hdpi/casting.png Normal file

Двоичный файл не отображается.

После

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

Двоичные данные
mobile/android/base/resources/drawable-hdpi/casting_active.png Normal file

Двоичный файл не отображается.

После

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

Двоичные данные
mobile/android/base/resources/drawable-mdpi/casting.png Normal file

Двоичный файл не отображается.

После

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

Двоичные данные
mobile/android/base/resources/drawable-mdpi/casting_active.png Normal file

Двоичный файл не отображается.

После

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

Двоичные данные
mobile/android/base/resources/drawable-xhdpi/casting.png Normal file

Двоичный файл не отображается.

После

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

Двоичные данные
mobile/android/base/resources/drawable-xhdpi/casting_active.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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);
}
}
}

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