Merge the last PGO-green inbound changest to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-10-30 10:48:44 -04:00
commit 498dad2875
298 changed files with 5451 additions and 2148 deletions

View File

@ -9,6 +9,7 @@
#include "InterfaceInitFuncs.h"
#include "nsMai.h"
#include "mozilla/Likely.h"
AtkSocketEmbedType AtkSocketAccessible::g_atk_socket_embed = NULL;
GType AtkSocketAccessible::g_atk_socket_type = G_TYPE_INVALID;
@ -105,7 +106,7 @@ void
mai_atk_component_iface_init(AtkComponentIface* aIface)
{
NS_ASSERTION(aIface, "Invalid Interface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->ref_accessible_at_point = RefAccessibleAtPoint;

View File

@ -9,6 +9,7 @@
#include "Accessible-inl.h"
#include "nsMai.h"
#include "Role.h"
#include "mozilla/Likely.h"
#include "nsString.h"
@ -116,7 +117,7 @@ void
actionInterfaceInitCB(AtkActionIface* aIface)
{
NS_ASSERTION(aIface, "Invalid aIface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->do_action = doActionCB;

View File

@ -10,6 +10,7 @@
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsMai.h"
#include "mozilla/Likely.h"
extern "C" {
@ -100,7 +101,7 @@ void
componentInterfaceInitCB(AtkComponentIface* aIface)
{
NS_ASSERTION(aIface, "Invalid Interface");
if(NS_UNLIKELY(!aIface))
if(MOZ_UNLIKELY(!aIface))
return;
/*

View File

@ -9,6 +9,7 @@
#include "AccessibleWrap.h"
#include "DocAccessible.h"
#include "nsMai.h"
#include "mozilla/Likely.h"
static const char* const kDocTypeName = "W3C-doctype";
static const char* const kDocUrlName = "DocURL";
@ -26,7 +27,7 @@ void
documentInterfaceInitCB(AtkDocumentIface *aIface)
{
NS_ASSERTION(aIface, "Invalid Interface");
if(NS_UNLIKELY(!aIface))
if(MOZ_UNLIKELY(!aIface))
return;
/*

View File

@ -10,6 +10,7 @@
#include "nsMai.h"
#include "nsString.h"
#include "mozilla/Likely.h"
extern "C" {
static void
@ -116,7 +117,7 @@ void
editableTextInterfaceInitCB(AtkEditableTextIface* aIface)
{
NS_ASSERTION(aIface, "Invalid aIface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->set_text_contents = setTextContentsCB;

View File

@ -7,6 +7,7 @@
#include "InterfaceInitFuncs.h"
#include "nsMaiHyperlink.h"
#include "mozilla/Likely.h"
extern "C" {
static AtkHyperlink*
@ -28,7 +29,7 @@ void
hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface)
{
NS_ASSERTION(aIface, "no interface!");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->get_hyperlink = getHyperlinkCB;

View File

@ -9,6 +9,7 @@
#include "HyperTextAccessible.h"
#include "nsMai.h"
#include "nsMaiHyperlink.h"
#include "mozilla/Likely.h"
extern "C" {
@ -70,7 +71,7 @@ void
hypertextInterfaceInitCB(AtkHypertextIface* aIface)
{
NS_ASSERTION(aIface, "no interface!");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->get_link = getLinkCB;

View File

@ -8,6 +8,7 @@
#include "AccessibleWrap.h"
#include "ImageAccessible.h"
#include "mozilla/Likely.h"
#include "nsMai.h"
using namespace mozilla;
@ -53,7 +54,7 @@ void
imageInterfaceInitCB(AtkImageIface* aIface)
{
NS_ASSERTION(aIface, "no interface!");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->get_image_position = getImagePositionCB;

View File

@ -8,6 +8,7 @@
#include "AccessibleWrap.h"
#include "nsMai.h"
#include "mozilla/Likely.h"
#include <atk/atk.h>
@ -96,7 +97,7 @@ void
selectionInterfaceInitCB(AtkSelectionIface* aIface)
{
NS_ASSERTION(aIface, "Invalid aIface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->add_selection = addSelectionCB;

View File

@ -15,6 +15,8 @@
#include "nsArrayUtils.h"
#include "mozilla/Likely.h"
using namespace mozilla::a11y;
extern "C" {
@ -293,7 +295,7 @@ void
tableInterfaceInitCB(AtkTableIface* aIface)
{
NS_ASSERTION(aIface, "no interface!");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->ref_at = refAtCB;

View File

@ -11,6 +11,8 @@
#include "nsIPersistentProperties2.h"
#include "mozilla/Likely.h"
using namespace mozilla::a11y;
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
@ -446,7 +448,7 @@ void
textInterfaceInitCB(AtkTextIface* aIface)
{
NS_ASSERTION(aIface, "Invalid aIface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->get_text = getTextCB;

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "InterfaceInitFuncs.h"
#include "mozilla/Likely.h"
#include "AccessibleWrap.h"
#include "nsMai.h"
@ -116,7 +117,7 @@ void
valueInterfaceInitCB(AtkValueIface* aIface)
{
NS_ASSERTION(aIface, "Invalid aIface");
if (NS_UNLIKELY(!aIface))
if (MOZ_UNLIKELY(!aIface))
return;
aIface->get_current_value = getCurrentValueCB;

View File

@ -250,6 +250,7 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
logging::Node("content", child);
}
logging::MsgEnd();
logging::Stack();
}
#endif
@ -269,6 +270,7 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
logging::Node("container", aContainer);
logging::Node("content", aChild);
logging::MsgEnd();
logging::Stack();
}
#endif

View File

@ -14,7 +14,7 @@ var gDumpToConsole = true;
*/
function testNames()
{
enableLogging("tree");
enableLogging("tree,stack");
var request = new XMLHttpRequest();
request.open("get", gNameRulesFileURL, false);

View File

@ -191,6 +191,7 @@ pref("app.creditsURL", "http://www.mozilla.org/credits/");
pref("app.featuresURL", "http://www.mozilla.com/%LOCALE%/b2g/features/");
pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/b2g/faq/");
// Whether we want to report crashes (headless)
//XXX Remove this pref when bug 801932 is fixed
pref("app.reportCrashes", true);
// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)

View File

@ -181,3 +181,15 @@ SettingsListener.observe('debug.dev-mode', false, function(value) {
SettingsListener.observe('privacy.donottrackheader.enabled', false, function(value) {
Services.prefs.setBoolPref('privacy.donottrackheader.enabled', value);
});
// =================== Crash Reporting ====================
SettingsListener.observe('app.reportCrashes', 'ask', function(value) {
if (value == 'always') {
Services.prefs.setBoolPref('app.reportCrashes', true);
} else if (value == 'never') {
Services.prefs.setBoolPref('app.reportCrashes', false);
} else {
Services.prefs.clearUserPref('app.reportCrashes');
}
});

View File

@ -72,26 +72,44 @@ var shell = {
return this.CrashSubmit;
},
reportCrash: function shell_reportCrash(aCrashID) {
reportCrash: function shell_reportCrash(isChrome, aCrashID) {
let crashID = aCrashID;
try {
if (crashID == undefined || crashID == "")
// For chrome crashes, we want to report the lastRunCrashID.
if (isChrome) {
crashID = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime).lastRunCrashID;
}
} catch(e) { }
if (Services.prefs.getBoolPref('app.reportCrashes') &&
crashID) {
Services.obs.addObserver(function observer(subject, topic, state) {
if (topic != "network:offline-status-changed")
// Bail if there isn't a valid crashID.
if (!crashID) {
return;
}
try {
// Check if we should automatically submit this crash.
if (Services.prefs.getBoolPref("app.reportCrashes")) {
this.submitCrash(crashID);
}
} catch (e) { }
// Let Gaia notify the user of the crash.
this.sendChromeEvent({
type: "handle-crash",
crashID: crashID,
chrome: isChrome
});
},
// This function submits a crash when we're online.
submitCrash: function shell_submitCrash(aCrashID) {
Services.obs.addObserver(function observer(subject, topic, state) {
if (state == 'online') {
shell.CrashSubmit.submit(crashID);
shell.CrashSubmit.submit(aCrashID);
Services.obs.removeObserver(observer, topic);
}
}
, "network:offline-status-changed", false);
}
}, "network:offline-status-changed", false);
},
get contentBrowser() {
@ -158,7 +176,7 @@ var shell = {
let manifestURL = this.manifestURL;
// <html:iframe id="homescreen"
// mozbrowser="true" mozallowfullscreen="true"
// mozbrowser="true" allowfullscreen="true"
// style="overflow: hidden; -moz-box-flex: 1; border: none;"
// src="data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;'>"/>
let browserFrame =
@ -166,7 +184,7 @@ var shell = {
browserFrame.setAttribute('id', 'homescreen');
browserFrame.setAttribute('mozbrowser', 'true');
browserFrame.setAttribute('mozapp', manifestURL);
browserFrame.setAttribute('mozallowfullscreen', 'true');
browserFrame.setAttribute('allowfullscreen', 'true');
browserFrame.setAttribute('style', "overflow: hidden; -moz-box-flex: 1; border: none;");
browserFrame.setAttribute('src', "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;");
document.getElementById('shell').appendChild(browserFrame);
@ -336,7 +354,7 @@ var shell = {
this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
this.reportCrash();
this.reportCrash(true);
let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
chromeWindow.browserDOMWindow = new nsBrowserAccess();
@ -771,16 +789,24 @@ window.addEventListener('ContentStart', function ss_onContentStart() {
(function contentCrashTracker() {
Services.obs.addObserver(function(aSubject, aTopic, aData) {
let cs = Cc["@mozilla.org/consoleservice;1"]
.getService(Ci.nsIConsoleService);
let props = aSubject.QueryInterface(Ci.nsIPropertyBag2);
if (props.hasKey("abnormal") && props.hasKey("dumpID")) {
shell.reportCrash(props.getProperty("dumpID"));
shell.reportCrash(false, props.getProperty("dumpID"));
}
},
"ipc:content-shutdown", false);
})();
// Listen for crashes submitted through the crash reporter UI.
window.addEventListener('ContentStart', function cr_onContentStart() {
let content = shell.contentBrowser.contentWindow;
content.addEventListener("mozContentEvent", function cr_onMozContentEvent(e) {
if (e.detail.type == "submit-crash" && e.detail.crashID) {
shell.submitCrash(e.detail.crashID);
}
});
});
window.addEventListener('ContentStart', function update_onContentStart() {
let updatePrompt = Cc["@mozilla.org/updates/update-prompt;1"]
.createInstance(Ci.nsIUpdatePrompt);

View File

@ -10,6 +10,15 @@
// From nsEventStateManager.cpp.
const MOUSE_SCROLL_ZOOM = 3;
Cu.import('resource://gre/modules/ContentPrefInstance.jsm');
function getContentPrefs(aWindow) {
let context = aWindow ? aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext) : null;
return new ContentPrefInstance(context);
}
/**
* Controls the "full zoom" setting and its site-specific preferences.
*/
@ -21,7 +30,7 @@ var FullZoom = {
// when first requested, then updated by the pref change listener as it changes.
// If there is no global value, then this should be undefined.
get globalValue() {
var globalValue = Services.contentPrefs.getPref(null, this.name);
var globalValue = getContentPrefs(gBrowser.contentDocument.defaultView).getPref(null, this.name);
if (typeof globalValue != "undefined")
globalValue = this._ensureValid(globalValue);
delete this.globalValue;
@ -55,7 +64,7 @@ var FullZoom = {
window.addEventListener("DOMMouseScroll", this, false);
// Register ourselves with the service so we know when our pref changes.
Services.contentPrefs.addObserver(this.name, this);
getContentPrefs().addObserver(this.name, this);
this._siteSpecificPref =
gPrefService.getBoolPref("browser.zoom.siteSpecific");
@ -68,7 +77,7 @@ var FullZoom = {
destroy: function FullZoom_destroy() {
gPrefService.removeObserver("browser.zoom.", this);
Services.contentPrefs.removeObserver(this.name, this);
getContentPrefs().removeObserver(this.name, this);
window.removeEventListener("DOMMouseScroll", this, false);
},
@ -149,7 +158,8 @@ var FullZoom = {
// nsIContentPrefObserver
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting(aValue);
else if (aGroup == null) {
this.globalValue = this._ensureValid(aValue);
@ -157,13 +167,14 @@ var FullZoom = {
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the new global preference now that
// the global preference has changed.
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
if (!contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
}
},
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting();
else if (aGroup == null) {
this.globalValue = undefined;
@ -171,7 +182,7 @@ var FullZoom = {
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the default preference now that
// the global preference has changed.
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
if (!contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
}
},
@ -207,12 +218,13 @@ var FullZoom = {
return;
}
if (Services.contentPrefs.hasCachedPref(aURI, this.name)) {
let zoomValue = Services.contentPrefs.getPref(aURI, this.name);
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (contentPrefs.hasCachedPref(aURI, this.name)) {
let zoomValue = contentPrefs.getPref(aURI, this.name);
this._applyPrefToSetting(zoomValue, browser);
} else {
var self = this;
Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
contentPrefs.getPref(aURI, this.name, function (aResult) {
// Check that we're still where we expect to be in case this took a while.
// Null check currentURI, since the window may have been destroyed before
// we were called.
@ -297,12 +309,12 @@ var FullZoom = {
return;
var zoomLevel = ZoomManager.zoom;
Services.contentPrefs.setPref(gBrowser.currentURI, this.name, zoomLevel);
getContentPrefs(gBrowser.contentDocument.defaultView).setPref(gBrowser.currentURI, this.name, zoomLevel);
},
_removePref: function FullZoom__removePref() {
if (!(content.document.mozSyntheticDocument))
Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
getContentPrefs(gBrowser.contentDocument.defaultView).removePref(gBrowser.currentURI, this.name);
},

View File

@ -210,6 +210,10 @@
observes="viewHistorySidebar"
label="&historyButton.label;"
accesskey="&historySidebarCmd.accesskey;"/>
<menuitem id="menu_socialSidebar"
type="checkbox"
autocheck="false"
command="Social:ToggleSidebar"/>
</menupopup>
</menu>
<menuseparator/>

View File

@ -103,6 +103,9 @@ let SocialUI = {
kbMenuitem.setAttribute("label", label);
kbMenuitem.setAttribute("accesskey", accesskey);
// The View->Sidebar menu.
document.getElementById("menu_socialSidebar").setAttribute("label", Social.provider.name);
SocialToolbar.init();
SocialShareButton.init();
SocialSidebar.init();
@ -192,6 +195,25 @@ let SocialUI = {
containerParent instanceof Ci.nsIDOMXULPopupElement) {
containerParent.hidePopup();
}
},
disableWithConfirmation: function SocialUI_disableWithConfirmation() {
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let dialogTitle = gNavigatorBundle.getFormattedString("social.remove.confirmationOK",
[Social.provider.name]);
let text = gNavigatorBundle.getFormattedString("social.remove.confirmationLabel",
[Social.provider.name, brandShortName]);
let okButtonText = dialogTitle;
let ps = Services.prompt;
let flags = ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 +
ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1 +
ps.BUTTON_POS_0_DEFAULT;
let confirmationIndex = ps.confirmEx(null, dialogTitle, text, flags,
okButtonText, null, null, null, {});
if (confirmationIndex == 0)
Social.active = false;
}
}
@ -650,6 +672,15 @@ var SocialToolbar = {
// Called once, after window load, when the Social.provider object is initialized
init: function SocialToolbar_init() {
this.button.setAttribute("image", Social.provider.iconURL);
let removeItem = document.getElementById("social-remove-menuitem");
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let label = gNavigatorBundle.getFormattedString("social.remove.label",
[brandShortName]);
let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
removeItem.setAttribute("label", label);
removeItem.setAttribute("accesskey", accesskey);
this.updateButton();
this.updateProfile();
this._dynamicResizer = new DynamicResizeWatcher();
@ -813,8 +844,7 @@ var SocialToolbar = {
if (!label.hasAttribute("value") || label.getAttribute("value") != labelValue)
label.setAttribute("value", labelValue);
if (image.getAttribute("src") != icon.iconURL)
image.setAttribute("src", icon.iconURL);
image.style.listStyleImage = "url(" + icon.iconURL + ")";
}
panel.appendChild(notificationFrames);
iconBox.appendChild(iconContainers);
@ -902,9 +932,21 @@ var SocialToolbar = {
var SocialSidebar = {
// Called once, after window load, when the Social.provider object is initialized
init: function SocialSidebar_init() {
let sbrowser = document.getElementById("social-sidebar-browser");
this.errorListener = new SocialErrorListener("sidebar");
this.configureSidebarDocShell(sbrowser.docShell);
this.updateSidebar();
},
configureSidebarDocShell: function SocialSidebar_configureDocShell(aDocShell) {
// setting isAppTab causes clicks on untargeted links to open new tabs
aDocShell.isAppTab = true;
aDocShell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(SocialSidebar.errorListener,
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
Ci.nsIWebProgress.NOTIFY_LOCATION);
},
// Whether the sidebar can be shown for this window.
get canShow() {
return Social.uiVisible && Social.provider.sidebarURL && !this.chromeless;
@ -923,10 +965,11 @@ var SocialSidebar = {
return Services.prefs.getBoolPref("social.sidebar.open") && !document.mozFullScreen;
},
dispatchEvent: function(aType, aDetail) {
setSidebarVisibilityState: function(aEnabled) {
let sbrowser = document.getElementById("social-sidebar-browser");
sbrowser.docShell.isActive = aEnabled;
let evt = sbrowser.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent(aType, true, true, aDetail ? aDetail : {});
evt.initCustomEvent(aEnabled ? "socialFrameShow" : "socialFrameHide", true, true, {});
sbrowser.contentDocument.documentElement.dispatchEvent(evt);
},
@ -944,9 +987,8 @@ var SocialSidebar = {
command.setAttribute("checked", !hideSidebar);
let sbrowser = document.getElementById("social-sidebar-browser");
sbrowser.docShell.isActive = !hideSidebar;
if (hideSidebar) {
this.dispatchEvent("socialFrameHide");
this.setSidebarVisibilityState(false);
// If we've been disabled, unload the sidebar content immediately;
// if the sidebar was just toggled to invisible, wait a timeout
// before unloading.
@ -962,21 +1004,16 @@ var SocialSidebar = {
// Make sure the right sidebar URL is loaded
if (sbrowser.getAttribute("origin") != Social.provider.origin) {
sbrowser.setAttribute("origin", Social.provider.origin);
// setting isAppTab causes clicks on untargeted links to open new tabs
sbrowser.docShell.isAppTab = true;
sbrowser.webProgress.addProgressListener(new SocialErrorListener("sidebar"),
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
Ci.nsIWebProgress.NOTIFY_LOCATION);
sbrowser.setAttribute("src", Social.provider.sidebarURL);
sbrowser.addEventListener("load", function sidebarOnShow() {
sbrowser.removeEventListener("load", sidebarOnShow);
sbrowser.removeEventListener("load", sidebarOnShow, true);
// let load finish, then fire our event
setTimeout(function () {
SocialSidebar.dispatchEvent("socialFrameShow");
SocialSidebar.setSidebarVisibilityState(true);
}, 0);
});
}, true);
} else {
this.dispatchEvent("socialFrameShow");
this.setSidebarVisibilityState(true);
}
}
},
@ -993,6 +1030,18 @@ var SocialSidebar = {
container.removeChild(sbrowser);
sbrowser.removeAttribute("origin");
sbrowser.removeAttribute("src");
function resetDocShell(docshellSupports) {
let docshell = docshellSupports.QueryInterface(Ci.nsIDocShell);
if (docshell.chromeEventHandler != sbrowser)
return;
SocialSidebar.configureSidebarDocShell(docshell);
Services.obs.removeObserver(resetDocShell, "webnavigation-create");
}
Services.obs.addObserver(resetDocShell, "webnavigation-create", false);
container.appendChild(sbrowser);
SocialFlyout.unload();

View File

@ -691,6 +691,9 @@
command="Social:ToggleNotifications"
label="&social.toggleNotifications.label;"
accesskey="&social.toggleNotifications.accesskey;"/>
<menuseparator/>
<menuitem id="social-remove-menuitem"
oncommand="SocialUI.disableWithConfirmation();"/>
</menupopup>
</toolbarbutton>
</toolbaritem>

View File

@ -356,7 +356,7 @@ Sanitizer.prototype = {
// Clear site-specific settings like page-zoom level
var cps = Components.classes["@mozilla.org/content-pref/service;1"]
.getService(Components.interfaces.nsIContentPrefService);
cps.removeGroupedPrefs();
cps.removeGroupedPrefs(null);
// Clear "Never remember passwords for this site", which is not handled by
// the permission manager

View File

@ -10,7 +10,7 @@
<xul:hbox class="chat-titlebar" xbl:inherits="minimized,selected,activity"
onclick="document.getBindingParent(this).toggle();" align="baseline">
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
<xul:label class="chat-title" flex="1" xbl:inherits="value=label,crop"/>
<xul:label class="chat-title" flex="1" xbl:inherits="value=label" crop="center"/>
<xul:toolbarbutton class="chat-close-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).close();"/>
</xul:hbox>

View File

@ -880,7 +880,7 @@ function startTest() {
return;
}
subwindow.mozAllowFullScreen = true;
subwindow.allowfullscreen = true;
lastElement = null;
text = subwindow.document.getElementById("test-text");

View File

@ -122,3 +122,8 @@ browser.jar:
# the following files are browser-specific overrides
* content/browser/license.html (/toolkit/content/license.html)
% override chrome://global/content/license.html chrome://browser/content/license.html
#ifdef MOZ_SAFE_BROWSING
* content/browser/report-phishing-overlay.xul (content/report-phishing-overlay.xul)
content/browser/blockedSite.xhtml (content/blockedSite.xhtml)
% overlay chrome://browser/content/browser.xul chrome://browser/content/report-phishing-overlay.xul
#endif

View File

@ -34,7 +34,7 @@ struct RedirEntry {
*/
static RedirEntry kRedirMap[] = {
#ifdef MOZ_SAFE_BROWSING
{ "blocked", "chrome://browser/content/safebrowsing/blockedSite.xhtml",
{ "blocked", "chrome://browser/content/blockedSite.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },

View File

@ -441,11 +441,6 @@ PrivateBrowsingService.prototype = {
getService(Ci.nsISecretDecoderRing);
sdr.logoutAndTeardown();
// clear plain HTTP auth sessions
let authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].
getService(Ci.nsIHttpAuthManager);
authMgr.clearAll();
try {
this._prefs.deleteBranch("geo.wifi.access_token.");
} catch (ex) {}

View File

@ -114,7 +114,7 @@ function runTest() {
{ // check clearHistory removes all data
clearHistory();
is(gDownloadLastDir.file, null, "clearHistory removes all data");
is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir"), false, "LastDir preference should be absent");
is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null), false, "LastDir preference should be absent");
is(gDownloadLastDir.getFile(uri1), null, "uri1 should point to null");
is(gDownloadLastDir.getFile(uri2), null, "uri2 should point to null");
is(gDownloadLastDir.getFile(uri3), null, "uri3 should point to null");

View File

@ -5,10 +5,9 @@
// This test makes sure the HTTP authenticated sessions are correctly cleared
// when entering and leaving the private browsing mode.
function run_test_on_service() {
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
Components.utils.import("resource://gre/modules/Services.jsm");
function run_test_on_service() {
var am = Cc["@mozilla.org/network/http-auth-manager;1"].
getService(Ci.nsIHttpAuthManager);
@ -25,22 +24,24 @@ function run_test_on_service() {
const kPassword2 = "pass2";
const kEmpty = "";
const PRIVATE = true;
const NOT_PRIVATE = false;
try {
var domain = {value: kEmpty}, user = {value: kEmpty}, pass = {value: kEmpty};
// simulate a login via HTTP auth outside of the private mode
am.setAuthIdentity(kHTTP, kHost1, kPort, kBasic, kRealm, kEmpty, kDomain, kUser, kPassword);
// make sure the recently added auth entry is available outside the private browsing mode
am.getAuthIdentity(kHTTP, kHost1, kPort, kBasic, kRealm, kEmpty, domain, user, pass);
am.getAuthIdentity(kHTTP, kHost1, kPort, kBasic, kRealm, kEmpty, domain, user, pass, NOT_PRIVATE);
do_check_eq(domain.value, kDomain);
do_check_eq(user.value, kUser);
do_check_eq(pass.value, kPassword);
// enter private browsing mode
pb.privateBrowsingEnabled = true;
// make sure the added auth entry is no longer accessible
// make sure the added auth entry is no longer accessible in private
domain = {value: kEmpty}, user = {value: kEmpty}, pass = {value: kEmpty};
try {
// should throw
am.getAuthIdentity(kHTTP, kHost1, kPort, kBasic, kRealm, kEmpty, domain, user, pass);
am.getAuthIdentity(kHTTP, kHost1, kPort, kBasic, kRealm, kEmpty, domain, user, pass, PRIVATE);
do_throw("Auth entry should not be retrievable after entering the private browsing mode");
} catch (e) {
do_check_eq(domain.value, kEmpty);
@ -49,26 +50,48 @@ function run_test_on_service() {
}
// simulate a login via HTTP auth inside of the private mode
am.setAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, kDomain, kUser2, kPassword2);
// make sure the recently added auth entry is available outside the private browsing mode
am.setAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, kDomain, kUser2, kPassword2, PRIVATE);
// make sure the recently added auth entry is available inside the private browsing mode
domain = {value: kEmpty}, user = {value: kEmpty}, pass = {value: kEmpty};
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass);
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass, PRIVATE);
do_check_eq(domain.value, kDomain);
do_check_eq(user.value, kUser2);
do_check_eq(pass.value, kPassword2);
// exit private browsing mode
pb.privateBrowsingEnabled = false;
// make sure the added auth entry is no longer accessible
try {
// make sure the recently added auth entry is not available outside the private browsing mode
domain = {value: kEmpty}, user = {value: kEmpty}, pass = {value: kEmpty};
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass, NOT_PRIVATE);
do_throw("Auth entry should not be retrievable outside of private browsing mode");
} catch (x) {
do_check_eq(domain.value, kEmpty);
do_check_eq(user.value, kEmpty);
do_check_eq(pass.value, kEmpty);
}
// simulate leaving private browsing mode
Services.obs.notifyObservers(null, "last-pb-context-exited", null);
// make sure the added auth entry is no longer accessible in any privacy state
domain = {value: kEmpty}, user = {value: kEmpty}, pass = {value: kEmpty};
try {
// should throw
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass);
// should throw (not available in public mode)
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass, NOT_PRIVATE);
do_throw("Auth entry should not be retrievable after exiting the private browsing mode");
} catch (e) {
do_check_eq(domain.value, kEmpty);
do_check_eq(user.value, kEmpty);
do_check_eq(pass.value, kEmpty);
}
try {
// should throw (no longer available in private mode)
am.getAuthIdentity(kHTTP, kHost2, kPort, kBasic, kRealm, kEmpty, domain, user, pass, PRIVATE);
do_throw("Auth entry should not be retrievable in private mode after exiting the private browsing mode");
} catch (x) {
do_check_eq(domain.value, kEmpty);
do_check_eq(user.value, kEmpty);
do_check_eq(pass.value, kEmpty);
}
} catch (e) {
do_throw("Unexpected exception while testing HTTP auth manager: " + e);
}

View File

@ -12,16 +12,4 @@ include $(DEPTH)/config/autoconf.mk
TEST_DIRS += content/test
# Normally the "client ID" sent in updates is appinfo.name, but for
# official Firefox releases from Mozilla we use a special identifier.
ifdef MOZILLA_OFFICIAL
ifdef MOZ_PHOENIX
DEFINES += -DUSE_HISTORIC_SAFEBROWSING_ID=1
endif
endif
EXTRA_PP_JS_MODULES = \
SafeBrowsing.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -1,8 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/safebrowsing/report-phishing-overlay.xul (content/report-phishing-overlay.xul)
content/browser/safebrowsing/blockedSite.xhtml (content/blockedSite.xhtml)
% overlay chrome://browser/content/browser.xul chrome://browser/content/safebrowsing/report-phishing-overlay.xul

View File

@ -394,6 +394,14 @@ social.toggle.accesskey=f
# LOCALIZATION NOTE (social.activated.description): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
social.activated.description=You've turned on %1$S for %2$S.
# LOCALIZATION NOTE (social.remove.label): %S = brandShortName
social.remove.label=Remove from %S
social.remove.accesskey=R
# LOCALIZATION NOTE (social.remove.confirmationLabel): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
social.remove.confirmationLabel=Are you sure you want to remove %1$S for %2$S?
# LOCALIZATION NOTE (social.remove.confirmationOK): %S is the name of the social provider
social.remove.confirmationOK=Remove %S
# LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
social.error.message=%1$S is unable to connect with %2$S right now.
social.error.tryAgain.label=Try Again

View File

@ -2652,8 +2652,7 @@ html|*#gcli-output-frame {
.social-notification-icon-image {
margin: 5px 3px;
width: 16px;
height: 16px;
-moz-image-region: rect(0, 16px, 16px, 0);
}
.social-notification-icon-hbox {
@ -2727,7 +2726,7 @@ html|*#gcli-output-frame {
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
color: black;
text-shadow: none;
cursor: inherit;
}

View File

@ -4100,8 +4100,7 @@ html|*#gcli-output-frame {
}
.social-notification-icon-image {
width: 16px;
height: 16px;
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* === end of social toolbar button === */
@ -4158,7 +4157,7 @@ html|*#gcli-output-frame {
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
color: black;
text-shadow: none;
cursor: inherit;
}

View File

@ -3314,7 +3314,7 @@ html|*#gcli-output-frame {
}
@navbarLargeIcons@ > #social-toolbar-item > .toolbarbutton-1 {
padding: 5px 0;
padding: 6px 0;
}
@navbarLargeIcons@ > #social-toolbar-item > .toolbarbutton-1:first-child {
@ -3348,8 +3348,7 @@ html|*#gcli-output-frame {
}
.social-notification-icon-image {
width: 16px;
height: 16px;
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* social toolbar provider menu */
@ -3431,7 +3430,7 @@ html|*#gcli-output-frame {
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
color: black;
text-shadow: none;
cursor: inherit;
}

View File

@ -7153,7 +7153,10 @@ if test "$OS_TARGET" = Android; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr"
fi
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl--wrap=PR_GetEnv,--wrap=PR_SetEnv"
if test -z "$gonkdir"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
fi
fi
dnl ========================================================

View File

@ -7,6 +7,7 @@
#define nsINode_h___
#include "mozilla/ErrorResult.h"
#include "mozilla/Likely.h"
#include "nsCOMPtr.h" // for member, local
#include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty
#include "nsIDOMEventTarget.h" // for base class
@ -738,7 +739,7 @@ public:
* @return the parent, or null if no parent or the parent is not an nsIContent
*/
nsIContent* GetParent() const {
return NS_LIKELY(GetBoolFlag(ParentIsContent)) ?
return MOZ_LIKELY(GetBoolFlag(ParentIsContent)) ?
reinterpret_cast<nsIContent*>(mParent) : nullptr;
}

View File

@ -11,6 +11,7 @@
*/
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/FragmentOrElement.h"
@ -1557,7 +1558,7 @@ static const char* kNSURIs[] = {
};
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
uint32_t nsid = tmp->GetNameSpaceID();
nsAtomCString localName(tmp->NodeInfo()->NameAtom());

View File

@ -21,6 +21,7 @@
#include "nsGkAtoms.h"
#include "mozilla/dom/HTMLCollectionBinding.h"
#include "mozilla/dom/NodeListBinding.h"
#include "mozilla/Likely.h"
// Form related includes
#include "nsIDOMHTMLFormElement.h"
@ -48,7 +49,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack() &&
NS_LIKELY(!cb.WantAllTraces())) {
MOZ_LIKELY(!cb.WantAllTraces())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mElements)

View File

@ -7,6 +7,7 @@
/* A namespace class for static layout utilities. */
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#include "jsapi.h"
#include "jsdbgapi.h"
@ -5618,7 +5619,7 @@ nsContentUtils::ASCIIToLower(nsAString& aStr)
{
PRUnichar* iter = aStr.BeginWriting();
PRUnichar* end = aStr.EndWriting();
if (NS_UNLIKELY(!iter || !end)) {
if (MOZ_UNLIKELY(!iter || !end)) {
return NS_ERROR_OUT_OF_MEMORY;
}
while (iter != end) {
@ -5639,7 +5640,7 @@ nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest)
aDest.SetLength(len);
if (aDest.Length() == len) {
PRUnichar* dest = aDest.BeginWriting();
if (NS_UNLIKELY(!dest)) {
if (MOZ_UNLIKELY(!dest)) {
return NS_ERROR_OUT_OF_MEMORY;
}
const PRUnichar* iter = aSource.BeginReading();
@ -5662,7 +5663,7 @@ nsContentUtils::ASCIIToUpper(nsAString& aStr)
{
PRUnichar* iter = aStr.BeginWriting();
PRUnichar* end = aStr.EndWriting();
if (NS_UNLIKELY(!iter || !end)) {
if (MOZ_UNLIKELY(!iter || !end)) {
return NS_ERROR_OUT_OF_MEMORY;
}
while (iter != end) {
@ -5683,7 +5684,7 @@ nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
aDest.SetLength(len);
if (aDest.Length() == len) {
PRUnichar* dest = aDest.BeginWriting();
if (NS_UNLIKELY(!dest)) {
if (MOZ_UNLIKELY(!dest)) {
return NS_ERROR_OUT_OF_MEMORY;
}
const PRUnichar* iter = aSource.BeginReading();
@ -6613,48 +6614,33 @@ nsContentUtils::FindInternalContentViewer(const char* aType,
#ifdef MOZ_MEDIA
#ifdef MOZ_OGG
if (nsHTMLMediaElement::IsOggEnabled()) {
for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gOggTypes); ++i) {
const char* type = nsHTMLMediaElement::gOggTypes[i];
if (!strcmp(aType, type)) {
if (nsHTMLMediaElement::IsOggType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
}
}
#endif
#ifdef MOZ_WEBM
if (nsHTMLMediaElement::IsWebMEnabled()) {
for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gWebMTypes); ++i) {
const char* type = nsHTMLMediaElement::gWebMTypes[i];
if (!strcmp(aType, type)) {
if (nsHTMLMediaElement::IsWebMType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
}
}
#endif
#ifdef MOZ_GSTREAMER
if (nsHTMLMediaElement::IsH264Enabled()) {
for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gH264Types); ++i) {
const char* type = nsHTMLMediaElement::gH264Types[i];
if (!strcmp(aType, type)) {
if (nsHTMLMediaElement::IsGStreamerSupportedType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
}
}
#endif
#ifdef MOZ_MEDIA_PLUGINS
@ -6667,7 +6653,6 @@ nsContentUtils::FindInternalContentViewer(const char* aType,
return docFactory.forget();
}
#endif // MOZ_MEDIA_PLUGINS
#endif // MOZ_MEDIA
return NULL;

View File

@ -9,6 +9,7 @@
*/
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
@ -1589,7 +1590,7 @@ static const char* kNSURIs[] = {
};
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
nsAutoCString loadedAsData;
if (tmp->IsLoadedAsData()) {
@ -9058,7 +9059,7 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
return false;
}
// Ensure that all ancestor <iframe> elements have the mozallowfullscreen
// Ensure that all ancestor <iframe> elements have the allowfullscreen
// boolean attribute set.
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
bool allowed = false;

View File

@ -73,6 +73,7 @@ GK_ATOM(all, "all")
GK_ATOM(allowevents, "allowevents")
GK_ATOM(allowforms, "allow-forms")
GK_ATOM(allownegativeassertions, "allownegativeassertions")
GK_ATOM(allowfullscreen, "allowfullscreen")
GK_ATOM(allowsameorigin, "allow-same-origin")
GK_ATOM(allowscripts, "allow-scripts")
GK_ATOM(allowtopnavigation, "allow-top-navigation")

View File

@ -13,6 +13,7 @@
#include "jsapi.h"
#include "mozAutoDocUpdate.h"
#include "mozilla/CORSMode.h"
#include "mozilla/Likely.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Util.h"
#include "nsAsyncDOMEvent.h"
@ -1142,7 +1143,7 @@ nsINode::UnoptimizableCCNode() const
bool
nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
{
if (NS_LIKELY(!cb.WantAllTraces())) {
if (MOZ_LIKELY(!cb.WantAllTraces())) {
nsIDocument *currentDoc = tmp->GetCurrentDoc();
if (currentDoc &&
nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {

View File

@ -10,6 +10,7 @@
*/
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#include "nscore.h"
#include "nsNodeInfo.h"
@ -164,7 +165,7 @@ static const char* kNSURIs[] = {
};
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsNodeInfo)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[72];
uint32_t nsid = tmp->NamespaceID();
nsAtomCString localName(tmp->NameAtom());

View File

@ -30,6 +30,7 @@
#include "nsTextFrame.h"
#include "nsFontFaceList.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Likely.h"
using namespace mozilla;
@ -395,7 +396,7 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
"mStartOffset is beyond the end of this node");
newStartOffset = static_cast<uint32_t>(mStartOffset) - aInfo->mChangeStart;
newStartNode = aInfo->mDetails->mNextSibling;
if (NS_UNLIKELY(aContent == mRoot)) {
if (MOZ_UNLIKELY(aContent == mRoot)) {
newRoot = IsValidBoundary(newStartNode);
}
@ -457,14 +458,14 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
if (removed == mStartParent) {
newStartOffset = static_cast<uint32_t>(mStartOffset) + aInfo->mChangeStart;
newStartNode = aContent;
if (NS_UNLIKELY(removed == mRoot)) {
if (MOZ_UNLIKELY(removed == mRoot)) {
newRoot = IsValidBoundary(newStartNode);
}
}
if (removed == mEndParent) {
newEndOffset = static_cast<uint32_t>(mEndOffset) + aInfo->mChangeStart;
newEndNode = aContent;
if (NS_UNLIKELY(removed == mRoot)) {
if (MOZ_UNLIKELY(removed == mRoot)) {
newRoot = IsValidBoundary(newEndNode);
}
}

View File

@ -13,6 +13,7 @@
#include "prprf.h"
#include "nsGlobalWindow.h"
#include "nsDOMEvent.h"
#include "mozilla/Likely.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetHelper)
@ -21,7 +22,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
nsAutoString uri;
if (tmp->mOwner && tmp->mOwner->GetExtantDocument()) {

View File

@ -308,7 +308,8 @@ public:
#endif
#ifdef MOZ_GSTREAMER
static bool IsH264Enabled();
static bool IsGStreamerEnabled();
static bool IsGStreamerSupportedType(const nsACString& aType);
static bool IsH264Type(const nsACString& aType);
static const char gH264Types[3][16];
static char const *const gH264Codecs[7];

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#include "nscore.h"
#include "nsGenericHTMLElement.h"
@ -1037,7 +1038,7 @@ StartElement(Element* aContent, StringBuilder& aBuilder)
continue;
}
if (NS_LIKELY(attNs == kNameSpaceID_None) ||
if (MOZ_LIKELY(attNs == kNameSpaceID_None) ||
(attNs == kNameSpaceID_XMLNS &&
attName == nsGkAtoms::xmlns)) {
aBuilder.Append(" ");
@ -2158,7 +2159,7 @@ nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID,
nsString value(aValue);
nsRefPtr<nsStringBuffer> buffer = nsCSSValue::BufferFromString(value);
if (NS_UNLIKELY(!buffer)) {
if (MOZ_UNLIKELY(!buffer)) {
return false;
}

View File

@ -55,7 +55,7 @@ NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Scrolling, scrolling)
NS_IMPL_URI_ATTR(nsHTMLIFrameElement, Src, src)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Width, width)
NS_IMPL_BOOL_ATTR(nsHTMLIFrameElement, MozAllowFullScreen, mozallowfullscreen)
NS_IMPL_BOOL_ATTR(nsHTMLIFrameElement, Allowfullscreen, allowfullscreen)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Sandbox, sandbox)
void

View File

@ -275,7 +275,7 @@ nsHTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
if (!prefSaved) {
// Store the last used directory using the content pref service
nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc()->GetDocumentURI(), localFile);
mInput->OwnerDoc(), localFile);
prefSaved = true;
}
}
@ -293,7 +293,7 @@ nsHTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
newFiles.AppendObject(domFile);
// Store the last used directory using the content pref service
nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc()->GetDocumentURI(), localFile);
mInput->OwnerDoc(), localFile);
}
}
}
@ -410,7 +410,7 @@ nsHTMLInputElement::AsyncClickHandler::Run()
} else {
// Attempt to retrieve the last used directory from the content pref service
nsCOMPtr<nsIFile> localFile;
nsHTMLInputElement::gUploadLastDir->FetchLastUsedDirectory(doc->GetDocumentURI(),
nsHTMLInputElement::gUploadLastDir->FetchLastUsedDirectory(doc,
getter_AddRefs(localFile));
if (!localFile) {
// Default to "desktop" directory for each platform
@ -448,10 +448,17 @@ nsHTMLInputElement::DestroyUploadLastDir() {
}
nsresult
UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile)
UploadLastDir::FetchLastUsedDirectory(nsIDocument* aDoc, nsIFile** aFile)
{
NS_PRECONDITION(aURI, "aURI is null");
NS_PRECONDITION(aDoc, "aDoc is null");
NS_PRECONDITION(aFile, "aFile is null");
nsIURI* docURI = aDoc->GetDocumentURI();
NS_PRECONDITION(docURI, "docURI is null");
nsCOMPtr<nsISupports> container = aDoc->GetContainer();
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
// Attempt to get the CPS, if it's not present we'll just return
nsCOMPtr<nsIContentPrefService> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@ -460,13 +467,13 @@ UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile)
nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
if (!uri)
return NS_ERROR_OUT_OF_MEMORY;
uri->SetAsISupports(aURI);
uri->SetAsISupports(docURI);
// Get the last used directory, if it is stored
bool hasPref;
if (NS_SUCCEEDED(contentPrefService->HasPref(uri, CPS_PREF_NAME, &hasPref)) && hasPref) {
if (NS_SUCCEEDED(contentPrefService->HasPref(uri, CPS_PREF_NAME, loadContext, &hasPref)) && hasPref) {
nsCOMPtr<nsIVariant> pref;
contentPrefService->GetPref(uri, CPS_PREF_NAME, nullptr, getter_AddRefs(pref));
contentPrefService->GetPref(uri, CPS_PREF_NAME, loadContext, nullptr, getter_AddRefs(pref));
nsString prefStr;
pref->GetAsAString(prefStr);
@ -480,10 +487,14 @@ UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile)
}
nsresult
UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile)
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aFile)
{
NS_PRECONDITION(aURI, "aURI is null");
NS_PRECONDITION(aDoc, "aDoc is null");
NS_PRECONDITION(aFile, "aFile is null");
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
NS_PRECONDITION(docURI, "docURI is null");
nsCOMPtr<nsIFile> parentFile;
aFile->GetParent(getter_AddRefs(parentFile));
if (!parentFile) {
@ -498,7 +509,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile)
nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
if (!uri)
return NS_ERROR_OUT_OF_MEMORY;
uri->SetAsISupports(aURI);
uri->SetAsISupports(docURI);
// Find the parent of aFile, and store it
nsString unicodePath;
@ -509,7 +520,10 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile)
if (!prefValue)
return NS_ERROR_OUT_OF_MEMORY;
prefValue->SetAsAString(unicodePath);
return contentPrefService->SetPref(uri, CPS_PREF_NAME, prefValue);
nsCOMPtr<nsISupports> container = aDoc->GetContainer();
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
return contentPrefService->SetPref(uri, CPS_PREF_NAME, prefValue, loadContext);
}
NS_IMETHODIMP
@ -519,7 +533,7 @@ UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar cons
nsCOMPtr<nsIContentPrefService> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
if (contentPrefService)
contentPrefService->RemovePrefsByName(CPS_PREF_NAME);
contentPrefService->RemovePrefsByName(CPS_PREF_NAME, nullptr);
}
return NS_OK;
}

View File

@ -35,10 +35,10 @@ public:
* Fetch the last used directory for this location from the content
* pref service, if it is available.
*
* @param aURI URI of the current page
* @param aDoc current document
* @param aFile path to the last used directory
*/
nsresult FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile);
nsresult FetchLastUsedDirectory(nsIDocument* aDoc, nsIFile** aFile);
/**
* Store the last used directory for this location using the
@ -47,7 +47,7 @@ public:
* @param aFile file chosen by the user - the path to the parent of this
* file will be stored
*/
nsresult StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile);
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aFile);
};
class nsHTMLInputElement : public nsGenericHTMLFormElement,

View File

@ -2153,24 +2153,19 @@ const char nsHTMLMediaElement::gH264Types[3][16] = {
};
bool
nsHTMLMediaElement::IsH264Enabled()
nsHTMLMediaElement::IsGStreamerEnabled()
{
return Preferences::GetBool("media.h264.enabled");
return Preferences::GetBool("media.gstreamer.enabled");
}
bool
nsHTMLMediaElement::IsH264Type(const nsACString& aType)
{
if (!IsH264Enabled()) {
return false;
}
for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) {
if (aType.EqualsASCII(gH264Types[i])) {
return true;
}
}
return false;
}
#endif
@ -2429,9 +2424,43 @@ nsHTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
return NS_OK;
}
#ifdef MOZ_GSTREAMER
bool
nsHTMLMediaElement::IsGStreamerSupportedType(const nsACString& aMimeType)
{
if (!IsGStreamerEnabled())
return false;
if (IsH264Type(aMimeType))
return true;
if (!Preferences::GetBool("media.prefer-gstreamer", false))
return false;
#ifdef MOZ_WEBM
if (IsWebMType(aMimeType))
return true;
#endif
#ifdef MOZ_OGG
if (IsOggType(aMimeType))
return true;
#endif
return false;
}
#endif
already_AddRefed<nsMediaDecoder>
nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
{
#ifdef MOZ_GSTREAMER
// When enabled, use GStreamer for H.264, but not for codecs handled by our
// bundled decoders, unless the "media.prefer-gstreamer" pref is set.
if (IsGStreamerSupportedType(aType)) {
nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_RAW
if (IsRawType(aType)) {
nsRefPtr<nsRawDecoder> decoder = new nsRawDecoder();
@ -2442,11 +2471,7 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
#endif
#ifdef MOZ_OGG
if (IsOggType(aType)) {
#ifdef MOZ_GSTREAMER
nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder();
#else
nsRefPtr<nsOggDecoder> decoder = new nsOggDecoder();
#endif
if (decoder->Init(this)) {
return decoder.forget();
}
@ -2478,11 +2503,7 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
#endif
#ifdef MOZ_WEBM
if (IsWebMType(aType)) {
#ifdef MOZ_GSTREAMER
nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder();
#else
nsRefPtr<nsWebMDecoder> decoder = new nsWebMDecoder();
#endif
if (decoder->Init(this)) {
return decoder.forget();
}
@ -2498,14 +2519,6 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
}
#endif
#ifdef MOZ_GSTREAMER
if (IsH264Type(aType)) {
nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
return nullptr;
}

View File

@ -78,7 +78,7 @@ function exit1(event) {
is(event.target, document, "10. Event target should be full-screen document #2");
is(document.mozFullScreenElement, null, "11. Full-screen element should be null.");
iframe = document.createElement("iframe");
iframe.mozAllowFullScreen = true;
iframe.allowfullscreen = true;
addFullscreenChangeContinuation("enter", enter2);
document.body.appendChild(iframe);
iframe.src = iframeContents;

View File

@ -4,17 +4,17 @@
function foo() {
document.addEventListener('mozfullscreenerror',
function() {
parent.ok(true, "Request from an iframe without mozallowfullscreen should be denied");
parent.ok(true, "Request from an iframe without allowfullscreen should be denied");
parent.finish();
},
false);
document.addEventListener('mozfullscreenchange',
function() {
parent.ok(false, "Request from an iframe without mozallowfullscreen should be denied, but was granted!");
parent.ok(false, "Request from an iframe without allowfullscreen should be denied, but was granted!");
parent.finish();
},
false);
parent.is(document.mozFullScreenEnabled, false, "Full-screen should not be enabled, coz mozallowfullscreen isn't present.");
parent.is(document.mozFullScreenEnabled, false, "Full-screen should not be enabled, coz allowfullscreen isn't present.");
document.body.mozRequestFullScreen();
}
</script>

View File

@ -71,7 +71,7 @@ function keyHandler(event) {
// to write.
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
// Create an iframe without a mozallowfullscreen attribute, whose contents requests
// Create an iframe without a allowfullscreen attribute, whose contents requests
// full-screen. The request should be denied, and we should not receive a fullscreenchange
// event in this document.
var iframe = document.createElement("iframe");

View File

@ -10,7 +10,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=697636
</head>
<body>
<iframe id="f" src="data:text/html,<body text=green>1" mozallowfullscreen></iframe>
<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697636">Mozilla Bug 697636</a>
<p id="display"></p>

View File

@ -10,7 +10,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=685402
</head>
<body style="background-color: gray;">
<iframe id="f" src="data:text/html,<body text=green>1" mozallowfullscreen></iframe>
<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685402">Mozilla Bug 685402</a>
<p id="display"></p>

View File

@ -26,7 +26,7 @@ Tests:
<div id="fse">
<div id="fse-inner">
<iframe id="subdoc" mozallowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe>
<iframe id="subdoc" allowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe>
</div>
</div>

View File

@ -31,7 +31,7 @@ SpecialPowers.setBoolPref("full-screen-api.enabled", true);
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
// Run the tests which go full-screen in new windows, as mochitests normally
// run in an iframe, which by default will not have the mozallowfullscreen
// run in an iframe, which by default will not have the allowfullscreen
// attribute set, so full-screen won't work.
var gTestWindows = [
"file_fullscreen-rollback.html",

View File

@ -0,0 +1,374 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#pragma once
#include "mozilla/Attributes.h"
#include "mozilla/FloatingPoint.h"
#include "nsTArray.h"
#include "math.h"
namespace mozilla {
namespace dom {
/**
* This class will be instantiated with different template arguments for testing and
* production code.
*
* FloatArrayWrapper is a type which satisfies the following:
* - Is copy-constructible.
* - Implements a Data() method returning a float*, representing an array.
* - Implements a Length() method returning a uint32_t, representing the array length.
* - Implements an inited() method returning true for valid objects.
* ErrorResult is a type which satisfies the following:
* - Implements a Throw() method taking an nsresult argument, representing an error code.
*/
template <class FloatArrayWrapper, class ErrorResult>
class AudioEventTimeline
{
private:
struct Event {
enum Type MOZ_ENUM_TYPE(uint32_t) {
SetValue,
LinearRamp,
ExponentialRamp,
SetTarget,
SetValueCurve
};
Event(Type aType, float aTime, float aValue, float aTimeConstant = 0.0,
float aDuration = 0.0, FloatArrayWrapper aCurve = FloatArrayWrapper())
: mType(aType)
, mTime(aTime)
, mValue(aValue)
, mTimeConstant(aTimeConstant)
, mDuration(aDuration)
{
if (aCurve.inited()) {
mCurve = aCurve;
}
}
bool IsValid() const
{
return IsValid(mTime) &&
IsValid(mValue) &&
IsValid(mTimeConstant) &&
IsValid(mDuration);
}
Type mType;
float mTime;
float mValue;
float mTimeConstant;
float mDuration;
FloatArrayWrapper mCurve;
private:
static bool IsValid(float value)
{
return MOZ_DOUBLE_IS_FINITE(value);
}
};
public:
AudioEventTimeline(float aDefaultValue,
float aMinValue,
float aMaxValue)
: mValue(aDefaultValue)
, mDefaultValue(aDefaultValue)
, mMinValue(aMinValue)
, mMaxValue(aMaxValue)
{
MOZ_ASSERT(aDefaultValue >= aMinValue);
MOZ_ASSERT(aDefaultValue <= aMaxValue);
MOZ_ASSERT(aMinValue < aMaxValue);
}
float Value() const
{
// TODO: Return the current value based on the timeline of the AudioContext
return mValue;
}
void SetValue(float aValue)
{
// Silently don't change anything if there are any events
if (mEvents.IsEmpty()) {
mValue = aValue;
}
}
float ComputedValue() const
{
// TODO: implement
return 0;
}
float MinValue() const
{
return mMinValue;
}
float MaxValue() const
{
return mMaxValue;
}
float DefaultValue() const
{
return mDefaultValue;
}
void SetValueAtTime(float aValue, float aStartTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::Type::SetValue, aStartTime, aValue), aRv);
}
void LinearRampToValueAtTime(float aValue, float aEndTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::Type::LinearRamp, aEndTime, aValue), aRv);
}
void ExponentialRampToValueAtTime(float aValue, float aEndTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::Type::ExponentialRamp, aEndTime, aValue), aRv);
}
void SetTargetAtTime(float aTarget, float aStartTime, float aTimeConstant, ErrorResult& aRv)
{
InsertEvent(Event(Event::Type::SetTarget, aStartTime, aTarget, aTimeConstant), aRv);
}
void SetValueCurveAtTime(const FloatArrayWrapper& aValues, float aStartTime, float aDuration, ErrorResult& aRv)
{
// TODO: implement
// InsertEvent(Event(Event::Type::SetValueCurve, aStartTime, 0.0f, 0.0f, aDuration, aValues), aRv);
}
void CancelScheduledValues(float aStartTime)
{
// TODO: implement
}
// This method computes the AudioParam value at a given time based on the event timeline
float GetValueAtTime(float aTime) const
{
const Event* previous = nullptr;
const Event* next = nullptr;
bool bailOut = false;
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
switch (mEvents[i].mType) {
case Event::Type::SetValue:
case Event::Type::SetTarget:
case Event::Type::LinearRamp:
case Event::Type::ExponentialRamp:
if (aTime == mEvents[i].mTime) {
// Find the last event with the same time
do {
++i;
} while (i < mEvents.Length() &&
aTime == mEvents[i].mTime);
return mEvents[i - 1].mValue;
}
previous = next;
next = &mEvents[i];
if (aTime < mEvents[i].mTime) {
bailOut = true;
}
break;
case Event::Type::SetValueCurve:
// TODO: implement
break;
default:
MOZ_ASSERT(false, "unreached");
}
}
// Handle the case where the time is past all of the events
if (!bailOut) {
previous = next;
next = nullptr;
}
// Just return the default value if we did not find anything
if (!previous && !next) {
return mValue;
}
// If the requested time is before all of the existing events
if (!previous) {
switch (next->mType) {
case Event::Type::SetValue:
case Event::Type::SetTarget:
// The requested time is before the first event
return mValue;
case Event::Type::LinearRamp:
// Use t=0 as T0 and v=defaultValue as V0
return LinearInterpolate(0.0f, mValue, next->mTime, next->mValue, aTime);
case Event::Type::ExponentialRamp:
// Use t=0 as T0 and v=defaultValue as V0
return ExponentialInterpolate(0.0f, mValue, next->mTime, next->mValue, aTime);
case Event::Type::SetValueCurve:
// TODO: implement
return 0.0f;
}
MOZ_ASSERT(false, "unreached");
}
// SetTarget nodes can be handled no matter what their next node is (if they have one)
if (previous->mType == Event::Type::SetTarget) {
// Follow the curve, without regard to the next node
return ExponentialApproach(previous->mTime, mValue, previous->mValue,
previous->mTimeConstant, aTime);
}
// If the requested time is after all of the existing events
if (!next) {
switch (previous->mType) {
case Event::Type::SetValue:
case Event::Type::LinearRamp:
case Event::Type::ExponentialRamp:
// The value will be constant after the last event
return previous->mValue;
case Event::Type::SetValueCurve:
// TODO: implement
return 0.0f;
case Event::Type::SetTarget:
MOZ_ASSERT(false, "unreached");
}
MOZ_ASSERT(false, "unreached");
}
// Finally, handle the case where we have both a previous and a next event
// First, handle the case where our range ends up in a ramp event
switch (next->mType) {
case Event::Type::LinearRamp:
return LinearInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
case Event::Type::ExponentialRamp:
return ExponentialInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
case Event::Type::SetValue:
case Event::Type::SetTarget:
case Event::Type::SetValueCurve:
break;
}
// Now handle all other cases
switch (previous->mType) {
case Event::Type::SetValue:
case Event::Type::LinearRamp:
case Event::Type::ExponentialRamp:
// If the next event type is neither linear or exponential ramp, the
// value is constant.
return previous->mValue;
case Event::Type::SetValueCurve:
// TODO: implement
return 0.0f;
case Event::Type::SetTarget:
MOZ_ASSERT(false, "unreached");
}
MOZ_ASSERT(false, "unreached");
return 0.0f;
}
// Return the number of events scheduled
uint32_t GetEventCount() const
{
return mEvents.Length();
}
static float LinearInterpolate(float t0, float v0, float t1, float v1, float t)
{
return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
}
static float ExponentialInterpolate(float t0, float v0, float t1, float v1, float t)
{
return v0 * powf(v1 / v0, (t - t0) / (t1 - t0));
}
static float ExponentialApproach(float t0, float v0, float v1, float timeConstant, float t)
{
return v1 + (v0 - v1) * expf(-(t - t0) / timeConstant);
}
private:
void InsertEvent(const Event& aEvent, ErrorResult& aRv)
{
if (!aEvent.IsValid()) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
// Make sure that non-curve events don't fall within the duration of a
// curve event.
for (unsigned i = 0; i < mEvents.Length(); ++i) {
if (mEvents[i].mType == Event::Type::SetValueCurve &&
mEvents[i].mTime <= aEvent.mTime &&
(mEvents[i].mTime + mEvents[i].mDuration) >= aEvent.mTime) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
}
// Make sure that curve events don't fall in a range which includes other
// events.
if (aEvent.mType == Event::Type::SetValueCurve) {
for (unsigned i = 0; i < mEvents.Length(); ++i) {
if (mEvents[i].mTime >= aEvent.mTime &&
mEvents[i].mTime <= (aEvent.mTime + aEvent.mDuration)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
}
}
for (unsigned i = 0; i < mEvents.Length(); ++i) {
if (aEvent.mTime == mEvents[i].mTime) {
if (aEvent.mType == mEvents[i].mType) {
// If times and types are equal, replace the event
mEvents.ReplaceElementAt(i, aEvent);
} else {
// Otherwise, place the element after the last event of another type
do {
++i;
} while (i < mEvents.Length() &&
aEvent.mType != mEvents[i].mType &&
aEvent.mTime == mEvents[i].mTime);
mEvents.InsertElementAt(i, aEvent);
}
return;
}
// Otherwise, place the event right after the latest existing event
if (aEvent.mTime < mEvents[i].mTime) {
mEvents.InsertElementAt(i, aEvent);
return;
}
}
// If we couldn't find a place for the event, just append it to the list
mEvents.AppendElement(aEvent);
}
private:
// This is a sorted array of the events in the timeline. Queries of this
// data structure should probably be more frequent than modifications to it,
// and that is the reason why we're using a simple array as the data structure.
// We can optimize this in the future if the performance of the array ends up
// being a bottleneck.
nsTArray<Event> mEvents;
float mValue;
const float mDefaultValue;
const float mMinValue;
const float mMaxValue;
};
}
}

View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioParam.h"
#include "nsContentUtils.h"
#include "nsIDOMWindow.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/AudioParamBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(AudioParam)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(AudioParam)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER_NATIVE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(AudioParam)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mContext, AudioContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(AudioParam)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioParam, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioParam, Release)
AudioParam::AudioParam(AudioContext* aContext,
float aDefaultValue,
float aMinValue,
float aMaxValue)
: AudioParamTimeline(aDefaultValue, aMinValue, aMaxValue)
, mContext(aContext)
{
SetIsDOMBinding();
}
AudioParam::~AudioParam()
{
}
JSObject*
AudioParam::WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return AudioParamBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
}
}

View File

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#pragma once
#include "AudioEventTimeline.h"
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "EnableWebAudioCheck.h"
#include "nsAutoPtr.h"
#include "AudioContext.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/Util.h"
class JSContext;
class nsIDOMWindow;
namespace mozilla {
class ErrorResult;
namespace dom {
namespace detail {
// This class wraps a JS typed array so that AudioEventTimeline does not need
// to know about JSObjects directly.
class FloatArrayWrapper
{
public:
FloatArrayWrapper() // creates an uninitialized object
{
}
FloatArrayWrapper(const Float32Array& array)
{
mArray.construct(array);
}
FloatArrayWrapper(const FloatArrayWrapper& rhs)
{
MOZ_ASSERT(!rhs.mArray.empty());
mArray.construct(rhs.mArray.ref());
}
FloatArrayWrapper& operator=(const FloatArrayWrapper& rhs)
{
MOZ_ASSERT(!rhs.mArray.empty());
mArray.destroyIfConstructed();
mArray.construct(rhs.mArray.ref());
return *this;
}
// Expose the API used by AudioEventTimeline
float* Data() const
{
MOZ_ASSERT(inited());
return mArray.ref().Data();
}
uint32_t Length() const
{
MOZ_ASSERT(inited());
return mArray.ref().Length();
}
bool inited() const
{
return !mArray.empty();
}
private:
Maybe<Float32Array> mArray;
};
}
typedef AudioEventTimeline<detail::FloatArrayWrapper, ErrorResult> AudioParamTimeline;
class AudioParam MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck,
public AudioParamTimeline
{
public:
AudioParam(AudioContext* aContext,
float aDefaultValue,
float aMinValue,
float aMaxValue);
virtual ~AudioParam();
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioParam)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)
AudioContext* GetParentObject() const
{
return mContext;
}
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap);
// We override SetValueCurveAtTime to convert the Float32Array to the wrapper
// object.
void SetValueCurveAtTime(JSContext* cx, const Float32Array& aValues, float aStartTime, float aDuration, ErrorResult& aRv)
{
AudioParamTimeline::SetValueCurveAtTime(detail::FloatArrayWrapper(aValues),
aStartTime, aDuration, aRv);
}
private:
nsRefPtr<AudioContext> mContext;
};
}
}

View File

@ -20,6 +20,7 @@ CPPSRCS := \
AudioContext.cpp \
AudioDestinationNode.cpp \
AudioNode.cpp \
AudioParam.cpp \
AudioSourceNode.cpp \
EnableWebAudioCheck.cpp \
$(NULL)
@ -30,11 +31,16 @@ EXPORTS_mozilla/dom := \
AudioBufferSourceNode.h \
AudioDestinationNode.h \
AudioNode.h \
AudioParam.h \
AudioSourceNode.h \
$(NULL)
PARALLEL_DIRS := test
ifdef ENABLE_TESTS
TOOL_DIRS += compiledtest
endif
FORCE_STATIC_LIB := 1
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,19 @@
# 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/.
DEPTH := @DEPTH@
topsrcdir := @top_srcdir@
srcdir := @srcdir@
VPATH := @srcdir@
relativesrcdir := @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
LOCAL_INCLUDES := -I$(srcdir)/..
CPP_UNIT_TESTS := \
TestAudioEventTimeline.cpp \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,343 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioEventTimeline.h"
#include "TestHarness.h"
#include <sstream>
#include <limits>
using namespace mozilla::dom;
using std::numeric_limits;
// Some simple testing primitives
void ok(bool val, const char* msg)
{
if (val) {
passed(msg);
} else {
fail(msg);
}
}
namespace std {
template <class T>
basic_ostream<T, char_traits<T> >&
operator<<(basic_ostream<T, char_traits<T> >& os, nsresult rv)
{
os << static_cast<uint32_t>(rv);
return os;
}
}
template <class T, class U>
void is(const T& a, const U& b, const char* msg)
{
std::stringstream ss;
ss << msg << ", Got: " << a << ", expected: " << b;
ok(a == b, ss.str().c_str());
}
template <>
void is(const float& a, const float& b, const char* msg)
{
// stupidly high, since we mostly care about the correctness of the algorithm
const float kEpsilon = 0.00001f;
std::stringstream ss;
ss << msg << ", Got: " << a << ", expected: " << b;
ok(fabsf(a - b) < kEpsilon, ss.str().c_str());
}
class FloatArrayMock
{
public:
// This implementation is not used for now, so let's just return dummy values.
float* Data() const
{
return nullptr;
}
uint32_t Length() const
{
return 0;
}
bool inited() const
{
return true;
}
};
class ErrorResultMock
{
public:
ErrorResultMock()
: mRv(NS_OK)
{
}
void Throw(nsresult aRv)
{
mRv = aRv;
}
operator nsresult() const
{
return mRv;
}
private:
nsresult mRv;
};
typedef AudioEventTimeline<FloatArrayMock, ErrorResultMock> Timeline;
void TestSpecExample()
{
// First, run the basic tests
Timeline timeline(10.0f, .1f, 20.0f);
is(timeline.DefaultValue(), 10.0f, "Correct default value returned");
is(timeline.MinValue(), .1f, "Correct min value returned");
is(timeline.MaxValue(), 20.0f, "Correct max value returned");
ErrorResultMock rv;
// This test is copied from the example in the Web Audio spec
const float t0 = 0.0f,
t1 = 0.1f,
t2 = 0.2f,
t3 = 0.3f,
t4 = 0.4f,
t5 = 0.6f,
t6 = 0.7f/*,
t7 = 1.0f*/;
timeline.SetValueAtTime(0.2f, t0, rv);
is(rv, NS_OK, "SetValueAtTime succeeded");
timeline.SetValueAtTime(0.3f, t1, rv);
is(rv, NS_OK, "SetValueAtTime succeeded");
timeline.SetValueAtTime(0.4f, t2, rv);
is(rv, NS_OK, "SetValueAtTime succeeded");
timeline.LinearRampToValueAtTime(1.0f, t3, rv);
is(rv, NS_OK, "LinearRampToValueAtTime succeeded");
timeline.LinearRampToValueAtTime(0.15f, t4, rv);
is(rv, NS_OK, "LinearRampToValueAtTime succeeded");
timeline.ExponentialRampToValueAtTime(0.75f, t5, rv);
is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded");
timeline.ExponentialRampToValueAtTime(0.05f, t6, rv);
is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded");
// TODO: Add the SetValueCurveAtTime test
is(timeline.GetValueAtTime(0.0f), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.05f), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.1f), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.15f), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.2f), 0.4f, "Correct value");
is(timeline.GetValueAtTime(0.25f), (0.4f + 1.0f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.3f), 1.0f, "Correct value");
is(timeline.GetValueAtTime(0.35f), (1.0f + 0.15f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.4f), 0.15f, "Correct value");
is(timeline.GetValueAtTime(0.45f), (0.15f * powf(0.75f / 0.15f, 0.05f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.5f), (0.15f * powf(0.75f / 0.15f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.55f), (0.15f * powf(0.75f / 0.15f, 0.15f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.6f), 0.75f, "Correct value");
is(timeline.GetValueAtTime(0.65f), (0.75f * powf(0.05 / 0.75f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.7f), 0.05f, "Correct value");
is(timeline.GetValueAtTime(1.0f), 0.05f, "Correct value");
}
void TestInvalidEvents()
{
MOZ_STATIC_ASSERT(numeric_limits<float>::has_quiet_NaN, "Platform must have a quiet NaN");
const float NaN = numeric_limits<float>::quiet_NaN();
const float Infinity = numeric_limits<float>::infinity();
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValueAtTime(NaN, 0.1f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetValueAtTime(Infinity, 0.1f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetValueAtTime(-Infinity, 0.1f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.LinearRampToValueAtTime(NaN, 0.2f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.LinearRampToValueAtTime(Infinity, 0.2f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.LinearRampToValueAtTime(-Infinity, 0.2f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.ExponentialRampToValueAtTime(NaN, 0.3f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.ExponentialRampToValueAtTime(Infinity, 0.3f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.ExponentialRampToValueAtTime(-Infinity, 0.4f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(NaN, 0.4f, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(Infinity, 0.4f, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(-Infinity, 0.4f, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(0.4f, NaN, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(0.4f, Infinity, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetTargetAtTime(0.4f, -Infinity, 1.0f, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
// TODO: Test SetValueCurveAtTime
}
void TestEventReplacement()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
is(timeline.GetEventCount(), 0, "No events yet");
timeline.SetValueAtTime(10.0f, 0.1f, rv);
is(timeline.GetEventCount(), 1, "One event scheduled now");
timeline.SetValueAtTime(20.0f, 0.1f, rv);
is(rv, NS_OK, "Event scheduling should be successful");
is(timeline.GetEventCount(), 1, "Event should be replaced");
is(timeline.GetValueAtTime(0.1f), 20.0f, "The first event should be overwritten");
timeline.LinearRampToValueAtTime(30.0f, 0.1f, rv);
is(rv, NS_OK, "Event scheduling should be successful");
is(timeline.GetEventCount(), 2, "Different event type should be appended");
is(timeline.GetValueAtTime(0.1f), 30.0f, "The first event should be overwritten");
}
void TestBeforeFirstEvent()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValueAtTime(20.0f, 1.0f, rv);
is(timeline.GetValueAtTime(0.5f), 10.0f, "Retrun the default value before the first event");
}
void TestAfterLastValueEvent()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValueAtTime(20.0f, 1.0f, rv);
is(timeline.GetValueAtTime(1.5f), 20.0f, "Return the last value after the last SetValue event");
}
void TestAfterLastTargetValueEvent()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetTargetAtTime(20.0f, 1.0f, 5.0f, rv);
is(timeline.GetValueAtTime(10.f), (20.f + (10.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after the last SetTarget event based on the curve");
}
void TestAfterLastTargetValueEventWithValueSet()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValue(50.f);
timeline.SetTargetAtTime(20.0f, 1.0f, 5.0f, rv);
is(timeline.GetValueAtTime(10.f), (20.f + (50.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after SetValue and the last SetTarget event based on the curve");
}
void TestValue()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
is(timeline.Value(), 10.0f, "value should initially match the default value");
timeline.SetValue(20.0f);
is(timeline.Value(), 20.0f, "Should be able to set the value");
timeline.SetValueAtTime(20.0f, 1.0f, rv);
// TODO: The following check needs to change when we compute the value based on the current time of the context
is(timeline.Value(), 20.0f, "TODO...");
timeline.SetValue(30.0f);
is(timeline.Value(), 20.0f, "Should not be able to set the value");
}
void TestLinearRampAtZero()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.LinearRampToValueAtTime(20.0f, 0.0f, rv);
is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0");
}
void TestExponentialRampAtZero()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.ExponentialRampToValueAtTime(20.0f, 0.0f, rv);
is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0");
}
void TestLinearRampAtSameTime()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValueAtTime(5.0f, 1.0f, rv);
timeline.LinearRampToValueAtTime(20.0f, 1.0f, rv);
is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1");
}
void TestExponentialRampAtSameTime()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetValueAtTime(5.0f, 1.0f, rv);
timeline.ExponentialRampToValueAtTime(20.0f, 1.0f, rv);
is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1");
}
void TestSetTargetZeroTimeConstant()
{
Timeline timeline(10.0f, .1f, 20.0f);
ErrorResultMock rv;
timeline.SetTargetAtTime(20.0f, 1.0f, 0.0f, rv);
is(timeline.GetValueAtTime(10.f), 20.f, "Should get the correct value with timeConstant == 0");
}
int main()
{
ScopedXPCOM xpcom("TestAudioEventTimeline");
if (xpcom.failed()) {
return 1;
}
TestSpecExample();
TestInvalidEvents();
TestEventReplacement();
TestBeforeFirstEvent();
TestAfterLastValueEvent();
TestAfterLastTargetValueEvent();
TestAfterLastTargetValueEventWithValueSet();
TestValue();
TestLinearRampAtZero();
TestExponentialRampAtZero();
TestLinearRampAtSameTime();
TestExponentialRampAtSameTime();
TestSetTargetZeroTimeConstant();
return gFailCount > 0;
}

View File

@ -5,6 +5,7 @@
#include "mozilla/StandardInteger.h"
#include "mozilla/Util.h"
#include "mozilla/Likely.h"
#include "nsGkAtoms.h"
#include "nsLayoutUtils.h"
@ -1329,7 +1330,7 @@ nsSVGSVGElement::
NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
"Setting override value when it's already set...?");
if (NS_UNLIKELY(NS_FAILED(rv))) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
// property-insertion failed (e.g. OOM in property-table code)
delete pAROverridePtr;
return false;
@ -1443,7 +1444,7 @@ nsSVGSVGElement::SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox)
NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
"Setting override value when it's already set...?");
if (NS_UNLIKELY(NS_FAILED(rv))) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
// property-insertion failed (e.g. OOM in property-table code)
delete pViewBoxOverridePtr;
return false;

View File

@ -2150,8 +2150,8 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
*aFullscreenAllowed = false;
// For non-content boundaries, check that the enclosing iframe element
// has the mozallowfullscreen attribute set to true. If any ancestor
// iframe does not have mozallowfullscreen=true, then fullscreen is
// has the allowfullscreen attribute set to true. If any ancestor
// iframe does not have allowfullscreen=true, then fullscreen is
// prohibited.
nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(GetAsSupports(this));
if (!win) {
@ -2160,12 +2160,13 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
nsCOMPtr<nsIContent> frameElement = do_QueryInterface(win->GetFrameElementInternal());
if (frameElement &&
frameElement->IsHTML(nsGkAtoms::iframe) &&
!frameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) &&
!frameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
return NS_OK;
}
// If we have no parent then we're the root docshell; no ancestor of the
// original docshell doesn't have a mozallowfullscreen attribute, so
// original docshell doesn't have a allowfullscreen attribute, so
// report fullscreen as allowed.
nsCOMPtr<nsIDocShellTreeItem> dsti = do_GetInterface(GetAsSupports(this));
NS_ENSURE_TRUE(dsti, NS_OK);

View File

@ -772,14 +772,14 @@ protected:
// mFullscreenAllowed stores how we determine whether fullscreen is allowed
// when GetFullscreenAllowed() is called. Fullscreen is allowed in a
// docshell when all containing iframes have the mozallowfullscreen
// docshell when all containing iframes have the allowfullscreen
// attribute set to true. When mFullscreenAllowed is CHECK_ATTRIBUTES
// we check this docshell's containing frame for the mozallowfullscreen
// we check this docshell's containing frame for the allowfullscreen
// attribute, and recurse onto the parent docshell to ensure all containing
// frames also have the mozallowfullscreen attribute. If we find an ancestor
// frames also have the allowfullscreen attribute. If we find an ancestor
// docshell with mFullscreenAllowed not equal to CHECK_ATTRIBUTES, we've
// reached a content boundary, and mFullscreenAllowed denotes whether the
// parent across the content boundary has mozallowfullscreen=true in all its
// parent across the content boundary has allowfullscreen=true in all its
// containing iframes. mFullscreenAllowed defaults to CHECK_ATTRIBUTES and
// is set otherwise when docshells which are content boundaries are created.
enum FullscreenAllowedState {

View File

@ -690,10 +690,10 @@ interface nsIDocShell : nsISupports
/**
* Attribute that determines whether fullscreen is allowed to be entered for
* this subtree of the docshell tree. This is true when all iframes containing
* this docshell have their "mozallowfullscreen" attribute set to "true".
* this docshell have their "allowfullscreen" attribute set to "true".
* fullscreenAllowed is only writable at content boundaries, where it is used
* to propagate the value of the cross process parent's iframe's
* "mozallowfullscreen" attribute to the child process. Setting
* "allowfullscreen" attribute to the child process. Setting
* fullscreenAllowed on docshells which aren't content boundaries throws an
* exception.
*/

View File

@ -547,6 +547,7 @@ WebappsApplication.prototype = {
case "Webapps:CheckForUpdate:Return:OK":
for (let prop in msg.app) {
this[prop] = msg.app[prop];
}
if (msg.event == "downloadapplied") {
Services.DOMRequest.fireSuccess(req, this.manifestURL);
this._fireEvent("downloadapplied", this._ondownloadapplied);
@ -554,7 +555,6 @@ WebappsApplication.prototype = {
Services.DOMRequest.fireSuccess(req, this.manifestURL);
this._fireEvent("downloadavailable", this._ondownloadavailable);
}
}
break;
case "Webapps:CheckForUpdate:Return:KO":
Services.DOMRequest.fireError(req, msg.error);
@ -580,7 +580,7 @@ WebappsApplication.prototype = {
this.downloadSize = app.downloadSize || 0;
this.installState = app.installState;
this.manifest = app.manifest;
this._fireEvent("downloaded", this._ondownloaded);
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
this._fireEvent("downloadapplied", this._ondownloadapplied);
break;
case "canceled":
@ -597,9 +597,9 @@ WebappsApplication.prototype = {
case "downloaded":
app = msg.app;
this.downloading = app.downloading;
this.downloadavailable = app.downloadavailable;
this.downloadAvailable = app.downloadAvailable;
this.readyToApplyDownload = app.readyToApplyDownload;
this._fireEvent("downloaded", this._ondownloaded);
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
break;
case "applied":
app = msg.app;
@ -669,7 +669,7 @@ WebappsApplicationMgmt.prototype = {
return;
}
cpmm.sendAsyncMessage("Webapps::ApplyDownload",
cpmm.sendAsyncMessage("Webapps:ApplyDownload",
{ manifestURL: aApp.manifestURL });
},

View File

@ -70,7 +70,7 @@ let DOMApplicationRegistry = {
"Webapps:GetList", "Webapps:RegisterForMessages",
"Webapps:UnregisterForMessages",
"Webapps:CancelDownload", "Webapps:CheckForUpdate",
"Webapps::Download", "Webapps::ApplyDownload",
"Webapps:Download", "Webapps:ApplyDownload",
"child-process-shutdown"];
this.frameMessages = ["Webapps:ClearBrowserData"];
@ -574,7 +574,7 @@ let DOMApplicationRegistry = {
// These are: getAll(), getNotInstalled() and applyDownload()
if (["Webapps:GetAll",
"Webapps:GetNotInstalled",
"Webapps::ApplyDownload"].indexOf(aMessage.name) != -1) {
"Webapps:ApplyDownload"].indexOf(aMessage.name) != -1) {
if (!aMessage.target.assertPermission("webapps-manage")) {
debug("mozApps message " + aMessage.name +
" from a content process with no 'webapps-manage' privileges.");
@ -596,7 +596,6 @@ let DOMApplicationRegistry = {
break;
case "Webapps:Uninstall":
this.uninstall(msg, mm);
debug("Webapps:Uninstall");
break;
case "Webapps:Launch":
this.launchApp(msg, mm);
@ -644,8 +643,8 @@ let DOMApplicationRegistry = {
case "Webapps:CheckForUpdate":
this.checkForUpdate(msg, mm);
break;
case "Webapps::ApplyDownload":
this.ApplyDownload(msg.manifestURL);
case "Webapps:ApplyDownload":
this.applyDownload(msg.manifestURL);
break;
case "Activities:Register:OK":
this.notifyAppsRegistryReady();
@ -719,7 +718,7 @@ let DOMApplicationRegistry = {
app.progress = 0;
app.installState = app.previousState;
app.downloading = false;
app.downloadavailable = false;
app.downloadAvailable = false;
app.downloadSize = 0;
this._saveApps((function() {
this.broadcastMessage("Webapps:PackageEvent",
@ -730,24 +729,26 @@ let DOMApplicationRegistry = {
}).bind(this));
},
startDownload: function cancelDownload(aManifestURL) {
let app = this.getAppByManifestURL(manifestURL);
startDownload: function startDownload(aManifestURL) {
debug("startDownload for " + aManifestURL);
let id = this._appIdForManifestURL(aManifestURL);
let app = this.webapps[id];
if (!app) {
debug("startDownload: No app found for " + aManifestURL);
return;
}
let id = this._appIdForManifestURL(manifestURL);
// We need to get the update manifest here, not the webapp manifest.
let file = FileUtils.getFile(DIRECTORY_NAME,
["webapps", id, "update.webapp"], true);
this._loadJSONAsync(file, (function(aJSON) {
if (!aJSON) {
debug("startDownload: No update manifest found at " + file.path + " " + aManifestURL);
return;
}
let manifest = new ManifestHelper(aJSON, app.origin);
let manifest = new ManifestHelper(aJSON, app.installOrigin);
this.downloadPackage(manifest, { manifestURL: aManifestURL,
origin: app.origin }, true,
function(aId, aManifest) {
@ -763,13 +764,13 @@ let DOMApplicationRegistry = {
function() { });
// Set state and fire events.
app.downloading = false;
app.downloadavailable = false;
app.downloadAvailable = false;
app.readyToApplyDownload = true;
DOMApplicationRegistry._saveApps(function() {
debug("About to fire Webapps:PackageEvent");
DOMApplicationRegistry.broadcastMessage("Webapps:PackageEvent",
{ type: "downloaded",
manifestURL: manifestURL,
manifestURL: aManifestURL,
app: app,
manifest: aManifest });
});
@ -778,15 +779,16 @@ let DOMApplicationRegistry = {
},
applyDownload: function applyDownload(aManifestURL) {
let app = this.getAppByManifestURL(manifestURL);
debug("applyDownload for " + aManifestURL);
let app = this.getAppByManifestURL(aManifestURL);
if (!app || (app && !app.readyToApplyDownload)) {
return;
}
let id = this._appIdForManifestURL(aApp.manifestURL);
let id = this._appIdForManifestURL(app.manifestURL);
// Move the application.zip and manifest.webapp files out of TmpD
let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], true, true);
let manFile = tmpDir.clone();
manFile.append("manifest.webapp");
let appFile = tmpDir.clone();
@ -805,13 +807,13 @@ let DOMApplicationRegistry = {
app.readyToApplyDownload = false;
this.broadcastMessage("Webapps:PackageEvent",
{ type: "applied",
manifestURL: aApp.manifestURL,
manifestURL: app.manifestURL,
app: app,
manifest: aData });
// Update the permissions for this app.
PermissionsInstaller.installPermissions({ manifest: aData,
origin: app.origin,
manifestURL: aApp.manifestURL },
manifestURL: app.manifestURL },
true);
}).bind(this));
},
@ -835,8 +837,9 @@ let DOMApplicationRegistry = {
},
checkForUpdate: function(aData, aMm) {
let app = this.getAppByManifestURL(aData.manifestURL);
let installOrigin = app.installOrigin;
debug("checkForUpdate for " + aData.manifestURL);
let id = this._appIdForManifestURL(aData.manifestURL);
let app = this.webapps[id];
if (!app) {
aData.error = "NO_SUCH_APP";
@ -851,6 +854,14 @@ let DOMApplicationRegistry = {
function updatePackagedApp(aManifest) {
debug("updatePackagedApp");
// if the app manifestURL has a app:// scheme, we can't have an
// update.
if (app.manifestURL.startsWith("app://")) {
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
return;
}
let manifest = new ManifestHelper(aManifest, app.manifestURL);
// A package is available: set downloadAvailable to fire the matching
// event.
@ -910,9 +921,10 @@ let DOMApplicationRegistry = {
// Update the registry.
this.webapps[id] = app;
this._saveApps((function() {
// XXX Should we fire notifications ?
}).bind(this));
this._saveApps(function() {
aData.event = "downloadapplied";
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:OK", aData);
});
// Preload the appcache if needed.
this.startOfflineCacheDownload(manifest, app);
@ -928,8 +940,8 @@ let DOMApplicationRegistry = {
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", aData.manifestURL, true);
if (aData.etag) {
xhr.setRequestHeader("If-None-Match", aData.etag);
if (app.etag) {
xhr.setRequestHeader("If-None-Match", app.etag);
}
xhr.addEventListener("load", (function() {
@ -941,15 +953,15 @@ let DOMApplicationRegistry = {
sendError("MANIFEST_PARSE_ERROR");
return;
}
if (!AppsUtils.checkManifest(manifest, installOrigin)) {
if (!AppsUtils.checkManifest(manifest, app.installOrigin)) {
sendError("INVALID_MANIFEST");
} else {
app.etag = xhr.getResponseHeader("Etag");
app.lastCheckedUpdate = Date.now();
if (manifest.package_path) {
if (app.origin.startsWith("app://")) {
updatePackagedApp(manifest);
} else {
updateHostedApp(manifest);
updateHostedApp.call(this, manifest);
}
}
this._saveApps();
@ -968,7 +980,7 @@ let DOMApplicationRegistry = {
}).bind(this), false);
xhr.addEventListener("error", (function() {
sendError(request, "NETWORK_ERROR");
sendError("NETWORK_ERROR");
}).bind(this), false);
xhr.send(null);
@ -1119,14 +1131,14 @@ let DOMApplicationRegistry = {
// Set state and fire events.
app.installState = "installed";
app.downloading = false;
app.downloadavailable = false;
app.downloadAvailable = false;
DOMApplicationRegistry._saveApps(function() {
// Update the permissions for this app.
PermissionsInstaller.installPermissions({ manifest: aManifest,
origin: appObject.origin,
manifestURL: appObject.manifestURL },
true);
debug("About to fire Webapps:PackageEvent");
debug("About to fire Webapps:PackageEvent 'installed'");
DOMApplicationRegistry.broadcastMessage("Webapps:PackageEvent",
{ type: "installed",
manifestURL: appObject.manifestURL,

View File

@ -553,6 +553,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/HTMLCollectionBinding.h"
#include "mozilla/Likely.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -702,6 +703,24 @@ DOMCI_DATA_NO_CLASS(DOMConstructor)
namespace {
class IDBFactorySH : public nsDOMGenericSH
{
protected:
IDBFactorySH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
{ }
virtual ~IDBFactorySH()
{ }
public:
NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto);
static nsIClassInfo *doCreate(nsDOMClassInfoData *aData)
{
return new IDBFactorySH(aData);
}
};
class IDBEventTargetSH : public nsEventTargetSH
{
protected:
@ -1580,7 +1599,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
NS_DEFINE_CLASSINFO_DATA(IDBFactory, IDBFactorySH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(IDBFileHandle, FileHandle, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
@ -6683,12 +6702,40 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
return NS_OK;
}
Maybe<JSAutoCompartment> ac;
JSObject* global;
bool defineOnXray = ObjectIsNativeWrapper(cx, obj);
if (defineOnXray) {
global = xpc::Unwrap(cx, obj, false);
if (!global) {
return NS_ERROR_DOM_SECURITY_ERR;
}
ac.construct(cx, global);
} else {
global = obj;
}
bool enabled;
bool defined = define(cx, obj, &enabled);
MOZ_ASSERT_IF(defined, enabled);
JSObject* interfaceObject = define(cx, global, &enabled);
if (enabled) {
*did_resolve = defined;
return defined ? NS_OK : NS_ERROR_FAILURE;
if (!interfaceObject) {
return NS_ERROR_FAILURE;
}
if (defineOnXray) {
// This really should be handled by the Xray for the window.
ac.destroy();
if (!JS_WrapObject(cx, &interfaceObject) ||
!JS_DefinePropertyById(cx, obj, id,
JS::ObjectValue(*interfaceObject), nullptr,
nullptr, 0)) {
return NS_ERROR_FAILURE;
}
}
*did_resolve = true;
return NS_OK;
}
}
}
@ -7939,6 +7986,92 @@ nsDOMMutationObserverSH::PreserveWrapper(nsISupports* aNative)
nsContentUtils::PreserveWrapper(aNative, mutationObserver);
}
// IDBFactory helper
/* static */
template<nsresult (*func)(JSContext *, unsigned, jsval *, bool), bool aDelete>
JSBool
IDBFNativeShim(JSContext *cx, unsigned argc, jsval *vp)
{
nsresult rv = (*func)(cx, argc, vp, aDelete);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return false;
}
return true;
}
/* static */ nsresult
IDBFOpenForPrincipal(JSContext *cx, unsigned argc, JS::Value *vp, bool aDelete)
{
// Just to be on the extra-safe side
if (!nsContentUtils::IsCallerChrome()) {
MOZ_NOT_REACHED("Shouldn't be possible to get here");
return NS_ERROR_FAILURE;
}
JSObject* principalJS;
JSString* nameJS;
uint32_t version = 0;
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "oS/u",
&principalJS, &nameJS, &version)) {
return NS_ERROR_FAILURE;
}
if (version < 1 && argc >= 3) {
return NS_ERROR_TYPE_ERR;
}
if (aDelete) {
version = 0;
}
nsDependentJSString name;
NS_ENSURE_TRUE(name.init(cx, nameJS), NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIPrincipal> principal = do_QueryWrapper(cx, principalJS);
NS_ENSURE_TRUE(principal, NS_ERROR_NO_INTERFACE);
nsCString extendedOrigin;
nsresult rv = principal->GetExtendedOrigin(extendedOrigin);
NS_ENSURE_FALSE(extendedOrigin.IsEmpty(), NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIIDBFactory> factory =
do_QueryWrapper(cx, JS_THIS_OBJECT(cx, vp));
NS_ENSURE_TRUE(factory, NS_ERROR_NO_INTERFACE);
nsRefPtr<indexedDB::IDBOpenDBRequest> request;
rv = static_cast<indexedDB::IDBFactory*>(factory.get())->
OpenCommon(name, version, extendedOrigin, aDelete, cx,
getter_AddRefs(request));
NS_ENSURE_SUCCESS(rv, rv);
return WrapNative(cx, JS_GetGlobalForScopeChain(cx),
static_cast<nsIIDBOpenDBRequest*>(request),
&NS_GET_IID(nsIIDBOpenDBRequest), true, vp);
}
NS_IMETHODIMP
IDBFactorySH::PostCreatePrototype(JSContext * cx, JSObject * proto)
{
// set up our proto first
nsresult rv = nsDOMGenericSH::PostCreatePrototype(cx, proto);
NS_ENSURE_SUCCESS(rv, rv);
if (xpc::AccessCheck::isChrome(js::GetObjectCompartment(proto)) &&
(!JS_DefineFunction(cx, proto, "openForPrincipal",
IDBFNativeShim<IDBFOpenForPrincipal, false>,
3, JSPROP_ENUMERATE) ||
!JS_DefineFunction(cx, proto, "deleteForPrincipal",
IDBFNativeShim<IDBFOpenForPrincipal, true>,
2, JSPROP_ENUMERATE))) {
return NS_ERROR_UNEXPECTED;
}
return rv;
}
// IDBEventTarget helper
NS_IMETHODIMP
@ -9149,7 +9282,7 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
if (!::JS_GetPrototype(cx, obj, &proto)) {
return JS_FALSE;
}
if (NS_UNLIKELY(!proto)) {
if (MOZ_UNLIKELY(!proto)) {
return JS_TRUE;
}
@ -9853,7 +9986,7 @@ nsHTMLPluginObjElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
return NS_ERROR_UNEXPECTED;
}
if (NS_UNLIKELY(!pi_obj)) {
if (MOZ_UNLIKELY(!pi_obj)) {
return NS_OK;
}
@ -9885,7 +10018,7 @@ nsHTMLPluginObjElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
return NS_ERROR_UNEXPECTED;
}
if (NS_UNLIKELY(!pi_obj)) {
if (MOZ_UNLIKELY(!pi_obj)) {
return NS_OK;
}

View File

@ -273,7 +273,8 @@ protected:
static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
};
// THIS ONE ISN'T SAFE!! It assumes that the private of the JSObject is
// an nsISupports.
inline
const nsQueryInterface
do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
@ -281,6 +282,8 @@ do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
return nsQueryInterface(nsDOMClassInfo::GetNative(wrapper, obj));
}
// THIS ONE ISN'T SAFE!! It assumes that the private of the JSObject is
// an nsISupports.
inline
const nsQueryInterfaceWithError
do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj,

View File

@ -42,6 +42,7 @@
#include "nsCharSeparatedTokenizer.h" // for Accept-Language parsing
#include "nsUnicharUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Likely.h"
// Other Classes
#include "nsEventListenerManager.h"
@ -1286,7 +1287,7 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
PR_snprintf(name, sizeof(name), "nsGlobalWindow #%ld", tmp->mWindowID);
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);

View File

@ -20,6 +20,7 @@
#include "nsIContentSecurityPolicy.h"
#include "nsAlgorithm.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
static const char kSetIntervalStr[] = "setInterval";
static const char kSetTimeoutStr[] = "setTimeout";
@ -76,7 +77,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSScriptTimeoutHandler)
tmp->ReleaseJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
nsAutoCString name("nsJSScriptTimeoutHandler");
if (tmp->mExpr) {
name.AppendLiteral(" [");

View File

@ -37,6 +37,7 @@
#include "jsfriendapi.h"
#include "nsContentUtils.h"
#include "nsEventStateManager.h"
#include "mozilla/Likely.h"
static nsresult
GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
@ -939,7 +940,7 @@ nsLocation::CallerSubsumes()
{
// Get the principal associated with the location object.
nsCOMPtr<nsIDOMWindow> outer = do_QueryReferent(mOuter);
if (NS_UNLIKELY(!outer))
if (MOZ_UNLIKELY(!outer))
return false;
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
bool subsumes = false;

View File

@ -146,10 +146,23 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
return xpc::NonVoidStringToJsval(cx, str, vp);
}
JSBool
Constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
const JS::Value& v =
js::GetFunctionNativeReserved(callee,
CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT);
JSNativeHolder* nativeHolder = static_cast<JSNativeHolder*>(v.toPrivate());
return (nativeHolder->mNative)(cx, argc, vp);
}
static JSObject*
CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
JSClass* constructorClass, JSNative constructorNative,
unsigned ctorNargs, JSObject* proto,
CreateInterfaceObject(JSContext* cx, JSObject* global,
JSClass* constructorClass,
JSNativeHolder* constructorNative,
unsigned ctorNargs,
JSObject* proto,
const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties,
const char* name)
@ -163,12 +176,16 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
constructor = JS_NewObject(cx, constructorClass, functionProto, global);
} else {
MOZ_ASSERT(constructorNative);
JSFunction* fun = JS_NewFunction(cx, constructorNative, ctorNargs,
JSFUN_CONSTRUCTOR, global, name);
JSFunction* fun = js::NewFunctionWithReserved(cx, Constructor, ctorNargs,
JSFUN_CONSTRUCTOR, global,
name);
if (!fun) {
return NULL;
}
constructor = JS_GetFunctionObject(fun);
js::SetFunctionNativeReserved(constructor,
CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT,
js::PrivateValue(constructorNative));
}
if (!constructor) {
return NULL;
@ -201,6 +218,11 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
return nullptr;
}
if (properties->staticAttributes &&
!DefinePrefable(cx, constructor, properties->staticAttributes)) {
return nullptr;
}
if (properties->constants &&
!DefinePrefable(cx, constructor, properties->constants)) {
return nullptr;
@ -213,6 +235,12 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
return nullptr;
}
if (chromeOnlyProperties->staticAttributes &&
!DefinePrefable(cx, constructor,
chromeOnlyProperties->staticAttributes)) {
return nullptr;
}
if (chromeOnlyProperties->constants &&
!DefinePrefable(cx, constructor, chromeOnlyProperties->constants)) {
return nullptr;
@ -224,13 +252,13 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
}
JSBool alreadyDefined;
if (!JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined)) {
if (!JS_AlreadyHasOwnProperty(cx, global, name, &alreadyDefined)) {
return NULL;
}
// This is Enumerable: False per spec.
if (!alreadyDefined &&
!JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
!JS_DefineProperty(cx, global, name, OBJECT_TO_JSVAL(constructor), NULL,
NULL, 0)) {
return NULL;
}
@ -287,11 +315,12 @@ CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
return ourProto;
}
JSObject*
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
JSObject* protoProto, JSClass* protoClass,
JSClass* constructorClass, JSNative constructor,
unsigned ctorNargs, const DOMClass* domClass,
void
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
JSClass* protoClass, JSObject** protoCache,
JSClass* constructorClass, JSNativeHolder* constructor,
unsigned ctorNargs, JSObject** constructorCache,
const DOMClass* domClass,
const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties,
const char* name)
@ -304,24 +333,35 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
(chromeOnlyProperties->methods ||
chromeOnlyProperties->attributes))) || protoClass,
"Methods or properties but no protoClass!");
MOZ_ASSERT(!((properties && properties->staticMethods) ||
(chromeOnlyProperties && chromeOnlyProperties->staticMethods)) ||
MOZ_ASSERT(!((properties &&
(properties->staticMethods || properties->staticAttributes)) ||
(chromeOnlyProperties &&
(chromeOnlyProperties->staticMethods ||
chromeOnlyProperties->staticAttributes))) ||
constructorClass || constructor,
"Static methods but no constructorClass or constructor!");
MOZ_ASSERT(bool(name) == bool(constructorClass || constructor),
"Must have name precisely when we have an interface object");
MOZ_ASSERT(!constructorClass || !constructor);
MOZ_ASSERT(!protoClass == !protoCache,
"If, and only if, there is an interface prototype object we need "
"to cache it");
MOZ_ASSERT(!(constructorClass || constructor) == !constructorCache,
"If, and only if, there is an interface object we need to cache "
"it");
JSObject* proto;
if (protoClass) {
proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
properties, chromeOnlyProperties);
if (!proto) {
return NULL;
return;
}
js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
JS::PrivateValue(const_cast<DOMClass*>(domClass)));
*protoCache = proto;
}
else {
proto = NULL;
@ -329,15 +369,19 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
JSObject* interface;
if (constructorClass || constructor) {
interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
constructor, ctorNargs, proto,
properties, chromeOnlyProperties, name);
interface = CreateInterfaceObject(cx, global, constructorClass, constructor,
ctorNargs, proto, properties,
chromeOnlyProperties, name);
if (!interface) {
return NULL;
if (protoCache) {
// If we fail we need to make sure to clear the value of protoCache we
// set above.
*protoCache = nullptr;
}
return;
}
*constructorCache = interface;
}
return protoClass ? proto : interface;
}
static bool
@ -472,52 +516,55 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
}
static bool
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
JSPropertyDescriptor* desc,
const NativeProperties* nativeProperties)
inline const NativePropertyHooks*
GetNativePropertyHooks(JSContext *cx, JSObject *obj, DOMObjectType& type)
{
if (nativeProperties->methods) {
Prefable<JSFunctionSpec>* method;
for (method = nativeProperties->methods; method->specs; ++method) {
if (method->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = method->specs - nativeProperties->methodsSpecs;
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
if (id == nativeProperties->methodIds[i]) {
JSFunctionSpec& methodSpec = nativeProperties->methodsSpecs[i];
JSFunction *fun = JS_NewFunctionById(cx, methodSpec.call.op,
methodSpec.nargs, 0,
wrapper, id);
if (!fun) {
return false;
}
SET_JITINFO(fun, methodSpec.call.info);
JSObject *funobj = JS_GetFunctionObject(fun);
desc->value.setObject(*funobj);
desc->attrs = methodSpec.flags;
desc->obj = wrapper;
desc->setter = nullptr;
desc->getter = nullptr;
return true;
}
}
}
}
const DOMClass* domClass;
if (GetDOMClass(obj, domClass) != eNonDOMObject) {
type = eInstance;
return domClass->mNativeHooks;
}
JSPropertySpec* attributeSpecs = nativeProperties->attributeSpecs;
Prefable<JSPropertySpec>* attr = nativeProperties->attributes;
jsid* attributeIds = nativeProperties->attributeIds;
// Do the attribute stuff for attributes, then for unforgeable attributes
for (int attrIteration = 0; attrIteration < 2; ++attrIteration) {
if (attr) {
for (; attr->specs; ++attr) {
if (attr->enabled) {
if (JS_ObjectIsFunction(cx, obj)) {
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
type = eInterface;
const JS::Value& v =
js::GetFunctionNativeReserved(obj,
CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT);
JSNativeHolder* nativeHolder = static_cast<JSNativeHolder*>(v.toPrivate());
return nativeHolder->mPropertyHooks;
}
MOZ_ASSERT(IsDOMIfaceAndProtoClass(js::GetObjectClass(obj)));
const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj));
type = ifaceAndProtoJSClass->mType;
return ifaceAndProtoJSClass->mNativeHooks;
}
bool
XrayResolveOwnProperty(JSContext* cx, JSObject* wrapper, JSObject* obj, jsid id,
bool set, JSPropertyDescriptor* desc)
{
DOMObjectType type;
const NativePropertyHooks *nativePropertyHooks =
GetNativePropertyHooks(cx, obj, type);
return type != eInstance || !nativePropertyHooks->mResolveOwnProperty ||
nativePropertyHooks->mResolveOwnProperty(cx, wrapper, obj, id, set,
desc);
}
static bool
XrayResolveAttribute(JSContext* cx, JSObject* wrapper, jsid id,
Prefable<JSPropertySpec>* attributes, jsid* attributeIds,
JSPropertySpec* attributeSpecs, JSPropertyDescriptor* desc)
{
for (; attributes->specs; ++attributes) {
if (attributes->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = attr->specs - attributeSpecs;
size_t i = attributes->specs - attributeSpecs;
for ( ; attributeIds[i] != JSID_VOID; ++i) {
if (id == attributeIds[i]) {
JSPropertySpec& attrSpec = attributeSpecs[i];
@ -554,11 +601,92 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
}
}
}
return true;
}
attributeSpecs = nativeProperties->unforgeableAttributeSpecs;
attr = nativeProperties->unforgeableAttributes;
attributeIds = nativeProperties->unforgeableAttributeIds;
static bool
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
JSPropertyDescriptor* desc, DOMObjectType type,
const NativeProperties* nativeProperties)
{
Prefable<JSFunctionSpec>* methods;
jsid* methodIds;
JSFunctionSpec* methodsSpecs;
if (type == eInterface) {
methods = nativeProperties->staticMethods;
methodIds = nativeProperties->staticMethodIds;
methodsSpecs = nativeProperties->staticMethodsSpecs;
} else {
methods = nativeProperties->methods;
methodIds = nativeProperties->methodIds;
methodsSpecs = nativeProperties->methodsSpecs;
}
if (methods) {
Prefable<JSFunctionSpec>* method;
for (method = methods; method->specs; ++method) {
if (method->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = method->specs - methodsSpecs;
for ( ; methodIds[i] != JSID_VOID; ++i) {
if (id == methodIds[i]) {
JSFunctionSpec& methodSpec = methodsSpecs[i];
JSFunction *fun = JS_NewFunctionById(cx, methodSpec.call.op,
methodSpec.nargs, 0,
wrapper, id);
if (!fun) {
return false;
}
SET_JITINFO(fun, methodSpec.call.info);
JSObject *funobj = JS_GetFunctionObject(fun);
desc->value.setObject(*funobj);
desc->attrs = methodSpec.flags;
desc->obj = wrapper;
desc->setter = nullptr;
desc->getter = nullptr;
return true;
}
}
}
}
}
if (type == eInterface) {
if (nativeProperties->staticAttributes) {
if (!XrayResolveAttribute(cx, wrapper, id,
nativeProperties->staticAttributes,
nativeProperties->staticAttributeIds,
nativeProperties->staticAttributeSpecs, desc)) {
return false;
}
if (desc->obj) {
return true;
}
}
} else {
if (nativeProperties->attributes) {
if (!XrayResolveAttribute(cx, wrapper, id,
nativeProperties->attributes,
nativeProperties->attributeIds,
nativeProperties->attributeSpecs, desc)) {
return false;
}
if (desc->obj) {
return true;
}
}
if (nativeProperties->unforgeableAttributes) {
if (!XrayResolveAttribute(cx, wrapper, id,
nativeProperties->unforgeableAttributes,
nativeProperties->unforgeableAttributeIds,
nativeProperties->unforgeableAttributeSpecs,
desc)) {
return false;
}
if (desc->obj) {
return true;
}
}
}
if (nativeProperties->constants) {
@ -583,21 +711,64 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
return true;
}
bool
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
JSPropertyDescriptor* desc,
const NativeProperties* nativeProperties,
const NativeProperties* chromeOnlyNativeProperties)
static bool
ResolvePrototypeOrConstructor(JSContext* cx, JSObject* wrapper, JSObject* obj,
size_t protoAndIfaceArrayIndex, unsigned attrs,
JSPropertyDescriptor* desc)
{
if (nativeProperties &&
!XrayResolveProperty(cx, wrapper, id, desc, nativeProperties)) {
JSObject* global = js::GetGlobalForObjectCrossCompartment(obj);
{
JSAutoCompartment ac(cx, global);
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(global);
JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
if (!protoOrIface) {
return false;
}
desc->obj = wrapper;
desc->shortid = 0;
desc->attrs = attrs;
desc->getter = JS_PropertyStub;
desc->setter = JS_StrictPropertyStub;
desc->value = JS::ObjectValue(*protoOrIface);
}
return JS_WrapPropertyDescriptor(cx, desc);
}
bool
XrayResolveNativeProperty(JSContext* cx, JSObject* wrapper,
const NativePropertyHooks* nativePropertyHooks,
DOMObjectType type, JSObject* obj, jsid id,
JSPropertyDescriptor* desc)
{
if (type == eInterface && IdEquals(id, "prototype")) {
return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count ||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
nativePropertyHooks->mPrototypeID,
JSPROP_PERMANENT | JSPROP_READONLY,
desc);
}
if (type == eInterfacePrototype && IdEquals(id, "constructor")) {
return nativePropertyHooks->mConstructorID == constructors::id::_ID_Count ||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
nativePropertyHooks->mConstructorID,
0, desc);
}
const NativePropertiesHolder& nativeProperties =
nativePropertyHooks->mNativeProperties;
if (nativeProperties.regular &&
!XrayResolveProperty(cx, wrapper, id, desc, type,
nativeProperties.regular)) {
return false;
}
if (!desc->obj &&
chromeOnlyNativeProperties &&
nativeProperties.chromeOnly &&
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
!XrayResolveProperty(cx, wrapper, id, desc, chromeOnlyNativeProperties)) {
!XrayResolveProperty(cx, wrapper, id, desc, type,
nativeProperties.chromeOnly)) {
return false;
}
@ -605,37 +776,48 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
}
bool
XrayEnumerateProperties(JS::AutoIdVector& props,
const NativeProperties* nativeProperties)
XrayResolveNativeProperty(JSContext* cx, JSObject* wrapper, JSObject* obj,
jsid id, JSPropertyDescriptor* desc)
{
if (nativeProperties->methods) {
Prefable<JSFunctionSpec>* method;
for (method = nativeProperties->methods; method->specs; ++method) {
if (method->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = method->specs - nativeProperties->methodsSpecs;
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
if ((nativeProperties->methodsSpecs[i].flags & JSPROP_ENUMERATE) &&
!props.append(nativeProperties->methodIds[i])) {
return false;
}
}
}
}
DOMObjectType type;
const NativePropertyHooks* nativePropertyHooks =
GetNativePropertyHooks(cx, obj, type);
if (type == eInstance) {
// Force the type to be eInterfacePrototype, since we need to walk the
// prototype chain.
type = eInterfacePrototype;
}
JSPropertySpec* attributeSpecs = nativeProperties->attributeSpecs;
Prefable<JSPropertySpec>* attr = nativeProperties->attributes;
jsid* attributeIds = nativeProperties->attributeIds;
// Do the attribute stuff for attributes, then for unforgeable attributes
for (int attrIteration = 0; attrIteration < 2; ++attrIteration) {
if (attr) {
for (; attr->specs; ++attr) {
if (attr->enabled) {
if (type == eInterfacePrototype) {
do {
if (!XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
obj, id, desc)) {
return false;
}
if (desc->obj) {
return true;
}
} while ((nativePropertyHooks = nativePropertyHooks->mProtoHooks));
return true;
}
return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type, obj,
id, desc);
}
bool
XrayEnumerateAttributes(Prefable<JSPropertySpec>* attributes,
jsid* attributeIds, JSPropertySpec* attributeSpecs,
JS::AutoIdVector& props)
{
for (; attributes->specs; ++attributes) {
if (attributes->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = attr->specs - attributeSpecs;
size_t i = attributes->specs - attributeSpecs;
for ( ; attributeIds[i] != JSID_VOID; ++i) {
if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
!props.append(attributeIds[i])) {
@ -644,11 +826,64 @@ XrayEnumerateProperties(JS::AutoIdVector& props,
}
}
}
return true;
}
attributeSpecs = nativeProperties->unforgeableAttributeSpecs;
attr = nativeProperties->unforgeableAttributes;
attributeIds = nativeProperties->unforgeableAttributeIds;
bool
XrayEnumerateProperties(JS::AutoIdVector& props, DOMObjectType type,
const NativeProperties* nativeProperties)
{
Prefable<JSFunctionSpec>* methods;
jsid* methodIds;
JSFunctionSpec* methodsSpecs;
if (type == eInterface) {
methods = nativeProperties->staticMethods;
methodIds = nativeProperties->staticMethodIds;
methodsSpecs = nativeProperties->staticMethodsSpecs;
} else {
methods = nativeProperties->methods;
methodIds = nativeProperties->methodIds;
methodsSpecs = nativeProperties->methodsSpecs;
}
if (methods) {
Prefable<JSFunctionSpec>* method;
for (method = methods; method->specs; ++method) {
if (method->enabled) {
// Set i to be the index into our full list of ids/specs that we're
// looking at now.
size_t i = method->specs - methodsSpecs;
for ( ; methodIds[i] != JSID_VOID; ++i) {
if ((methodsSpecs[i].flags & JSPROP_ENUMERATE) &&
!props.append(methodIds[i])) {
return false;
}
}
}
}
}
if (type == eInterface) {
if (nativeProperties->staticAttributes &&
!XrayEnumerateAttributes(nativeProperties->staticAttributes,
nativeProperties->staticAttributeIds,
nativeProperties->staticAttributeSpecs,
props)) {
return false;
}
} else {
if (nativeProperties->attributes &&
!XrayEnumerateAttributes(nativeProperties->attributes,
nativeProperties->attributeIds,
nativeProperties->attributeSpecs, props)) {
return false;
}
if (nativeProperties->unforgeableAttributes &&
!XrayEnumerateAttributes(nativeProperties->unforgeableAttributes,
nativeProperties->unforgeableAttributeIds,
nativeProperties->unforgeableAttributeSpecs,
props)) {
return false;
}
}
if (nativeProperties->constants) {
@ -671,25 +906,91 @@ XrayEnumerateProperties(JS::AutoIdVector& props,
}
bool
XrayEnumerateProperties(JSObject* wrapper,
JS::AutoIdVector& props,
const NativeProperties* nativeProperties,
const NativeProperties* chromeOnlyNativeProperties)
XrayEnumerateNativeProperties(JSContext* cx, JSObject* wrapper,
const NativePropertyHooks* nativePropertyHooks,
DOMObjectType type, JSObject* obj,
JS::AutoIdVector& props)
{
if (nativeProperties &&
!XrayEnumerateProperties(props, nativeProperties)) {
if (type == eInterface &&
nativePropertyHooks->mPrototypeID != prototypes::id::_ID_Count &&
!AddStringToIDVector(cx, props, "prototype")) {
return false;
}
if (chromeOnlyNativeProperties &&
if (type == eInterfacePrototype &&
nativePropertyHooks->mConstructorID != constructors::id::_ID_Count &&
!AddStringToIDVector(cx, props, "constructor")) {
return false;
}
const NativePropertiesHolder& nativeProperties =
nativePropertyHooks->mNativeProperties;
if (nativeProperties.regular &&
!XrayEnumerateProperties(props, type, nativeProperties.regular)) {
return false;
}
if (nativeProperties.chromeOnly &&
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
!XrayEnumerateProperties(props, chromeOnlyNativeProperties)) {
!XrayEnumerateProperties(props, type, nativeProperties.chromeOnly)) {
return false;
}
return true;
}
bool
XrayEnumerateProperties(JSContext* cx, JSObject* wrapper, JSObject* obj,
bool ownOnly, JS::AutoIdVector& props)
{
DOMObjectType type;
const NativePropertyHooks* nativePropertyHooks =
GetNativePropertyHooks(cx, obj, type);
if (type == eInstance) {
if (nativePropertyHooks->mEnumerateOwnProperties &&
!nativePropertyHooks->mEnumerateOwnProperties(cx, wrapper, obj,
props)) {
return false;
}
if (ownOnly) {
return true;
}
// Force the type to be eInterfacePrototype, since we need to walk the
// prototype chain.
type = eInterfacePrototype;
}
if (type == eInterfacePrototype) {
do {
if (!XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
obj, props)) {
return false;
}
} while ((nativePropertyHooks = nativePropertyHooks->mProtoHooks));
return true;
}
return XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
obj, props);
}
NativePropertyHooks sWorkerNativePropertyHooks = {
nullptr,
nullptr,
{
nullptr,
nullptr
},
prototypes::id::_ID_Count,
constructors::id::_ID_Count,
nullptr
};
bool
GetPropertyOnPrototype(JSContext* cx, JSObject* proxy, jsid id, bool* found,
JS::Value* vp)
@ -748,21 +1049,33 @@ WrapCallbackInterface(JSContext *cx, JSObject *scope, nsISupports* callback,
JSObject*
GetXrayExpandoChain(JSObject* obj)
{
MOZ_ASSERT(IsDOMObject(obj));
JS::Value v = IsDOMProxy(obj) ? js::GetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO)
: js::GetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT);
js::Class* clasp = js::GetObjectClass(obj);
JS::Value v;
if (IsDOMClass(clasp) || IsDOMIfaceAndProtoClass(clasp)) {
v = js::GetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT);
} else if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
MOZ_ASSERT(js::GetProxyHandler(obj)->family() == ProxyFamily());
v = js::GetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO);
} else {
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
v = js::GetFunctionNativeReserved(obj, CONSTRUCTOR_XRAY_EXPANDO_SLOT);
}
return v.isUndefined() ? nullptr : &v.toObject();
}
void
SetXrayExpandoChain(JSObject* obj, JSObject* chain)
{
MOZ_ASSERT(IsDOMObject(obj));
JS::Value v = chain ? JS::ObjectValue(*chain) : JSVAL_VOID;
if (IsDOMProxy(obj)) {
js::Class* clasp = js::GetObjectClass(obj);
if (IsDOMClass(clasp) || IsDOMIfaceAndProtoClass(clasp)) {
js::SetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT, v);
} else if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
MOZ_ASSERT(js::GetProxyHandler(obj)->family() == ProxyFamily());
js::SetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO, v);
} else {
js::SetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT, v);
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
js::SetFunctionNativeReserved(obj, CONSTRUCTOR_XRAY_EXPANDO_SLOT, v);
}
}
@ -788,5 +1101,82 @@ MainThreadDictionaryBase::ParseJSON(const nsAString& aJSON,
return cx;
}
static JSString*
ConcatJSString(JSContext* cx, const char* pre, JSString* str, const char* post)
{
if (!str) {
return nullptr;
}
JSString* preString = JS_NewStringCopyN(cx, pre, strlen(pre));
JSString* postString = JS_NewStringCopyN(cx, post, strlen(post));
if (!preString || !postString) {
return nullptr;
}
str = JS_ConcatStrings(cx, preString, str);
if (!str) {
return nullptr;
}
return JS_ConcatStrings(cx, str, postString);
}
bool
NativeToString(JSContext* cx, JSObject* wrapper, JSObject* obj, const char* pre,
const char* post, JS::Value* v)
{
JSPropertyDescriptor toStringDesc;
toStringDesc.obj = nullptr;
toStringDesc.attrs = 0;
toStringDesc.shortid = 0;
toStringDesc.getter = nullptr;
toStringDesc.setter = nullptr;
toStringDesc.value = JS::UndefinedValue();
if (!XrayResolveNativeProperty(cx, wrapper, obj,
nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING),
&toStringDesc)) {
return false;
}
JSString* str;
{
JSAutoCompartment ac(cx, obj);
if (toStringDesc.obj) {
JS::Value toString = toStringDesc.value;
if (!JS_WrapValue(cx, &toString)) {
return false;
}
MOZ_ASSERT(JS_ObjectIsCallable(cx, &toString.toObject()));
JS::Value toStringResult;
if (JS_CallFunctionValue(cx, obj, toString, 0, nullptr,
&toStringResult)) {
str = toStringResult.toString();
} else {
str = nullptr;
}
} else {
if (IsDOMProxy(obj)) {
str = js::GetProxyHandler(obj)->obj_toString(cx, obj);
} else if (IsDOMClass(JS_GetClass(obj)) ||
IsDOMIfaceAndProtoClass(JS_GetClass(obj))) {
str = ConcatJSString(cx, "[object ",
JS_NewStringCopyZ(cx, JS_GetClass(obj)->name),
"]");
} else if (JS_IsNativeFunction(obj, Constructor)) {
str = JS_DecompileFunction(cx, JS_GetObjectFunction(obj), 0);
}
str = ConcatJSString(cx, pre, str, post);
}
}
if (!str) {
return false;
}
v->setString(str);
return JS_WrapValue(cx, v);
}
} // namespace dom
} // namespace mozilla

View File

@ -68,6 +68,7 @@ ThrowMethodFailedWithDetails(JSContext* cx, const ErrorResult& rv,
return Throw<mainThread>(cx, rv.ErrorCode());
}
// Returns true if the JSClass is used for DOM objects.
inline bool
IsDOMClass(const JSClass* clasp)
{
@ -80,6 +81,20 @@ IsDOMClass(const js::Class* clasp)
return IsDOMClass(Jsvalify(clasp));
}
// Returns true if the JSClass is used for DOM interface and interface
// prototype objects.
inline bool
IsDOMIfaceAndProtoClass(const JSClass* clasp)
{
return clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS;
}
inline bool
IsDOMIfaceAndProtoClass(const js::Class* clasp)
{
return IsDOMIfaceAndProtoClass(Jsvalify(clasp));
}
// It's ok for eRegularDOMObject and eProxyDOMObject to be the same, but
// eNonDOMObject should always be different from the other two. This enum
// shouldn't be used to differentiate between non-proxy and proxy bindings.
@ -168,9 +183,7 @@ inline bool
IsDOMObject(JSObject* obj)
{
js::Class* clasp = js::GetObjectClass(obj);
return IsDOMClass(clasp) ||
((js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) &&
js::GetProxyHandler(obj)->family() == ProxyFamily());
return IsDOMClass(clasp) || IsDOMProxy(obj, clasp);
}
// Some callers don't want to set an exception when unwrapping fails
@ -275,8 +288,13 @@ UnwrapObject(JSContext* cx, JSObject* obj, U& value)
PrototypeIDMap<T>::PrototypeID), T>(cx, obj, value);
}
const size_t kProtoAndIfaceCacheCount =
prototypes::id::_ID_Count + constructors::id::_ID_Count;
// The items in the protoAndIfaceArray are indexed by the prototypes::id::ID and
// constructors::id::ID enums, in that order. The end of the prototype objects
// should be the start of the interface objects.
MOZ_STATIC_ASSERT((size_t)constructors::id::_ID_Start ==
(size_t)prototypes::id::_ID_Count,
"Overlapping or discontiguous indexes.");
const size_t kProtoAndIfaceCacheCount = constructors::id::_ID_Count;
inline void
AllocateProtoAndIfaceCache(JSObject* obj)
@ -323,27 +341,36 @@ DestroyProtoAndIfaceCache(JSObject* obj)
bool
DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs);
struct JSNativeHolder
{
JSNative mNative;
const NativePropertyHooks* mPropertyHooks;
};
/*
* Create a DOM interface object (if constructorClass is non-null) and/or a
* DOM interface prototype object (if protoClass is non-null).
*
* global is used as the parent of the interface object and the interface
* prototype object
* receiver is the object on which we need to define the interface object as a
* property
* protoProto is the prototype to use for the interface prototype object.
* protoClass is the JSClass to use for the interface prototype object.
* This is null if we should not create an interface prototype
* object.
* protoCache a pointer to a JSObject pointer where we should cache the
* interface prototype object. This must be null if protoClass is and
* vice versa.
* constructorClass is the JSClass to use for the interface object.
* This is null if we should not create an interface object or
* if it should be a function object.
* constructor is the JSNative to use as a constructor. If this is non-null, it
* should be used as a JSNative to back the interface object, which
* should be a Function. If this is null, then we should create an
* object of constructorClass, unless that's also null, in which
* case we should not create an interface object at all.
* constructor holds the JSNative to back the interface object which should be a
* Function, unless constructorClass is non-null in which case it is
* ignored. If this is null and constructorClass is also null then
* we should not create an interface object at all.
* ctorNargs is the length of the constructor function; 0 if no constructor
* constructorCache a pointer to a JSObject pointer where we should cache the
* interface object. This must be null if both constructorClass
* and constructor are null, and non-null otherwise.
* domClass is the DOMClass of instance objects for this class. This can be
* null if this is not a concrete proto.
* properties contains the methods, attributes and constants to be defined on
@ -353,21 +380,19 @@ DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs);
* interface doesn't have any ChromeOnly properties or if the
* object is being created in non-chrome compartment.
*
* At least one of protoClass and constructorClass should be non-null.
* If constructorClass is non-null, the resulting interface object will be
* defined on the given global with property name |name|, which must also be
* non-null.
*
* returns the interface prototype object if protoClass is non-null, else it
* returns the interface object.
* At least one of protoClass, constructorClass or constructor should be
* non-null. If constructorClass or constructor are non-null, the resulting
* interface object will be defined on the given global with property name
* |name|, which must also be non-null.
*/
JSObject*
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
JSObject* protoProto, JSClass* protoClass,
JSClass* constructorClass, JSNative constructor,
unsigned ctorNargs, const DOMClass* domClass,
const NativeProperties* properties,
const NativeProperties* chromeProperties,
void
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
JSClass* protoClass, JSObject** protoCache,
JSClass* constructorClass, JSNativeHolder* constructor,
unsigned ctorNargs, JSObject** constructorCache,
const DOMClass* domClass,
const NativeProperties* regularProperties,
const NativeProperties* chromeOnlyProperties,
const char* name);
/*
@ -1244,18 +1269,94 @@ public:
}
};
// Implementation of the bits that XrayWrapper needs
bool
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
JSPropertyDescriptor* desc,
const NativeProperties* nativeProperties,
const NativeProperties* chromeOnlyNativeProperties);
inline bool
IdEquals(jsid id, const char* string)
{
return JSID_IS_STRING(id) &&
JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), string);
}
inline bool
AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
{
return vector.growBy(1) &&
InternJSString(cx, vector[vector.length() - 1], name);
}
// Implementation of the bits that XrayWrapper needs
/**
* This resolves indexed or named properties of obj.
*
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
*/
bool
XrayEnumerateProperties(JSObject* wrapper,
JS::AutoIdVector& props,
const NativeProperties* nativeProperties,
const NativeProperties* chromeOnlyNativeProperties);
XrayResolveOwnProperty(JSContext* cx, JSObject* wrapper, JSObject* obj,
jsid id, bool set, JSPropertyDescriptor* desc);
/**
* This resolves operations, attributes and constants of the interfaces for obj.
*
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
*/
bool
XrayResolveNativeProperty(JSContext* cx, JSObject* wrapper, JSObject* obj,
jsid id, JSPropertyDescriptor* desc);
/**
* This enumerates indexed or named properties of obj and operations, attributes
* and constants of the interfaces for obj.
*
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
*/
bool
XrayEnumerateProperties(JSContext* cx, JSObject* wrapper, JSObject* obj,
bool ownOnly, JS::AutoIdVector& props);
extern NativePropertyHooks sWorkerNativePropertyHooks;
// We use one constructor JSNative to represent all DOM interface objects (so
// we can easily detect when we need to wrap them in an Xray wrapper). We store
// the real JSNative in the mNative member of a JSNativeHolder in the
// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
// specific interface object. We also store the NativeProperties in the
// JSNativeHolder. The CONSTRUCTOR_XRAY_EXPANDO_SLOT is used to store the
// expando chain of the Xray for the interface object.
// Note that some interface objects are not yet a JSFunction but a normal
// JSObject with a DOMJSClass, those do not use these slots.
enum {
CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0,
CONSTRUCTOR_XRAY_EXPANDO_SLOT
};
JSBool
Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
inline bool
UseDOMXray(JSObject* obj)
{
const js::Class* clasp = js::GetObjectClass(obj);
return IsDOMClass(clasp) ||
IsDOMProxy(obj, clasp) ||
JS_IsNativeFunction(obj, Constructor) ||
IsDOMIfaceAndProtoClass(clasp);
}
#ifdef DEBUG
inline bool
HasConstructor(JSObject* obj)
{
return JS_IsNativeFunction(obj, Constructor) ||
js::GetObjectClass(obj)->construct;
}
#endif
// Transfer reference in ptr to smartPtr.
template<class T>
@ -1292,6 +1393,24 @@ protected:
JS::Value& aVal);
};
/**
* This creates a JSString containing the value that the toString function for
* obj should create according to the WebIDL specification, ignoring any
* modifications by script. The value is prefixed with pre and postfixed with
* post, unless this is called for an object that has a stringifier. It is
* specifically for use by Xray code.
*
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
* pre is a string that should be prefixed to the value.
* post is a string that should be prefixed to the value.
* v contains the JSString for the value if the function returns true.
*/
bool
NativeToString(JSContext* cx, JSObject* wrapper, JSObject* obj, const char* pre,
const char* post, JS::Value* v);
} // namespace dom
} // namespace mozilla

View File

@ -96,6 +96,10 @@ DOMInterfaces = {
'concrete': False,
},
'AudioParam' : {
'nativeOwnership': 'refcounted'
},
'AudioSourceNode': {
'concrete': False,
},

View File

@ -62,13 +62,14 @@ class CGNativePropertyHooks(CGThing):
"""
Generate a NativePropertyHooks for a given descriptor
"""
def __init__(self, descriptor):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
self.descriptor = descriptor
self.properties = properties
def declare(self):
if self.descriptor.workers:
return ""
return "extern const NativePropertyHooks NativeHooks;\n"
return "extern const NativePropertyHooks sNativePropertyHooks;\n"
def define(self):
if self.descriptor.workers:
return ""
@ -76,13 +77,45 @@ class CGNativePropertyHooks(CGThing):
resolveOwnProperty = "ResolveOwnProperty"
enumerateOwnProperties = "EnumerateOwnProperties"
else:
enumerateOwnProperties = resolveOwnProperty = "NULL"
resolveOwnProperty = "nullptr"
enumerateOwnProperties = "nullptr"
if self.properties.hasNonChromeOnly():
regular = "&sNativeProperties"
else:
regular = "nullptr"
if self.properties.hasChromeOnly():
chrome = "&sChromeOnlyNativeProperties"
else:
chrome = "nullptr"
constructorID = "constructors::id::"
if self.descriptor.interface.hasInterfaceObject():
constructorID += self.descriptor.name
else:
constructorID += "_ID_Count"
prototypeID = "prototypes::id::"
if self.descriptor.interface.hasInterfacePrototypeObject():
prototypeID += self.descriptor.name
else:
prototypeID += "_ID_Count"
parent = self.descriptor.interface.parent
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks"
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::sNativePropertyHooks"
if parent else 'NULL')
return """
const NativePropertyHooks NativeHooks = { %s, ResolveProperty, %s, EnumerateProperties, %s };
""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks)
return CGWrapper(CGIndenter(CGList([CGGeneric(resolveOwnProperty),
CGGeneric(enumerateOwnProperties),
CGWrapper(CGList([CGGeneric(regular),
CGGeneric(chrome)],
", "),
pre="{ ", post=" }"),
CGGeneric(prototypeID),
CGGeneric(constructorID),
CGGeneric(parentHooks)],
",\n")),
pre="const NativePropertyHooks sNativePropertyHooks = {\n",
post="\n};\n").define()
def NativePropertyHooks(descriptor):
return "&sWorkerNativePropertyHooks" if descriptor.workers else "&sNativePropertyHooks"
def DOMClass(descriptor):
protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
@ -92,16 +125,17 @@ def DOMClass(descriptor):
# padding.
protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
nativeHooks = "NULL" if descriptor.workers else "&NativeHooks"
if descriptor.workers or descriptor.nativeOwnership != 'refcounted':
participant = "nullptr"
else:
participant = "NS_CYCLE_COLLECTION_PARTICIPANT(%s)" % descriptor.nativeType
return """{
{ %s },
%s, %s, %s
%s,
%s,
%s
}""" % (prototypeChainString, toStringBool(descriptor.nativeOwnership == 'nsisupports'),
nativeHooks,
NativePropertyHooks(descriptor),
participant)
class CGDOMJSClass(CGThing):
@ -144,16 +178,18 @@ DOMJSClass Class = {
CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
class CGPrototypeJSClass(CGThing):
def __init__(self, descriptor):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
self.descriptor = descriptor
self.properties = properties
def declare(self):
# We're purely for internal consumption
return ""
def define(self):
return """static JSClass PrototypeClass = {
return """static DOMIfaceAndProtoJSClass PrototypeClass = {
{
"%sPrototype",
JSCLASS_HAS_RESERVED_SLOTS(1),
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
@ -161,31 +197,41 @@ class CGPrototypeJSClass(CGThing):
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* checkAccess */
NULL, /* call */
NULL, /* hasInstance */
NULL, /* construct */
NULL, /* trace */
nullptr, /* finalize */
nullptr, /* checkAccess */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterfacePrototype,
%s
};
""" % (self.descriptor.interface.identifier.name)
""" % (self.descriptor.interface.identifier.name,
NativePropertyHooks(self.descriptor))
class CGInterfaceObjectJSClass(CGThing):
def __init__(self, descriptor):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
self.descriptor = descriptor
self.properties = properties
def declare(self):
# We're purely for internal consumption
return ""
def define(self):
if not self.descriptor.hasInstanceInterface:
return ""
ctorname = "NULL" if not self.descriptor.interface.ctor() else CONSTRUCT_HOOK_NAME
if self.descriptor.interface.ctor():
ctorname = CONSTRUCT_HOOK_NAME
else:
ctorname = "ThrowingConstructor"
hasinstance = HASINSTANCE_HOOK_NAME
return """
static JSClass InterfaceObjectClass = {
"Function", 0,
static DOMIfaceAndProtoJSClass InterfaceObjectClass = {
{
"Function",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
@ -193,15 +239,18 @@ static JSClass InterfaceObjectClass = {
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* checkAccess */
nullptr, /* finalize */
nullptr, /* checkAccess */
%s, /* call */
%s, /* hasInstance */
%s, /* construct */
NULL, /* trace */
nullptr, /* trace */
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterface,
%s
};
""" % (ctorname, hasinstance, ctorname)
""" % (ctorname, hasinstance, ctorname, NativePropertyHooks(self.descriptor))
class CGList(CGThing):
"""
@ -805,6 +854,18 @@ class CGClassConstructHook(CGAbstractStaticMethod):
self.descriptor, self._ctor)
return preamble + callGenerator.define();
class CGClassConstructHookHolder(CGGeneric):
def __init__(self, descriptor):
if descriptor.interface.ctor():
constructHook = CONSTRUCT_HOOK_NAME
else:
constructHook = "ThrowingConstructor"
CGGeneric.__init__(self,
"JSNativeHolder " + CONSTRUCT_HOOK_NAME + "_holder = {\n" +
" " + constructHook + ",\n" +
" " + NativePropertyHooks(descriptor) + "\n" +
"};\n")
class CGClassHasInstanceHook(CGAbstractStaticMethod):
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
@ -1012,16 +1073,18 @@ class MethodDefiner(PropertyDefiner):
methods = [m for m in descriptor.interface.members if
m.isMethod() and m.isStatic() == static and
not m.isIdentifierLess()]
self.chrome = [{"name": m.identifier.name,
self.chrome = []
self.regular = []
for m in methods:
method = { "name": m.identifier.name,
"methodInfo": not m.isStatic(),
"length": methodLength(m),
"flags": "JSPROP_ENUMERATE",
"pref": PropertyDefiner.getControllingPref(m) }
for m in methods if isChromeOnly(m)]
self.regular = [{"name": m.identifier.name,
"length": methodLength(m),
"flags": "JSPROP_ENUMERATE",
"pref": PropertyDefiner.getControllingPref(m) }
for m in methods if not isChromeOnly(m)]
if isChromeOnly(m):
self.chrome.append(method)
else:
self.regular.append(method)
# FIXME Check for an existing iterator on the interface first.
if any(m.isGetter() and m.isIndexed() for m in methods):
@ -1085,15 +1148,27 @@ class MethodDefiner(PropertyDefiner):
pref, specData, doIdArrays)
class AttrDefiner(PropertyDefiner):
def __init__(self, descriptor, name, unforgeable):
def __init__(self, descriptor, name, static, unforgeable=False):
assert not (static and unforgeable)
PropertyDefiner.__init__(self, descriptor, name)
self.name = name
attributes = [m for m in descriptor.interface.members
if m.isAttr() and m.isUnforgeable() == unforgeable]
attributes = [m for m in descriptor.interface.members if
m.isAttr() and m.isStatic() == static and
m.isUnforgeable() == unforgeable]
self.chrome = [m for m in attributes if isChromeOnly(m)]
self.regular = [m for m in attributes if not isChromeOnly(m)]
self.static = static
self.unforgeable = unforgeable
if static:
if not descriptor.interface.hasInterfaceObject():
# static attributes go on the interface object
assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
else:
if not descriptor.interface.hasInterfacePrototypeObject():
# non-static attributes go on the interface prototype object
assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
if unforgeable and len(attributes) != 0 and descriptor.proxy:
raise TypeError("Unforgeable properties are not supported on "
"proxy bindings without [NamedPropertiesObject]. "
@ -1111,20 +1186,26 @@ class AttrDefiner(PropertyDefiner):
unforgeable)
def getter(attr):
native = ("genericLenientGetter" if attr.hasLenientThis()
if self.static:
accessor = 'get_' + attr.identifier.name
jitinfo = "nullptr"
else:
accessor = ("genericLenientGetter" if attr.hasLenientThis()
else "genericGetter")
return ("{(JSPropertyOp)%(native)s, &%(name)s_getterinfo}"
% {"name" : attr.identifier.name,
"native" : native})
jitinfo = "&%s_getterinfo" % attr.identifier.name
return "{ (JSPropertyOp)%s, %s }" % (accessor, jitinfo)
def setter(attr):
if self.static:
accessor = 'set_' + attr.identifier.name
jitinfo = "nullptr"
else:
if attr.readonly and attr.getExtendedAttribute("PutForwards") is None:
return "JSOP_NULLWRAPPER"
native = ("genericLenientSetter" if attr.hasLenientThis()
accessor = ("genericLenientSetter" if attr.hasLenientThis()
else "genericSetter")
return ("{(JSStrictPropertyOp)%(native)s, &%(name)s_setterinfo}"
% {"name" : attr.identifier.name,
"native" : native})
jitinfo = "&%s_setterinfo" % attr.identifier.name
return "{ (JSStrictPropertyOp)%s, %s }" % (accessor, jitinfo)
def specData(attr):
return (attr.identifier.name, flags(attr), getter(attr),
@ -1165,17 +1246,20 @@ class ConstDefiner(PropertyDefiner):
class PropertyArrays():
def __init__(self, descriptor):
self.staticMethods = MethodDefiner(descriptor, "StaticMethods", True)
self.methods = MethodDefiner(descriptor, "Methods", False)
self.attrs = AttrDefiner(descriptor, "Attributes", unforgeable=False)
self.staticMethods = MethodDefiner(descriptor, "StaticMethods",
static=True)
self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes",
static=True)
self.methods = MethodDefiner(descriptor, "Methods", static=False)
self.attrs = AttrDefiner(descriptor, "Attributes", static=False)
self.unforgeableAttrs = AttrDefiner(descriptor, "UnforgeableAttributes",
unforgeable=True)
static=False, unforgeable=True)
self.consts = ConstDefiner(descriptor, "Constants")
@staticmethod
def arrayNames():
return [ "staticMethods", "methods", "attrs", "unforgeableAttrs",
"consts" ]
return [ "staticMethods", "staticAttrs", "methods", "attrs",
"unforgeableAttrs", "consts" ]
@staticmethod
def xrayRelevantArrayNames():
@ -1233,8 +1317,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
"""
def __init__(self, descriptor, properties):
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
Argument('JSObject*', 'aReceiver')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'JSObject*', args)
Argument('JSObject**', 'protoAndIfaceArray')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties
def definition_body(self):
protoChain = self.descriptor.prototypeChain
@ -1242,7 +1326,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
getParentProto = "JS_GetObjectPrototype(aCx, aGlobal)"
else:
parentProtoName = self.descriptor.prototypeChain[-2]
getParentProto = ("%s::GetProtoObject(aCx, aGlobal, aReceiver)" %
getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
toBindingNamespace(parentProtoName))
needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
@ -1275,7 +1359,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
initIds = CGList(
[initIds,
CGGeneric((" %s_ids[0] = JSID_VOID;\n"
" return NULL;") % idsToInit[0]),
" return;") % idsToInit[0]),
CGGeneric("}")],
"\n")
else:
@ -1299,20 +1383,33 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
getParentProto = ("JSObject* parentProto = %s;\n" +
"if (!parentProto) {\n" +
" return NULL;\n" +
" return;\n" +
"}\n") % getParentProto
needInterfaceObjectClass = (needInterfaceObject and
self.descriptor.hasInstanceInterface)
needConstructor = (needInterfaceObject and
not self.descriptor.hasInstanceInterface)
constructHook = "&" + CONSTRUCT_HOOK_NAME + "_holder"
if self.descriptor.interface.ctor():
constructHook = CONSTRUCT_HOOK_NAME
constructArgs = methodLength(self.descriptor.interface.ctor())
else:
constructHook = "ThrowingConstructor"
constructArgs = 0
if needInterfacePrototypeObject:
protoClass = "&PrototypeClass.mBase"
protoCache = "&protoAndIfaceArray[prototypes::id::%s]" % self.descriptor.name
else:
protoClass = "nullptr"
protoCache = "nullptr"
if needInterfaceObject:
if self.descriptor.hasInstanceInterface:
interfaceClass = "&InterfaceObjectClass.mBase"
else:
interfaceClass = "nullptr"
interfaceCache = "&protoAndIfaceArray[constructors::id::%s]" % self.descriptor.name
else:
interfaceClass = "nullptr"
interfaceCache = "nullptr"
if self.descriptor.concrete:
if self.descriptor.proxy:
domClass = "&Class"
@ -1330,20 +1427,20 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr"
else:
chromeProperties = "nullptr"
call = """return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,
%s, %s, %s, %d,
%s,
%s,
%s,
%s);""" % (
"&PrototypeClass" if needInterfacePrototypeObject else "NULL",
"&InterfaceObjectClass" if needInterfaceObjectClass else "NULL",
constructHook if needConstructor else "NULL",
constructArgs,
call = ("dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,\n"
" %s, %s,\n"
" %s, %s, %d, %s,\n"
" %s,\n"
" %s,\n"
" %s,\n"
" %s);" % (
protoClass, protoCache,
interfaceClass, constructHook if needConstructor else "nullptr",
constructArgs, interfaceCache,
domClass,
properties,
chromeProperties,
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL")
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
functionBody = CGList(
[CGGeneric(getParentProto), initIds, prefCache, CGGeneric(call)],
"\n\n")
@ -1355,20 +1452,13 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
constructor object).
"""
def __init__(self, descriptor, name, idPrefix=""):
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
Argument('JSObject*', 'aReceiver')]
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
CGAbstractMethod.__init__(self, descriptor, name,
'JSObject*', args, inline=True)
self.id = idPrefix + "id::" + self.descriptor.name
def definition_body(self):
return """
/* aGlobal and aReceiver are usually the same, but they can be different
too. For example a sandbox often has an xray wrapper for a window as the
prototype of the sandbox's global. In that case aReceiver is the xray
wrapper and aGlobal is the sandbox's global.
*/
/* Make sure our global is sane. Hopefully we can remove this sometime */
if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
return NULL;
@ -1377,7 +1467,8 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
JSObject* cachedObject = protoAndIfaceArray[%s];
if (!cachedObject) {
protoAndIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray);
cachedObject = protoAndIfaceArray[%s];
}
/* cachedObject might _still_ be null, but that's OK */
@ -1441,9 +1532,9 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
a given interface.
"""
def __init__(self, descriptor):
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aReceiver'),
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
Argument('bool*', 'aEnabled')]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args)
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'JSObject*', args)
def declare(self):
if self.descriptor.workers:
@ -1456,18 +1547,10 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return CGAbstractMethod.define(self)
def definition_body(self):
if self.descriptor.interface.hasInterfacePrototypeObject():
# We depend on GetProtoObject defining an interface constructor
# object as needed.
getter = "GetProtoObject"
else:
getter = "GetConstructorObject"
return (" JSObject* global = JS_GetGlobalForObject(aCx, aReceiver);\n" +
CheckPref(self.descriptor, "global", "*aEnabled", "false") +
return (CheckPref(self.descriptor, "aGlobal", "*aEnabled", "nullptr") +
"""
*aEnabled = true;
return !!%s(aCx, global, aReceiver);""" % (getter))
return GetConstructorObject(aCx, aGlobal);""")
class CGPrefEnabled(CGAbstractMethod):
"""
@ -1594,7 +1677,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
JSAutoCompartment ac(aCx, parent);
JSObject* global = JS_GetGlobalForObject(aCx, parent);
%s
JSObject* proto = GetProtoObject(aCx, global, global);
JSObject* proto = GetProtoObject(aCx, global);
if (!proto) {
return NULL;
}
@ -1636,7 +1719,7 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
def definition_body(self):
return """
JSObject* global = JS_GetGlobalForObject(aCx, aScope);
JSObject* proto = GetProtoObject(aCx, global, global);
JSObject* proto = GetProtoObject(aCx, global);
if (!proto) {
return NULL;
}
@ -3620,9 +3703,13 @@ class CGGetterCall(CGPerSignatureCall):
getter.
"""
def __init__(self, returnType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, returnType, [], [],
nativeMethodName, False, descriptor,
attr, getter=True)
if attr.isStatic():
argsPre = [ "global" ]
else:
argsPre = []
CGPerSignatureCall.__init__(self, returnType, argsPre, [],
nativeMethodName, attr.isStatic(),
descriptor, attr, getter=True)
class FakeArgument():
"""
@ -3649,10 +3736,14 @@ class CGSetterCall(CGPerSignatureCall):
setter.
"""
def __init__(self, argType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, None, [],
if attr.isStatic():
argsPre = [ "global" ]
else:
argsPre = []
CGPerSignatureCall.__init__(self, None, argsPre,
[FakeArgument(argType, attr)],
nativeMethodName, False, descriptor, attr,
setter=True)
nativeMethodName, attr.isStatic(),
descriptor, attr, setter=True)
def wrap_return_value(self):
# We have no return value
return "\nreturn true;"
@ -3691,21 +3782,60 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
# we're someone's consequential interface. But for this-unwrapping, we
# know that we're the real deal. So fake a descriptor here for
# consumption by FailureFatalCastableObjectUnwrapper.
unwrapThis = CGIndenter(CGGeneric(
getThis = CGGeneric("""js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
if (!obj) {
return false;
}
%s* self;""" % self.descriptor.nativeType)
unwrapThis = CGGeneric(
str(CastableObjectUnwrapper(
FakeCastableDescriptor(self.descriptor),
"obj", "self", self.unwrapFailureCode))))
return CGList([ self.getThis(), unwrapThis,
"obj", "self", self.unwrapFailureCode)))
return CGList([ CGIndenter(getThis), CGIndenter(unwrapThis),
self.generate_code() ], "\n").define()
def getThis(self):
return CGIndenter(
CGGeneric("js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
"if (!obj) {\n"
" return false;\n"
"}\n"
"\n"
"%s* self;" % self.descriptor.nativeType))
def generate_code(self):
assert(False) # Override me
class CGAbstractStaticBindingMethod(CGAbstractStaticMethod):
"""
Common class to generate the JSNatives for all our static methods, getters
and setters. This will generate the function declaration and unwrap the
global object. Subclasses are expected to override the generate_code
function to do the rest of the work. This function should return a
CGThing which is already properly indented.
"""
def __init__(self, descriptor, name, args):
CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
def definition_body(self):
isMainThread = toStringBool(not self.descriptor.workers)
unwrap = CGGeneric("""js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
if (!obj) {
return false;
}
if (js::IsWrapper(obj)) {
obj = XPCWrapper::Unwrap(cx, obj, false);
if (!obj) {
return Throw<%s>(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
}
}
nsISupports* global;
xpc_qsSelfRef globalRef;
{
JS::Value val;
val.setObjectOrNull(JS_GetGlobalForObject(cx, obj));
nsresult rv = xpc_qsUnwrapArg<nsISupports>(cx, val, &global, &globalRef.ptr,
&val);
if (NS_FAILED(rv)) {
return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
}
}""" % (isMainThread, isMainThread))
return CGList([ CGIndenter(unwrap),
self.generate_code() ], "\n\n").define()
def generate_code(self):
assert(False) # Override me
@ -3752,6 +3882,23 @@ class CGSpecializedMethod(CGAbstractStaticMethod):
name = method.identifier.name
return MakeNativeName(descriptor.binaryNames.get(name, name))
class CGStaticMethod(CGAbstractStaticBindingMethod):
"""
A class for generating the C++ code for an IDL static method.
"""
def __init__(self, descriptor, method):
self.method = method
name = method.identifier.name
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
def generate_code(self):
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
self.method)
return CGMethodCall([ "global" ], nativeName, True, self.descriptor,
self.method)
class CGGenericGetter(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL attribute getter.
@ -3810,6 +3957,23 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
nativeName = "Get" + nativeName
return nativeName
class CGStaticGetter(CGAbstractStaticBindingMethod):
"""
A class for generating the C++ code for an IDL static attribute getter.
"""
def __init__(self, descriptor, attr):
self.attr = attr
name = 'get_' + attr.identifier.name
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
def generate_code(self):
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
self.attr)
return CGIndenter(CGGetterCall(self.attr.type, nativeName,
self.descriptor, self.attr))
class CGGenericSetter(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL attribute setter.
@ -3868,6 +4032,29 @@ class CGSpecializedSetter(CGAbstractStaticMethod):
name = attr.identifier.name
return "Set" + MakeNativeName(descriptor.binaryNames.get(name, name))
class CGStaticSetter(CGAbstractStaticBindingMethod):
"""
A class for generating the C++ code for an IDL static attribute setter.
"""
def __init__(self, descriptor, attr):
self.attr = attr
name = 'set_' + attr.identifier.name
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
def generate_code(self):
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
self.attr)
argv = CGGeneric("""JS::Value* argv = JS_ARGV(cx, vp);
JS::Value undef = JS::UndefinedValue();
if (argc == 0) {
argv = &undef;
}""")
call = CGSetterCall(self.attr.type, nativeName, self.descriptor,
self.attr)
return CGIndenter(CGList([ argv, call ], "\n"))
class CGSpecializedForwardingSetter(CGSpecializedSetter):
"""
A class for generating the code for a specialized attribute setter with
@ -4676,15 +4863,12 @@ class CGClass(CGThing):
class CGResolveOwnProperty(CGAbstractMethod):
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
Argument('jsid', 'id'), Argument('bool', 'set'),
Argument('JSObject*', 'obj'), Argument('jsid', 'id'),
Argument('bool', 'set'),
Argument('JSPropertyDescriptor*', 'desc')]
CGAbstractMethod.__init__(self, descriptor, "ResolveOwnProperty", "bool", args)
def definition_body(self):
return """ JSObject* obj = wrapper;
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
obj = js::UnwrapObject(obj);
}
// We rely on getOwnPropertyDescriptor not shadowing prototype properties by named
return """ // We rely on getOwnPropertyDescriptor not shadowing prototype properties by named
// properties. If that changes we'll need to filter here.
return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, set, desc);
"""
@ -4692,64 +4876,15 @@ class CGResolveOwnProperty(CGAbstractMethod):
class CGEnumerateOwnProperties(CGAbstractMethod):
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
Argument('JSObject*', 'obj'),
Argument('JS::AutoIdVector&', 'props')]
CGAbstractMethod.__init__(self, descriptor, "EnumerateOwnProperties", "bool", args)
def definition_body(self):
return """ JSObject* obj = wrapper;
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
obj = js::UnwrapObject(obj);
}
// We rely on getOwnPropertyNames not shadowing prototype properties by named
return """ // We rely on getOwnPropertyNames not shadowing prototype properties by named
// properties. If that changes we'll need to filter here.
return js::GetProxyHandler(obj)->getOwnPropertyNames(cx, wrapper, props);
"""
class CGXrayHelper(CGAbstractMethod):
def __init__(self, descriptor, name, args, properties):
CGAbstractMethod.__init__(self, descriptor, name, "bool", args)
self.properties = properties
def definition_body(self):
prefixArgs = CGGeneric(self.getPrefixArgs())
if self.properties.hasNonChromeOnly():
regular = "&sNativeProperties"
else:
regular = "nullptr"
regular = CGGeneric(regular)
if self.properties.hasChromeOnly():
chrome = "&sChromeOnlyNativeProperties"
else:
chrome = "nullptr"
chrome = CGGeneric(chrome)
return CGIndenter(
CGWrapper(CGList([prefixArgs, regular, chrome], ",\n"),
pre=("return Xray%s(" % self.name),
post=");",
reindent=True)).define()
class CGResolveProperty(CGXrayHelper):
def __init__(self, descriptor, properties):
args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
Argument('jsid', 'id'), Argument('bool', 'set'),
Argument('JSPropertyDescriptor*', 'desc')]
CGXrayHelper.__init__(self, descriptor, "ResolveProperty", args,
properties)
def getPrefixArgs(self):
return "cx, wrapper, id, desc"
class CGEnumerateProperties(CGXrayHelper):
def __init__(self, descriptor, properties):
args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
Argument('JS::AutoIdVector&', 'props')]
CGXrayHelper.__init__(self, descriptor, "EnumerateProperties", args,
properties)
def getPrefixArgs(self):
return "wrapper, props"
class CGPrototypeTraitsClass(CGClass):
def __init__(self, descriptor, indent=''):
templateArgs = [Argument('prototypes::ID', 'PrototypeID')]
@ -5325,21 +5460,32 @@ class CGDescriptor(CGThing):
cgThings = []
if descriptor.interface.hasInterfacePrototypeObject():
# These are set to true if at least one non-static
# method/getter/setter exist on the interface.
(hasMethod, hasGetter, hasLenientGetter,
hasSetter, hasLenientSetter) = False, False, False, False, False
for m in descriptor.interface.members:
if (m.isMethod() and not m.isStatic() and
if (m.isMethod() and
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
if m.isStatic():
cgThings.append(CGStaticMethod(descriptor, m))
else:
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
elif m.isAttr():
if m.isStatic():
cgThings.append(CGStaticGetter(descriptor, m))
else:
cgThings.append(CGSpecializedGetter(descriptor, m))
if m.hasLenientThis():
hasLenientGetter = True
else:
hasGetter = True
if not m.readonly:
if m.isStatic():
cgThings.append(CGStaticSetter(descriptor, m))
else:
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis():
hasLenientSetter = True
@ -5348,6 +5494,7 @@ class CGDescriptor(CGThing):
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
hasSetter = True
if not m.isStatic():
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
@ -5375,32 +5522,32 @@ class CGDescriptor(CGThing):
if (descriptor.customTrace):
cgThings.append(CGClassTraceHook(descriptor))
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGClassConstructHook(descriptor))
cgThings.append(CGClassHasInstanceHook(descriptor))
cgThings.append(CGInterfaceObjectJSClass(descriptor))
if descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGPrototypeJSClass(descriptor))
properties = PropertyArrays(descriptor)
cgThings.append(CGGeneric(define=str(properties)))
cgThings.append(CGNativeProperties(descriptor, properties))
cgThings.append(CGNativePropertyHooks(descriptor, properties))
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGClassConstructHook(descriptor))
cgThings.append(CGClassHasInstanceHook(descriptor))
cgThings.append(CGInterfaceObjectJSClass(descriptor, properties))
cgThings.append(CGClassConstructHookHolder(descriptor))
if descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGPrototypeJSClass(descriptor, properties))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
if descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGGetProtoObjectMethod(descriptor))
else:
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGGetConstructorObjectMethod(descriptor))
# Set up our Xray callbacks as needed. Note that we don't need to do
# it in workers.
if (descriptor.interface.hasInterfacePrototypeObject() and
not descriptor.workers):
if descriptor.concrete and descriptor.proxy:
if not descriptor.workers and descriptor.concrete and descriptor.proxy:
cgThings.append(CGResolveOwnProperty(descriptor))
cgThings.append(CGEnumerateOwnProperties(descriptor))
cgThings.append(CGResolveProperty(descriptor, properties))
cgThings.append(CGEnumerateProperties(descriptor, properties))
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
@ -5410,9 +5557,6 @@ class CGDescriptor(CGThing):
descriptor.interface.getExtendedAttribute("PrefControlled") is not None):
cgThings.append(CGPrefEnabled(descriptor))
if descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGNativePropertyHooks(descriptor))
if descriptor.concrete:
if descriptor.proxy:
cgThings.append(CGProxyIsProxy(descriptor))
@ -6022,7 +6166,7 @@ class CGExampleMember(CGThing):
static = "static " if self.member.isStatic() else ""
# Mark our getters, which are attrs that have a non-void return type,
# as const.
if self.member.isAttr() and not self.signatures[0][0].isVoid():
if not self.member.isStatic() and self.member.isAttr() and not self.signatures[0][0].isVoid():
const = " const"
else:
const = ""
@ -6422,7 +6566,8 @@ class GlobalGenRoots():
# Prototype ID enum.
protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)]
idEnum = CGNamespacedEnum('id', 'ID', protos, [0])
idEnum = CGNamespacedEnum('id', 'ID', ['_ID_Start'] + protos,
[0, '_ID_Start'])
idEnum = CGList([idEnum])
idEnum.append(CGGeneric(declare="const unsigned MaxProtoChainLength = " +
str(config.maxProtoChainLength) + ";\n\n"))
@ -6435,9 +6580,9 @@ class GlobalGenRoots():
curr = CGList([idEnum])
# Constructor ID enum.
constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True,
hasInterfacePrototypeObject=False)]
idEnum = CGNamespacedEnum('id', 'ID', constructors, [0])
constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True)]
idEnum = CGNamespacedEnum('id', 'ID', ['_ID_Start'] + constructors,
['prototypes::id::_ID_Count', '_ID_Start'])
# Wrap all of that in our namespaces.
idEnum = CGNamespace.build(['mozilla', 'dom', 'constructors'],
@ -6551,7 +6696,7 @@ struct PrototypeIDMap;
curr = CGWrapper(curr, post='\n')
curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr)
curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h", "XPCWrapper.h"], [], curr)
# Add include guards.
curr = CGIncludeGuard('UnionConversions', curr)

View File

@ -8,6 +8,7 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/PrototypeList.h" // auto-generated
@ -27,20 +28,26 @@ class nsCycleCollectionParticipant;
// We use these flag bits for the new bindings.
#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
#define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
MOZ_STATIC_ASSERT(DOM_PROTO_INSTANCE_CLASS_SLOT != DOM_XRAY_EXPANDO_SLOT,
"Interface prototype object use both of these, so they must "
"not be the same slot.");
namespace mozilla {
namespace dom {
typedef bool
(* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set,
JSPropertyDescriptor* desc);
(* ResolveOwnProperty)(JSContext* cx, JSObject* wrapper, JSObject* obj, jsid id,
bool set, JSPropertyDescriptor* desc);
typedef bool
(* EnumerateProperties)(JSContext* cx, JSObject* wrapper,
(* EnumerateOwnProperties)(JSContext* cx, JSObject* wrapper, JSObject* obj,
JS::AutoIdVector& props);
struct ConstantSpec
@ -64,6 +71,9 @@ struct NativeProperties
Prefable<JSFunctionSpec>* staticMethods;
jsid* staticMethodIds;
JSFunctionSpec* staticMethodsSpecs;
Prefable<JSPropertySpec>* staticAttributes;
jsid* staticAttributeIds;
JSPropertySpec* staticAttributeSpecs;
Prefable<JSFunctionSpec>* methods;
jsid* methodIds;
JSFunctionSpec* methodsSpecs;
@ -78,16 +88,47 @@ struct NativeProperties
ConstantSpec* constantSpecs;
};
struct NativePropertiesHolder
{
const NativeProperties* regular;
const NativeProperties* chromeOnly;
};
// Helper structure for Xrays for DOM binding objects. The same instance is used
// for instances, interface objects and interface prototype objects of a
// specific interface.
struct NativePropertyHooks
{
ResolveProperty mResolveOwnProperty;
ResolveProperty mResolveProperty;
EnumerateProperties mEnumerateOwnProperties;
EnumerateProperties mEnumerateProperties;
// The hook to call for resolving indexed or named properties. May be null if
// there can't be any.
ResolveOwnProperty mResolveOwnProperty;
// The hook to call for enumerating indexed or named properties. May be null
// if there can't be any.
EnumerateOwnProperties mEnumerateOwnProperties;
// The property arrays for this interface.
NativePropertiesHolder mNativeProperties;
// This will be set to the ID of the interface prototype object for the
// interface, if it has one. If it doesn't have one it will be set to
// prototypes::id::_ID_Count.
prototypes::ID mPrototypeID;
// This will be set to the ID of the interface object for the interface, if it
// has one. If it doesn't have one it will be set to
// constructors::id::_ID_Count.
constructors::ID mConstructorID;
// The NativePropertyHooks instance for the parent interface.
const NativePropertyHooks* mProtoHooks;
};
enum DOMObjectType {
eInstance,
eInterface,
eInterfacePrototype
};
struct DOMClass
{
// A list of interfaces that this object implements, in order of decreasing
@ -137,6 +178,31 @@ struct DOMJSClass
JSClass* ToJSClass() { return &mBase; }
};
// Special JSClass for DOM interface and interface prototype objects.
struct DOMIfaceAndProtoJSClass
{
// It would be nice to just inherit from JSClass, but that precludes pure
// compile-time initialization of the form
// |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace
// initialization for aggregate/POD types.
JSClass mBase;
// Either eInterface or eInterfacePrototype
DOMObjectType mType;
const NativePropertyHooks* mNativeHooks;
static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) {
MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS);
return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base);
}
static const DOMIfaceAndProtoJSClass* FromJSClass(const js::Class* base) {
return FromJSClass(Jsvalify(base));
}
JSClass* ToJSClass() { return &mBase; }
};
inline bool
HasProtoAndIfaceArray(JSObject* global)
{

View File

@ -36,18 +36,25 @@ def parseInt(literal):
return value * sign
# Magic for creating enums
def M_add_class_attribs(attribs):
def M_add_class_attribs(attribs, start):
def foo(name, bases, dict_):
for v, k in enumerate(attribs):
dict_[k] = v
dict_[k] = start + v
assert 'length' not in dict_
dict_['length'] = len(attribs)
dict_['length'] = start + len(attribs)
return type(name, bases, dict_)
return foo
def enum(*names):
class Foo(object):
__metaclass__ = M_add_class_attribs(names)
def enum(*names, **kw):
if len(kw) == 1:
base = kw['base'].__class__
start = base.length
else:
assert len(kw) == 0
base = object
start = 0
class Foo(base):
__metaclass__ = M_add_class_attribs(names, start)
def __setattr__(self, name, value): # this makes it read-only
raise NotImplementedError
return Foo()
@ -1928,6 +1935,11 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
'Method'
)
Special = enum(
'Static',
'Stringifier'
)
def __init__(self, location, identifier, tag):
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
self.tag = tag
@ -1991,8 +2003,8 @@ class IDLConst(IDLInterfaceMember):
pass
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit,
static=False):
def __init__(self, location, identifier, type, readonly, inherit=False,
static=False, stringifier=False):
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Attr)
@ -2003,6 +2015,7 @@ class IDLAttribute(IDLInterfaceMember):
self.static = static
self.lenientThis = False
self._unforgeable = False
self.stringifier = stringifier
if readonly and inherit:
raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
@ -2265,14 +2278,12 @@ class IDLMethodOverload:
class IDLMethod(IDLInterfaceMember, IDLScope):
Special = enum(
'None',
'Getter',
'Setter',
'Creator',
'Deleter',
'LegacyCaller',
'Stringifier',
'Static'
base=IDLInterfaceMember.Special
)
TypeSuffixModifier = enum(
@ -3096,16 +3107,32 @@ class Parser(Tokenizer):
"""
p[0] = p[1]
def p_AttributeWithQualifier(self, p):
"""
Attribute : Qualifier AttributeRest
"""
static = IDLInterfaceMember.Special.Static in p[1]
stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
(location, identifier, type, readonly) = p[2]
p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
stringifier=stringifier)
def p_Attribute(self, p):
"""
Attribute : Inherit ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
Attribute : Inherit AttributeRest
"""
location = self.getLocation(p, 3)
inherit = p[1]
readonly = p[2]
t = p[4]
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
p[0] = IDLAttribute(location, identifier, t, readonly, inherit)
(location, identifier, type, readonly) = p[2]
p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
def p_AttributeRest(self, p):
"""
AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
"""
location = self.getLocation(p, 2)
readonly = p[1]
t = p[3]
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4])
p[0] = (location, identifier, t, readonly)
def p_ReadOnly(self, p):
"""
@ -3142,17 +3169,21 @@ class Parser(Tokenizer):
raise WebIDLError("Duplicate qualifiers are not allowed",
[self.getLocation(p, 1)])
static = True if IDLMethod.Special.Static in p[1] else False
static = IDLInterfaceMember.Special.Static in p[1]
# If static is there that's all that's allowed. This is disallowed
# by the parser, so we can assert here.
assert not static or len(qualifiers) == 1
stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
# If stringifier is there that's all that's allowed. This is disallowed
# by the parser, so we can assert here.
assert not stringifier or len(qualifiers) == 1
getter = True if IDLMethod.Special.Getter in p[1] else False
setter = True if IDLMethod.Special.Setter in p[1] else False
creator = True if IDLMethod.Special.Creator in p[1] else False
deleter = True if IDLMethod.Special.Deleter in p[1] else False
legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
stringifier = True if IDLMethod.Special.Stringifier in p[1] else False
if getter or deleter:
if setter or creator:
@ -3260,15 +3291,22 @@ class Parser(Tokenizer):
legacycaller=legacycaller, stringifier=stringifier)
p[0] = method
def p_QualifiersStatic(self, p):
def p_QualifierStatic(self, p):
"""
Qualifiers : STATIC
Qualifier : STATIC
"""
p[0] = [IDLMethod.Special.Static]
p[0] = [IDLInterfaceMember.Special.Static]
def p_QualifiersSpecials(self, p):
def p_QualifierStringifier(self, p):
"""
Qualifiers : Specials
Qualifier : STRINGIFIER
"""
p[0] = [IDLInterfaceMember.Special.Stringifier]
def p_Qualifiers(self, p):
"""
Qualifiers : Qualifier
| Specials
"""
p[0] = p[1]
@ -3315,12 +3353,6 @@ class Parser(Tokenizer):
"""
p[0] = IDLMethod.Special.LegacyCaller
def p_SpecialStringifier(self, p):
"""
Special : STRINGIFIER
"""
p[0] = IDLMethod.Special.Stringifier
def p_OperationRest(self, p):
"""
OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON

View File

@ -428,6 +428,11 @@ public:
already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
void ExerciseTypedefInterfaces3(TestInterface&);
// Static methods and attributes
static void StaticMethod(nsISupports*, bool);
static bool StaticAttribute(nsISupports*);
static void SetStaticAttribute(nsISupports*, bool);
// Miscellania
int32_t AttrWithLenientThis();
void SetAttrWithLenientThis(int32_t);

View File

@ -334,6 +334,10 @@ interface TestInterface {
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
// Static methods and attributes
static attribute boolean staticAttribute;
static void staticMethod(boolean arg);
// Miscellania
[LenientThis] attribute long attrWithLenientThis;
[Unforgeable] readonly attribute long unforgeableAttr;

View File

@ -301,6 +301,10 @@ interface TestExampleInterface {
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
// Static methods and attributes
static attribute boolean staticAttribute;
static void staticMethod(boolean arg);
// Miscellania
[LenientThis] attribute long attrWithLenientThis;
[Unforgeable] readonly attribute long unforgeableAttr;

View File

@ -373,7 +373,8 @@ BrowserElementParent.prototype = {
},
_recvGetFullscreenAllowed: function(data) {
return this._frameElement.hasAttribute('mozallowfullscreen');
return this._frameElement.hasAttribute('allowfullscreen') ||
this._frameElement.hasAttribute('mozallowfullscreen');
},
_fireCtxMenuEvent: function(data) {

View File

@ -28,6 +28,7 @@
#include "jsapi.h"
#include "nsThread.h"
#include <media/MediaProfiles.h>
#include "mozilla/FileUtils.h"
#include "nsDirectoryServiceDefs.h" // for NS_GetSpecialDirectory
#include "nsPrintfCString.h"
#include "DOMCameraManager.h"
@ -734,20 +735,17 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
filename->GetNativePath(nativeFilename);
DOM_CAMERA_LOGI("Video filename is '%s'\n", nativeFilename.get());
int fd = open(nativeFilename.get(), O_RDWR | O_CREAT, 0644);
ScopedClose fd(open(nativeFilename.get(), O_RDWR | O_CREAT, 0644));
if (fd < 0) {
DOM_CAMERA_LOGE("Couldn't create file '%s': (%d) %s\n", nativeFilename.get(), errno, strerror(errno));
return NS_ERROR_FAILURE;
}
if (SetupRecording(fd) != NS_OK) {
DOM_CAMERA_LOGE("SetupRecording() failed\n");
close(fd);
return NS_ERROR_FAILURE;
}
nsresult rv = SetupRecording(fd);
NS_ENSURE_SUCCESS(rv, rv);
if (mRecorder->start() != OK) {
DOM_CAMERA_LOGE("mRecorder->start() failed\n");
close(fd);
return NS_ERROR_FAILURE;
}

View File

@ -8,6 +8,12 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<script type="text/javascript;version=1.7">
function createZipFileWithData(fileData) {
@ -48,6 +54,17 @@
return fileList.files[0];
}
handleFinished = 0;
function markTestDone() {
++handleFinished;
if (isFinished()) {
SimpleTest.finish();
}
}
function isFinished() {
return handleFinished == 5;
}
function testSteps()
{
var binaryString = '504B03040A00000000002E6BF14000000000000000000000000005001C00746573742F555409000337CA055039CA055075780B' +
@ -111,10 +128,12 @@
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
handle.onsuccess = function() {
ok(false, "ArchiveReader.getFilenames() should return a 'failure' if the input file is not a zip");
markTestDone();
}
handle.onerror = function() {
ok(true, "ArchiveReader.getFilenames() should return a 'error' if the input file is a zip file");
is(this.reader, rt, "ArchiveRequest.reader == ArchiveReader");
markTestDone();
}
// Create - good!
@ -131,9 +150,11 @@
is(this.result[0], "test/a.txt", "ArchiveReader.getFilenames(): first file is 'test/a.txt'");
is(this.result[1], "test/b.txt", "ArchiveReader.getFilenames(): second file is 'test/b.txt'");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
markTestDone();
}
handle.onerror = function() {
ok(false, "ArchiveReader.getFilenames() should not return any 'error'");
markTestDone();
}
// GetFile - wrong (no args)
@ -150,10 +171,12 @@
isnot(handle2, null, "ArchiveReader.getFile() cannot be null");
handle2.onsuccess = function() {
ok(false, "ArchiveReader.getFile('unknown file') should not return a 'success'");
markTestDone();
}
handle2.onerror = function() {
ok(true, "ArchiveReader.getFile('unknown file') should return an 'error'");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
markTestDone();
}
var handle3 = r.getFile("test/b.txt");
@ -168,14 +191,17 @@
fr.readAsText(this.result);
fr.onerror = function() {
ok(false, "ArchiveReader + FileReader should work!");
markTestDone();
}
fr.onload = function(event) {
is(event.target.result, "hello world, 2!\n", "ArchiveReader + FileReader are working together.");
markTestDone();
}
}
handle3.onerror = function() {
ok(false, "ArchiveReader.getFile('test/b.txt') should not return an 'error'");
markTestDone();
}
var handle4 = r.getFile("test/a.txt");
@ -190,6 +216,7 @@
fr.readAsText(this.result);
fr.onerror = function() {
ok(false, "ArchiveReader + FileReader should work!");
markTestDone();
}
fr.onload = function(event) {
is(event.target.result.length, 600, "ArchiveReader + FileReader are working with a compress data");
@ -198,24 +225,18 @@
for (var i = 0; i < p.length; ++i)
is(p[i], "hello world", "ArchiveReader + FileReader are working with a compress data");
markTestDone();
}
}
handle4.onerror = function() {
ok(false, "ArchiveReader.getFile('test/a.txt') should not return an 'error'");
markTestDone();
}
}
finishTest();
yield;
}
SimpleTest.waitForExplicitFinish();
testSteps();
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
</body>
</html>

View File

@ -499,6 +499,7 @@ DOMCI_DATA(IDBFactory, IDBFactory)
nsresult
IDBFactory::OpenCommon(const nsAString& aName,
int64_t aVersion,
const nsACString& aASCIIOrigin,
bool aDeleting,
JSContext* aCallingCx,
IDBOpenDBRequest** _retval)
@ -529,7 +530,7 @@ IDBFactory::OpenCommon(const nsAString& aName,
if (IndexedDatabaseManager::IsMainProcess()) {
nsRefPtr<OpenDatabaseHelper> openHelper =
new OpenDatabaseHelper(request, aName, mASCIIOrigin, aVersion, aDeleting,
new OpenDatabaseHelper(request, aName, aASCIIOrigin, aVersion, aDeleting,
mContentParent, privilege);
rv = openHelper->Init();
@ -542,13 +543,13 @@ IDBFactory::OpenCommon(const nsAString& aName,
NS_ASSERTION(mgr, "This should never be null!");
rv =
mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mASCIIOrigin),
mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin),
openHelper->Id(), permissionHelper);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
else if (aDeleting) {
nsCOMPtr<nsIAtom> databaseId =
IndexedDatabaseManager::GetDatabaseId(mASCIIOrigin, aName);
IndexedDatabaseManager::GetDatabaseId(aASCIIOrigin, aName);
NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
IndexedDBDeleteDatabaseRequestChild* actor =

View File

@ -92,10 +92,22 @@ public:
nsresult
OpenCommon(const nsAString& aName,
int64_t aVersion,
const nsACString& aASCIIOrigin,
bool aDeleting,
JSContext* aCallingCx,
IDBOpenDBRequest** _retval);
nsresult
OpenCommon(const nsAString& aName,
int64_t aVersion,
bool aDeleting,
JSContext* aCallingCx,
IDBOpenDBRequest** _retval)
{
return OpenCommon(aName, aVersion, mASCIIOrigin, aDeleting, aCallingCx,
_retval);
}
void
SetActor(IndexedDBChild* aActorChild)
{

View File

@ -81,6 +81,7 @@ MOCHITEST_FILES = \
test_object_identity.html \
test_odd_result_order.html \
test_open_empty_db.html \
test_open_for_principal.html \
test_open_objectStore.html \
test_optionalArguments.html \
test_overlapping_transactions.html \

View File

@ -0,0 +1,31 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
is("open" in indexedDB, true, "open() defined");
is("openForPrincipal" in indexedDB, false, "openForPrincipal() not defined");
is("deleteDatabase" in indexedDB, true, "deleteDatabase() defined");
is("deleteForPrincipal" in indexedDB, false, "deleteForPrincipal() not defined");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -45,6 +45,7 @@ MOCHITEST_FILES = \
test_objectStore_remove_values.js \
test_odd_result_order.js \
test_open_empty_db.js \
test_open_for_principal.js \
test_open_objectStore.js \
test_optionalArguments.js \
test_overlapping_transactions.js \

View File

@ -0,0 +1,90 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const objectStoreName = "Foo";
const data = { key: 1, value: "bar" };
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.type, "upgradeneeded", "Got correct event type");
let db = event.target.result;
db.onerror = errorHandler;
let objectStore = db.createObjectStore(objectStoreName, { });
event = yield;
is(event.type, "success", "Got correct event type");
objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
request = objectStore.get(data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, null, "Got no data");
request = objectStore.add(data.value, data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, data.key, "Got correct key");
let uri = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newURI("http://appdata.example.com", null, null);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(uri);
request = indexedDB.openForPrincipal(principal, name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.type, "upgradeneeded", "Got correct event type");
db = event.target.result;
db.onerror = errorHandler;
objectStore = db.createObjectStore(objectStoreName, { });
event = yield;
is(event.type, "success", "Got correct event type");
objectStore = db.transaction([objectStoreName])
.objectStore(objectStoreName);
request = objectStore.get(data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, null, "Got no data");
db.close();
request = indexedDB.deleteForPrincipal(principal, name);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler
event = yield;
finishTest();
yield;
}

View File

@ -38,6 +38,7 @@ tail =
[test_objectStore_remove_values.js]
[test_odd_result_order.js]
[test_open_empty_db.js]
[test_open_for_principal.js]
[test_open_objectStore.js]
[test_optionalArguments.js]
[test_overlapping_transactions.js]

View File

@ -7,6 +7,7 @@
interface nsIVariant;
interface nsIPropertyBag2;
interface nsIContentURIGrouper;
interface nsILoadContext;
interface mozIStorageConnection;
[scriptable, uuid(746c7a02-f6c1-4869-b434-7c8b86e60e61)]
@ -38,7 +39,7 @@ interface nsIContentPrefCallback : nsISupports
void onResult(in nsIVariant aResult);
};
[scriptable, uuid(0014e2b4-1bab-4946-9211-7d28fc8df4d7)]
[scriptable, uuid(e3f772f3-023f-4b32-b074-36cf0fd5d414)]
interface nsIContentPrefService : nsISupports
{
/**
@ -57,6 +58,11 @@ interface nsIContentPrefService : nsISupports
* (typically in the format of a hostname), or null
* to get the global pref (applies to all sites)
* @param aName the name of the pref to get
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search in memory or in
* permanent storage for it), obtained from a relevant
* window or channel.
* @param aCallback an optional nsIContentPrefCallback to receive the
* result. If desired, JavaScript callers can instead
* provide a function to call upon completion
@ -66,6 +72,7 @@ interface nsIContentPrefService : nsISupports
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
nsIVariant getPref(in nsIVariant aGroup, in AString aName,
in nsILoadContext aPrivacyContext,
[optional] in nsIContentPrefCallback aCallback);
/**
@ -80,10 +87,15 @@ interface nsIContentPrefService : nsISupports
* to set the global pref (applies to all sites)
* @param aName the name of the pref to set
* @param aValue the new value of the pref
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to store it in memory or in
* permanent storage), obtained from a relevant
* window or channel.
* @throws NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
void setPref(in nsIVariant aGroup, in AString aName, in nsIVariant aValue);
void setPref(in nsIVariant aGroup, in AString aName, in nsIVariant aValue, in nsILoadContext aPrivacyContext);
/**
* Check whether or not a pref exists.
@ -93,10 +105,15 @@ interface nsIContentPrefService : nsISupports
* (typically in the format of a hostname), or null
* to check for the global pref (applies to all sites)
* @param aName the name of the pref to check for
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search in memory or in
* permanent storage for it), obtained from a relevant
* window or channel.
* @throws NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
boolean hasPref(in nsIVariant aGroup, in AString aName);
boolean hasPref(in nsIVariant aGroup, in AString aName, in nsILoadContext aContext);
/**
* Check whether or not the value of a pref (or its non-existance) is cached.
@ -106,10 +123,15 @@ interface nsIContentPrefService : nsISupports
* (typically in the format of a hostname), or null
* to check for the global pref (applies to all sites)
* @param aName the name of the pref to check for
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search in memory or in
* permanent storage for it), obtained from a relevant
* window or channel.
* @throws NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
boolean hasCachedPref(in nsIVariant aGroup, in AString aName);
boolean hasCachedPref(in nsIVariant aGroup, in AString aName, in nsILoadContext aContext);
/**
* Remove a pref.
@ -119,24 +141,40 @@ interface nsIContentPrefService : nsISupports
* (typically in the format of a hostname), or null
* to remove the global pref (applies to all sites)
* @param aName the name of the pref to remove
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search in memory or in
* permanent storage for it), obtained from a relevant
* window or channel.
* @throws NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
void removePref(in nsIVariant aGroup, in AString aName);
void removePref(in nsIVariant aGroup, in AString aName, in nsILoadContext aContext);
/**
* Remove all grouped prefs. Useful for removing references to the sites
* the user has visited when the user clears their private data.
*
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to remove prefs in memory or
* in permanent storage), obtained from a relevant
* window or channel.
*/
void removeGroupedPrefs();
void removeGroupedPrefs(in nsILoadContext aContext);
/**
* Remove all prefs with the given name.
*
* @param aName the setting name for which to remove prefs
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the prefs (ie. whether to remove prefs in memory or
* in permanent storage), obtained from a relevant
* window or channel.
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
void removePrefsByName(in AString aName);
void removePrefsByName(in AString aName, in nsILoadContext aContext);
/**
* Get the prefs that apply to the given site.
@ -145,21 +183,31 @@ interface nsIContentPrefService : nsISupports
* from which the hostname will be used, a string
* (typically in the format of a hostname), or null
* to get the global prefs (apply to all sites)
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search for prefs in memory
* or in permanent storage), obtained from a relevant
* window or channel.
*
* @returns a property bag of prefs
* @throws NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
*/
nsIPropertyBag2 getPrefs(in nsIVariant aGroup);
nsIPropertyBag2 getPrefs(in nsIVariant aGroup, in nsILoadContext aContext);
/**
* Get the prefs with the given name.
*
* @param aName the setting name for which to retrieve prefs
* @param aPrivacyContext
* a context from which to determine the privacy status
* of the pref (ie. whether to search for prefs in memory
* or in permanent storage), obtained from a relevant
* window or channel.
*
* @returns a property bag of prefs
* @throws NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
*/
nsIPropertyBag2 getPrefsByName(in AString aName);
nsIPropertyBag2 getPrefsByName(in AString aName, in nsILoadContext aContext);
/**
* Add an observer.

View File

@ -353,7 +353,7 @@ interface nsIDOMDocument : nsIDOMNode
/**
* Denotes whether the full-screen-api.enabled is true, no windowed
* plugins are present, and all ancestor documents have the
* mozallowfullscreen attribute set.
* allowfullscreen attribute set.
*
* @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
*/

View File

@ -16,7 +16,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(52f6244b-b1f5-4f4c-8ff3-7e146316f411)]
[scriptable, uuid(a7bd1e34-3969-47ae-8c1d-2970132ba925)]
interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement
{
attribute DOMString align;
@ -35,8 +35,8 @@ interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement
attribute DOMString sandbox;
// Mozilla extensions
// iframe elements require the mozAllowFullScreen attribute to be present
// iframe elements require the allowfullscreen attribute to be present
// if they're to allow content in the sub document to go into DOM full-screen
// mode. See https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI
attribute boolean mozAllowFullScreen;
attribute boolean allowfullscreen;
};

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