mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
Merge the last PGO-green inbound changest to m-c.
This commit is contained in:
commit
498dad2875
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -14,7 +14,7 @@ var gDumpToConsole = true;
|
||||
*/
|
||||
function testNames()
|
||||
{
|
||||
enableLogging("tree");
|
||||
enableLogging("tree,stack");
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("get", gNameRulesFileURL, false);
|
||||
|
@ -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)
|
||||
|
@ -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');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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")
|
||||
return;
|
||||
if (state == 'online') {
|
||||
shell.CrashSubmit.submit(crashID);
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
}
|
||||
}
|
||||
, "network:offline-status-changed", false);
|
||||
// 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(aCrashID);
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
}
|
||||
}, "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);
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
|
||||
|
@ -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/>
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -880,7 +880,7 @@ function startTest() {
|
||||
return;
|
||||
}
|
||||
|
||||
subwindow.mozAllowFullScreen = true;
|
||||
subwindow.allowfullscreen = true;
|
||||
lastElement = null;
|
||||
|
||||
text = subwindow.document.getElementById("test-text");
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -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) {}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
@ -24,23 +23,25 @@ function run_test_on_service() {
|
||||
const kPassword = "pass";
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ========================================================
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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,47 +6614,32 @@ 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)) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_CONTENT;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
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)) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_CONTENT;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
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)) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_CONTENT;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
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
|
||||
|
||||
@ -6667,7 +6653,6 @@ nsContentUtils::FindInternalContentViewer(const char* aType,
|
||||
return docFactory.forget();
|
||||
}
|
||||
#endif // MOZ_MEDIA_PLUGINS
|
||||
|
||||
#endif // MOZ_MEDIA
|
||||
|
||||
return NULL;
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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())) {
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
@ -2265,7 +2260,7 @@ nsHTMLMediaElement::IsDASHMPDType(const nsACString& aType)
|
||||
#endif
|
||||
|
||||
/* static */
|
||||
nsHTMLMediaElement::CanPlayStatus
|
||||
nsHTMLMediaElement::CanPlayStatus
|
||||
nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
|
||||
char const *const ** aCodecList)
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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",
|
||||
|
374
content/media/webaudio/AudioEventTimeline.h
Normal file
374
content/media/webaudio/AudioEventTimeline.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
54
content/media/webaudio/AudioParam.cpp
Normal file
54
content/media/webaudio/AudioParam.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
116
content/media/webaudio/AudioParam.h
Normal file
116
content/media/webaudio/AudioParam.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
19
content/media/webaudio/compiledtest/Makefile.in
Normal file
19
content/media/webaudio/compiledtest/Makefile.in
Normal 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
|
343
content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp
Normal file
343
content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -547,13 +547,13 @@ 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);
|
||||
} else if (msg.event == "downloadavailable") {
|
||||
Services.DOMRequest.fireSuccess(req, this.manifestURL);
|
||||
this._fireEvent("downloadavailable", this._ondownloadavailable);
|
||||
}
|
||||
}
|
||||
if (msg.event == "downloadapplied") {
|
||||
Services.DOMRequest.fireSuccess(req, this.manifestURL);
|
||||
this._fireEvent("downloadapplied", this._ondownloadapplied);
|
||||
} else if (msg.event == "downloadavailable") {
|
||||
Services.DOMRequest.fireSuccess(req, this.manifestURL);
|
||||
this._fireEvent("downloadavailable", this._ondownloadavailable);
|
||||
}
|
||||
break;
|
||||
case "Webapps:CheckForUpdate:Return:KO":
|
||||
@ -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 });
|
||||
},
|
||||
|
||||
|
@ -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);
|
||||
@ -921,15 +933,15 @@ let DOMApplicationRegistry = {
|
||||
PermissionsInstaller.installPermissions({ manifest: aManifest,
|
||||
origin: app.origin,
|
||||
manifestURL: aData.manifestURL },
|
||||
true);
|
||||
true);
|
||||
}
|
||||
|
||||
// First, we download the manifest.
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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(" [");
|
||||
|
@ -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;
|
||||
|
@ -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,21 +516,121 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
inline const NativePropertyHooks*
|
||||
GetNativePropertyHooks(JSContext *cx, JSObject *obj, DOMObjectType& type)
|
||||
{
|
||||
const DOMClass* domClass;
|
||||
if (GetDOMClass(obj, domClass) != eNonDOMObject) {
|
||||
type = eInstance;
|
||||
return domClass->mNativeHooks;
|
||||
}
|
||||
|
||||
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 = attributes->specs - attributeSpecs;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if (id == attributeIds[i]) {
|
||||
JSPropertySpec& attrSpec = attributeSpecs[i];
|
||||
// Because of centralization, we need to make sure we fault in the
|
||||
// JitInfos as well. At present, until the JSAPI changes, the easiest
|
||||
// way to do this is wrap them up as functions ourselves.
|
||||
desc->attrs = attrSpec.flags & ~JSPROP_NATIVE_ACCESSORS;
|
||||
// They all have getters, so we can just make it.
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSFunction *fun = JS_NewFunction(cx, (JSNative)attrSpec.getter.op,
|
||||
0, 0, global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attrSpec.getter.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->getter = js::CastAsJSPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_GETTER;
|
||||
if (attrSpec.setter.op) {
|
||||
// We have a setter! Make it.
|
||||
fun = JS_NewFunction(cx, (JSNative)attrSpec.setter.op, 1, 0,
|
||||
global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attrSpec.setter.info);
|
||||
funobj = JS_GetFunctionObject(fun);
|
||||
desc->setter = js::CastAsJSStrictPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_SETTER;
|
||||
} else {
|
||||
desc->setter = nullptr;
|
||||
}
|
||||
desc->obj = wrapper;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
JSPropertyDescriptor* desc,
|
||||
JSPropertyDescriptor* desc, DOMObjectType type,
|
||||
const NativeProperties* nativeProperties)
|
||||
{
|
||||
if (nativeProperties->methods) {
|
||||
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 = nativeProperties->methods; method->specs; ++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 - nativeProperties->methodsSpecs;
|
||||
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
|
||||
if (id == nativeProperties->methodIds[i]) {
|
||||
JSFunctionSpec& methodSpec = nativeProperties->methodsSpecs[i];
|
||||
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);
|
||||
@ -507,58 +651,42 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if (id == attributeIds[i]) {
|
||||
JSPropertySpec& attrSpec = attributeSpecs[i];
|
||||
// Because of centralization, we need to make sure we fault in the
|
||||
// JitInfos as well. At present, until the JSAPI changes, the easiest
|
||||
// way to do this is wrap them up as functions ourselves.
|
||||
desc->attrs = attrSpec.flags & ~JSPROP_NATIVE_ACCESSORS;
|
||||
// They all have getters, so we can just make it.
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSFunction *fun = JS_NewFunction(cx, (JSNative)attrSpec.getter.op,
|
||||
0, 0, global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attrSpec.getter.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->getter = js::CastAsJSPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_GETTER;
|
||||
if (attrSpec.setter.op) {
|
||||
// We have a setter! Make it.
|
||||
fun = JS_NewFunction(cx, (JSNative)attrSpec.setter.op, 1, 0,
|
||||
global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attrSpec.setter.info);
|
||||
funobj = JS_GetFunctionObject(fun);
|
||||
desc->setter = js::CastAsJSStrictPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_SETTER;
|
||||
} else {
|
||||
desc->setter = nullptr;
|
||||
}
|
||||
desc->obj = wrapper;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
attributeSpecs = nativeProperties->unforgeableAttributeSpecs;
|
||||
attr = nativeProperties->unforgeableAttributes;
|
||||
attributeIds = nativeProperties->unforgeableAttributeIds;
|
||||
}
|
||||
|
||||
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,19 +776,85 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
}
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
XrayResolveNativeProperty(JSContext* cx, JSObject* wrapper, JSObject* obj,
|
||||
jsid id, JSPropertyDescriptor* desc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 = attributes->specs - attributeSpecs;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(attributeIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JS::AutoIdVector& props, DOMObjectType type,
|
||||
const NativeProperties* nativeProperties)
|
||||
{
|
||||
if (nativeProperties->methods) {
|
||||
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 = nativeProperties->methods; method->specs; ++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 - nativeProperties->methodsSpecs;
|
||||
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
|
||||
if ((nativeProperties->methodsSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(nativeProperties->methodIds[i])) {
|
||||
size_t i = method->specs - methodsSpecs;
|
||||
for ( ; methodIds[i] != JSID_VOID; ++i) {
|
||||
if ((methodsSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(methodIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -625,30 +862,28 @@ XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(attributeIds[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;
|
||||
}
|
||||
|
||||
attributeSpecs = nativeProperties->unforgeableAttributeSpecs;
|
||||
attr = nativeProperties->unforgeableAttributes;
|
||||
attributeIds = nativeProperties->unforgeableAttributeIds;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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,19 +1269,95 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
bool
|
||||
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
JSPropertyDescriptor* desc,
|
||||
const NativeProperties* nativeProperties,
|
||||
const NativeProperties* chromeOnlyNativeProperties);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
inline void
|
||||
@ -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
|
||||
|
||||
|
@ -96,6 +96,10 @@ DOMInterfaces = {
|
||||
'concrete': False,
|
||||
},
|
||||
|
||||
'AudioParam' : {
|
||||
'nativeOwnership': 'refcounted'
|
||||
},
|
||||
|
||||
'AudioSourceNode': {
|
||||
'concrete': False,
|
||||
},
|
||||
|
@ -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,64 +178,79 @@ 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 = {
|
||||
"%sPrototype",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
NULL, /* finalize */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* construct */
|
||||
NULL, /* trace */
|
||||
JSCLASS_NO_INTERNAL_MEMBERS
|
||||
return """static DOMIfaceAndProtoJSClass PrototypeClass = {
|
||||
{
|
||||
"%sPrototype",
|
||||
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
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,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
NULL, /* finalize */
|
||||
NULL, /* checkAccess */
|
||||
%s, /* call */
|
||||
%s, /* hasInstance */
|
||||
%s, /* construct */
|
||||
NULL, /* trace */
|
||||
JSCLASS_NO_INTERNAL_MEMBERS
|
||||
static DOMIfaceAndProtoJSClass InterfaceObjectClass = {
|
||||
{
|
||||
"Function",
|
||||
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
nullptr, /* finalize */
|
||||
nullptr, /* checkAccess */
|
||||
%s, /* call */
|
||||
%s, /* hasInstance */
|
||||
%s, /* construct */
|
||||
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,
|
||||
"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)]
|
||||
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) }
|
||||
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()
|
||||
else "genericGetter")
|
||||
return ("{(JSPropertyOp)%(native)s, &%(name)s_getterinfo}"
|
||||
% {"name" : attr.identifier.name,
|
||||
"native" : native})
|
||||
if self.static:
|
||||
accessor = 'get_' + attr.identifier.name
|
||||
jitinfo = "nullptr"
|
||||
else:
|
||||
accessor = ("genericLenientGetter" if attr.hasLenientThis()
|
||||
else "genericGetter")
|
||||
jitinfo = "&%s_getterinfo" % attr.identifier.name
|
||||
return "{ (JSPropertyOp)%s, %s }" % (accessor, jitinfo)
|
||||
|
||||
def setter(attr):
|
||||
if attr.readonly and attr.getExtendedAttribute("PutForwards") is None:
|
||||
return "JSOP_NULLWRAPPER"
|
||||
native = ("genericLenientSetter" if attr.hasLenientThis()
|
||||
else "genericSetter")
|
||||
return ("{(JSStrictPropertyOp)%(native)s, &%(name)s_setterinfo}"
|
||||
% {"name" : attr.identifier.name,
|
||||
"native" : native})
|
||||
if self.static:
|
||||
accessor = 'set_' + attr.identifier.name
|
||||
jitinfo = "nullptr"
|
||||
else:
|
||||
if attr.readonly and attr.getExtendedAttribute("PutForwards") is None:
|
||||
return "JSOP_NULLWRAPPER"
|
||||
accessor = ("genericLenientSetter" if attr.hasLenientThis()
|
||||
else "genericSetter")
|
||||
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,30 +5460,42 @@ 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'])):
|
||||
cgThings.append(CGSpecializedMethod(descriptor, m))
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
hasMethod = True
|
||||
elif m.isAttr():
|
||||
cgThings.append(CGSpecializedGetter(descriptor, m))
|
||||
if m.hasLenientThis():
|
||||
hasLenientGetter = True
|
||||
if m.isStatic():
|
||||
cgThings.append(CGStaticMethod(descriptor, m))
|
||||
else:
|
||||
hasGetter = True
|
||||
if not m.readonly:
|
||||
cgThings.append(CGSpecializedSetter(descriptor, m))
|
||||
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():
|
||||
hasLenientSetter = True
|
||||
hasLenientGetter = True
|
||||
else:
|
||||
hasSetter = True
|
||||
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
|
||||
else:
|
||||
hasSetter = True
|
||||
elif m.getExtendedAttribute("PutForwards"):
|
||||
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
|
||||
hasSetter = True
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if not m.isStatic():
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
|
||||
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
|
||||
if hasLenientGetter: 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:
|
||||
cgThings.append(CGResolveOwnProperty(descriptor))
|
||||
cgThings.append(CGEnumerateOwnProperties(descriptor))
|
||||
cgThings.append(CGResolveProperty(descriptor, properties))
|
||||
cgThings.append(CGEnumerateProperties(descriptor, properties))
|
||||
if not descriptor.workers and descriptor.concrete and descriptor.proxy:
|
||||
cgThings.append(CGResolveOwnProperty(descriptor))
|
||||
cgThings.append(CGEnumerateOwnProperties(descriptor))
|
||||
|
||||
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)
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include "mozilla/dom/PrototypeList.h" // auto-generated
|
||||
|
||||
@ -27,21 +28,27 @@ 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,
|
||||
JS::AutoIdVector& props);
|
||||
(* 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,14 +88,45 @@ 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;
|
||||
|
||||
const NativePropertyHooks *mProtoHooks;
|
||||
// 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
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -371,9 +371,10 @@ BrowserElementParent.prototype = {
|
||||
_recvGetName: function(data) {
|
||||
return this._frameElement.getAttribute('name');
|
||||
},
|
||||
|
||||
|
||||
_recvGetFullscreenAllowed: function(data) {
|
||||
return this._frameElement.hasAttribute('mozallowfullscreen');
|
||||
return this._frameElement.hasAttribute('allowfullscreen') ||
|
||||
this._frameElement.hasAttribute('mozallowfullscreen');
|
||||
},
|
||||
|
||||
_fireCtxMenuEvent: function(data) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,14 @@
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
<body>
|
||||
<p id="display">
|
||||
<input id="fileList" type="file"></input>
|
||||
</p>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function createZipFileWithData(fileData) {
|
||||
var Cc = SpecialPowers.Cc;
|
||||
var Ci = SpecialPowers.Ci;
|
||||
@ -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>
|
||||
|
@ -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 =
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 \
|
||||
|
31
dom/indexedDB/test/test_open_for_principal.html
Normal file
31
dom/indexedDB/test/test_open_for_principal.html
Normal 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>
|
@ -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 \
|
||||
|
90
dom/indexedDB/test/unit/test_open_for_principal.js
Normal file
90
dom/indexedDB/test/unit/test_open_for_principal.js
Normal 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;
|
||||
}
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
*/
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user