Merge mozilla-central into build-system

Only conflict was configure.in amd was due to context, not
changed lines themselves.
This commit is contained in:
Gregory Szorc 2013-02-25 22:09:18 -08:00
commit 45faa95b04
151 changed files with 2160 additions and 1011 deletions

View File

@ -18,7 +18,7 @@
<script class="testbody" type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
const Ci = Components.interfaces;
const Ci = SpecialPowers.Ci;
let wrapperClickCount = 0;
function test1() {

View File

@ -64,4 +64,11 @@ BRANDING_DEST := $(DIST)/branding
BRANDING_TARGET := export
INSTALL_TARGETS += BRANDING
ifeq ($(MOZ_WIDGET_TOOLKIT) $(DIST_SUBDIR),windows metro)
VISUALMANIFEST := VisualElementsManifest.xml
VISUALMANIFEST_FLAGS := -Fsubstitution -DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME}
VISUALMANIFEST_PATH := $(DIST)/bin
PP_TARGETS += VISUALMANIFEST
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,16 @@
<Application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VisualElements
DisplayName="@MOZ_APP_DISPLAYNAME@"
Logo="tileresources\VisualElements_logo.png"
SmallLogo="tileresources\VisualElements_smalllogo.png"
ForegroundText="light"
BackgroundColor="#1c112e">
<DefaultTile
ShortName="@MOZ_APP_DISPLAYNAME@"
ShowName="allLogos"
/>
<SplashScreen
Image="tileresources\VisualElements_splashscreen.png" />
</VisualElements>
</Application>

View File

@ -64,4 +64,11 @@ BRANDING_DEST := $(DIST)/branding
BRANDING_TARGET := export
INSTALL_TARGETS += BRANDING
ifeq ($(MOZ_WIDGET_TOOLKIT) $(DIST_SUBDIR),windows metro)
VISUALMANIFEST := VisualElementsManifest.xml
VISUALMANIFEST_FLAGS := -Fsubstitution -DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME}
VISUALMANIFEST_PATH := $(DIST)/bin
PP_TARGETS += VISUALMANIFEST
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,16 @@
<Application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VisualElements
DisplayName="@MOZ_APP_DISPLAYNAME@"
Logo="tileresources\VisualElements_logo.png"
SmallLogo="tileresources\VisualElements_smalllogo.png"
ForegroundText="light"
BackgroundColor="#001226">
<DefaultTile
ShortName="@MOZ_APP_DISPLAYNAME@"
ShowName="allLogos"
/>
<SplashScreen
Image="tileresources\VisualElements_splashscreen.png" />
</VisualElements>
</Application>

View File

@ -64,4 +64,11 @@ BRANDING_DEST := $(DIST)/branding
BRANDING_TARGET := export
INSTALL_TARGETS += BRANDING
ifeq ($(MOZ_WIDGET_TOOLKIT) $(DIST_SUBDIR),windows metro)
VISUALMANIFEST := VisualElementsManifest.xml
VISUALMANIFEST_FLAGS := -Fsubstitution -DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME}
VISUALMANIFEST_PATH := $(DIST)/bin
PP_TARGETS += VISUALMANIFEST
endif
include $(topsrcdir)/config/rules.mk

View File

@ -64,4 +64,11 @@ BRANDING_DEST := $(DIST)/branding
BRANDING_TARGET := export
INSTALL_TARGETS += BRANDING
ifeq ($(MOZ_WIDGET_TOOLKIT) $(DIST_SUBDIR),windows metro)
VISUALMANIFEST := VisualElementsManifest.xml
VISUALMANIFEST_FLAGS := -Fsubstitution -DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME}
VISUALMANIFEST_PATH := $(DIST)/bin
PP_TARGETS += VISUALMANIFEST
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,16 @@
<Application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VisualElements
DisplayName="@MOZ_APP_DISPLAYNAME@"
Logo="tileresources\VisualElements_logo.png"
SmallLogo="tileresources\VisualElements_smalllogo.png"
ForegroundText="light"
BackgroundColor="#001226">
<DefaultTile
ShortName="@MOZ_APP_DISPLAYNAME@"
ShowName="allLogos"
/>
<SplashScreen
Image="tileresources\VisualElements_splashscreen.png" />
</VisualElements>
</Application>

View File

@ -8,6 +8,7 @@
var gClient = null;
var gTab = null;
var gHomeTab = null;
var gThreadClient = null;
var gNewGlobal = false;
var gAttached = false;
@ -33,8 +34,7 @@ function test()
gAttached = true;
// Ensure that a new global will be created.
let frame = content.document.createElement("iframe");
content.document.querySelector("body").appendChild(frame);
gHomeTab = gBrowser.addTab("about:home");
finish_test();
});
@ -58,6 +58,7 @@ function finish_test()
}
gClient.removeListener("newScript", onNewScript);
gThreadClient.resume(function(aResponse) {
removeTab(gHomeTab);
removeTab(gTab);
gClient.close(function() {
ok(gNewGlobal, "Received newGlobal event.");

View File

@ -219,7 +219,7 @@ var TouchModule = {
this._targetScrollInterface = targetScrollInterface;
if (!this._targetScrollbox) {
return false;
return;
}
// XXX shouldn't dragger always be valid here?

View File

@ -13,15 +13,8 @@ include $(DEPTH)/config/autoconf.mk
export::
$(NSINSTALL) $(srcdir)/resources.pri $(DIST)/bin
$(RM) $(DIST)/bin/VisualElementsManifest.xml
$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) -DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME} \
$(srcdir)/VisualElementsManifest.xml.in > $(DIST)/bin/VisualElementsManifest.xml
install::
$(NSINSTALL) $(srcdir)/resources.pri $(DIST)/bin
# bug 744566
# $(RM) $(DIST)/bin/resources.pri
# $(MAKEPRI) new -v -pr $(srcdir)/tileresources -cf $(srcdir)/priconfig.xml -mn $(srcdir)/AppManifest.xml -of $(DIST)/bin/resources.pri -o
include $(topsrcdir)/config/rules.mk

View File

@ -94,6 +94,15 @@ if test "$CLANG_CXX"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-mismatched-tags"
fi
if test -z "$GNU_CC"; then
case "$target" in
*-mingw*)
## Warning 4099 (equivalent of mismatched-tags) is disabled (bug 780474)
## for the same reasons as above.
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -wd4099"
esac
fi
if test "$GNU_CC"; then
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fno-exceptions"

View File

@ -2157,8 +2157,9 @@ ia64*-hpux*)
# that behavior) that it's better to turn it off.
# MSVC warning C4819 warns some UTF-8 characters (e.g. copyright sign)
# on non-Western system locales even if it is in a comment.
# khuey says we can safely ignore MSVC warning C4251
CFLAGS="$CFLAGS -wd4819"
CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4482 -wd4800 -wd4819"
CXXFLAGS="$CXXFLAGS -wd4251 -wd4345 -wd4351 -wd4482 -wd4800 -wd4819"
# make 'foo == bar;' error out
CFLAGS="$CFLAGS -we4553"
CXXFLAGS="$CXXFLAGS -we4553"
@ -8965,7 +8966,7 @@ case "$host" in
;;
esac
# target_arch is from {ia32|x64|arm}
# target_arch is from {ia32|x64|arm|ppc}
case "$CPU_ARCH" in
x86_64 | ia64)
WEBRTC_TARGET_ARCH=x64
@ -8979,6 +8980,9 @@ x86)
WEBRTC_TARGET_ARCH=ia32
;;
ppc*)
WEBRTC_TARGET_ARCH=ppc
;;
*)
# unsupported arch for webrtc
WEBRTC_TARGET_ARCH=unknown

View File

@ -86,7 +86,7 @@
#include "sampler.h"
#include "jsapi.h"
#include "nsHTMLIFrameElement.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "nsSandboxFlags.h"
#include "mozilla/dom/StructuredCloneUtils.h"
@ -450,8 +450,8 @@ nsFrameLoader::ReallyStartLoadingInternal()
// Is this an <iframe> with a sandbox attribute or a parent which is
// sandboxed ?
nsHTMLIFrameElement* iframe =
nsHTMLIFrameElement::FromContent(mOwnerContent);
HTMLIFrameElement* iframe =
HTMLIFrameElement::FromContent(mOwnerContent);
uint32_t sandboxFlags = 0;

View File

@ -1025,7 +1025,8 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
if (!unicodeDecoder &&
aChannel &&
NS_SUCCEEDED(aChannel->GetContentCharset(charset))) {
NS_SUCCEEDED(aChannel->GetContentCharset(charset)) &&
!charset.IsEmpty()) {
charsetConv->GetUnicodeDecoder(charset.get(),
getter_AddRefs(unicodeDecoder));
}

View File

@ -3371,6 +3371,8 @@ nsXMLHttpRequest::SetMultipart(bool aMultipart, nsresult& aRv)
return;
}
LogMessage("MultipartXHRWarning", GetOwner());
if (aMultipart) {
mState |= XML_HTTP_REQUEST_MULTIPART;
} else {

View File

@ -24,10 +24,8 @@ let am = {
authMgr: null,
init: function() {
const {classes: Cc, interfaces: Ci} = SpecialPowers.wrap(Components);
this.authMgr = Cc["@mozilla.org/network/http-auth-manager;1"]
.getService(Components.interfaces.nsIHttpAuthManager)
this.authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
.getService(SpecialPowers.Ci.nsIHttpAuthManager)
},
addIdentity: function() {

View File

@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=425013
<script type="text/javascript;version=1.7">
var missingPlugins = new Array();
var OBJLC = Components.interfaces.nsIObjectLoadingContent;
var OBJLC = SpecialPowers.Ci.nsIObjectLoadingContent;
function pluginBinding(event)
{

View File

@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429157
<script>
var missingPlugins = new Array();
const OBJLC = Components.interfaces.nsIObjectLoadingContent;
const OBJLC = SpecialPowers.Ci.nsIObjectLoadingContent;
function pluginBindingAttached(event)
{

View File

@ -19,7 +19,7 @@ function test(tag, type) {
"use strict";
info("testing " + tag + " tag with type " + type);
const OBJLC = Components.interfaces.nsIObjectLoadingContent;
const OBJLC = SpecialPowers.Ci.nsIObjectLoadingContent;
let obj = document.createElement(tag);
obj.type = type;
document.body.appendChild(obj);

View File

@ -16,14 +16,12 @@
<pre id="test">
<script class="testbody" type="application/javascript;version=1.8">
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = SpecialPowers.wrap(Components);
const APP_URL = "http://example.org";
const APP_MANIFEST = "http://example.org/manifest.webapp";
const CHILD_PROCESS_SHUTDOWN_MESSAGE = "child-process-shutdown";
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster);
let ppmm = SpecialPowers.Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsIMessageBroadcaster);
/**
* Load the example.org site in an <iframe mozbrowser>

View File

@ -15,18 +15,16 @@
<pre id="test">
<script class="testbody" type="application/javascript;version=1.8">
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = SpecialPowers.wrap(Components);
const APP_URL = "http://example.org";
const APP_MANIFEST = "http://example.org/manifest.webapp";
const CHILD_PROCESS_SHUTDOWN_MESSAGE = "child-process-shutdown";
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster);
let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
let gAppsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
let ppmm = SpecialPowers.Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsIMessageBroadcaster);
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsISyncMessageSender);
let gAppsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"]
.getService(SpecialPowers.Ci.nsIAppsService);
function setUp() {
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);

View File

@ -45,8 +45,8 @@ var OPTIONS = {
SimpleTest.waitForExplicitFinish();
function detectDriverType() {
const Cc = SpecialPowers.wrap(Components).classes;
const Ci = SpecialPowers.wrap(Components).interfaces;
const Cc = SpecialPowers.Cc;
const Ci = SpecialPowers.Ci;
var doc = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser).parseFromString("<html/>", "text/html");
var canvas = doc.createElement("canvas");
@ -105,15 +105,15 @@ function start() {
if (kIsWindows) {
// code borrowed from browser/modules/test/browser_taskbar_preview.js
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var version = Components.classes["@mozilla.org/system-info;1"]
.getService(Components.interfaces.nsIPropertyBag2)
var version = SpecialPowers.Cc["@mozilla.org/system-info;1"]
.getService(SpecialPowers.Ci.nsIPropertyBag2)
.getProperty("version");
kIsWindowsVistaOrHigher = (parseFloat(version) >= 6.0);
}
function getEnv(env) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var envsvc = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment);
var envsvc = SpecialPowers.Cc["@mozilla.org/process/environment;1"].getService(SpecialPowers.Ci.nsIEnvironment);
var val = envsvc.get(env);
if (val == "")
return null;

View File

@ -5,7 +5,7 @@
#include "mozilla/Util.h"
#include "nsHTMLIFrameElement.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "nsIDOMSVGDocument.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
@ -14,86 +14,86 @@
#include "nsStyleConsts.h"
#include "nsContentUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser)
DOMCI_NODE_DATA(HTMLIFrameElement, mozilla::dom::HTMLIFrameElement)
namespace mozilla {
namespace dom {
HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
{
}
nsHTMLIFrameElement::~nsHTMLIFrameElement()
HTMLIFrameElement::~HTMLIFrameElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLIFrameElement, Element)
NS_IMPL_ADDREF_INHERITED(HTMLIFrameElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLIFrameElement, Element)
DOMCI_NODE_DATA(HTMLIFrameElement, nsHTMLIFrameElement)
// QueryInterface implementation for nsHTMLIFrameElement
NS_INTERFACE_TABLE_HEAD(nsHTMLIFrameElement)
NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(nsHTMLIFrameElement)
NS_INTERFACE_TABLE_ENTRY(nsHTMLIFrameElement, nsIDOMHTMLIFrameElement)
NS_INTERFACE_TABLE_ENTRY(nsHTMLIFrameElement, nsIDOMGetSVGDocument)
// QueryInterface implementation for HTMLIFrameElement
NS_INTERFACE_TABLE_HEAD(HTMLIFrameElement)
NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(HTMLIFrameElement)
NS_INTERFACE_TABLE_ENTRY(HTMLIFrameElement, nsIDOMHTMLIFrameElement)
NS_INTERFACE_TABLE_ENTRY(HTMLIFrameElement, nsIDOMGetSVGDocument)
NS_OFFSET_AND_INTERFACE_TABLE_END
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLIFrameElement,
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLIFrameElement,
nsGenericHTMLFrameElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLIFrameElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLIFrameElement)
NS_IMPL_ELEMENT_CLONE(HTMLIFrameElement)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Align, align)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, FrameBorder, frameborder)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Height, height)
NS_IMPL_URI_ATTR(nsHTMLIFrameElement, LongDesc, longdesc)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, MarginHeight, marginheight)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, MarginWidth, marginwidth)
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, Allowfullscreen, allowfullscreen)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Sandbox, sandbox)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Align, align)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, FrameBorder, frameborder)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Height, height)
NS_IMPL_URI_ATTR(HTMLIFrameElement, LongDesc, longdesc)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginHeight, marginheight)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginWidth, marginwidth)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Name, name)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Scrolling, scrolling)
NS_IMPL_URI_ATTR(HTMLIFrameElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Width, width)
NS_IMPL_BOOL_ATTR(HTMLIFrameElement, Allowfullscreen, allowfullscreen)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Sandbox, sandbox)
void
nsHTMLIFrameElement::GetItemValueText(nsAString& aValue)
HTMLIFrameElement::GetItemValueText(nsAString& aValue)
{
GetSrc(aValue);
}
void
nsHTMLIFrameElement::SetItemValueText(const nsAString& aValue)
HTMLIFrameElement::SetItemValueText(const nsAString& aValue)
{
SetSrc(aValue);
}
NS_IMETHODIMP
nsHTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
HTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
{
return nsGenericHTMLFrameElement::GetContentDocument(aContentDocument);
}
NS_IMETHODIMP
nsHTMLIFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
HTMLIFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
{
return nsGenericHTMLFrameElement::GetContentWindow(aContentWindow);
}
NS_IMETHODIMP
nsHTMLIFrameElement::GetSVGDocument(nsIDOMDocument **aResult)
HTMLIFrameElement::GetSVGDocument(nsIDOMDocument **aResult)
{
return GetContentDocument(aResult);
}
bool
nsHTMLIFrameElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
HTMLIFrameElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::marginwidth) {
@ -180,7 +180,7 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
}
NS_IMETHODIMP_(bool)
nsHTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
HTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::width },
@ -202,15 +202,15 @@ nsHTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
nsMapRuleToAttributesFunc
nsHTMLIFrameElement::GetAttributeMappingFunction() const
HTMLIFrameElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
nsresult
nsHTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
bool aNotify)
HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
bool aNotify)
{
if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None) {
// Parse the new value of the sandbox attribute, and if we have a docshell
@ -237,7 +237,7 @@ nsHTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
uint32_t
nsHTMLIFrameElement::GetSandboxFlags()
HTMLIFrameElement::GetSandboxFlags()
{
nsAutoString sandboxAttr;
@ -248,3 +248,6 @@ nsHTMLIFrameElement::GetSandboxFlags()
// No sandbox attribute, no sandbox flags.
return 0;
}
} // namespace dom
} // namespace mozilla

View File

@ -3,20 +3,26 @@
* 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/. */
#ifndef mozilla_dom_HTMLIFrameElement_h
#define mozilla_dom_HTMLIFrameElement_h
#include "nsGenericHTMLFrameElement.h"
#include "nsIDOMHTMLIFrameElement.h"
#include "nsIDOMGetSVGDocument.h"
class nsHTMLIFrameElement : public nsGenericHTMLFrameElement
, public nsIDOMHTMLIFrameElement
, public nsIDOMGetSVGDocument
namespace mozilla {
namespace dom {
class HTMLIFrameElement MOZ_FINAL : public nsGenericHTMLFrameElement
, public nsIDOMHTMLIFrameElement
, public nsIDOMGetSVGDocument
{
public:
nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
virtual ~nsHTMLIFrameElement();
HTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser = NOT_FROM_PARSER);
virtual ~HTMLIFrameElement();
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(nsHTMLIFrameElement, iframe)
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLIFrameElement, iframe)
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -58,3 +64,8 @@ protected:
virtual void GetItemValueText(nsAString& text);
virtual void SetItemValueText(const nsAString& text);
};
} // namespace dom
} // namespace mozilla
#endif

View File

@ -21,7 +21,6 @@ endif # !_MSC_VER
EXPORTS = \
HTMLPropertiesCollection.h \
nsGenericHTMLElement.h \
nsHTMLIFrameElement.h \
nsClientRect.h \
nsHTMLDNSPrefetch.h \
nsTimeRanges.h \
@ -43,6 +42,7 @@ EXPORTS_mozilla/dom = \
HTMLFrameSetElement.h \
HTMLHeadingElement.h \
HTMLHRElement.h \
HTMLIFrameElement.h \
HTMLImageElement.h \
HTMLLabelElement.h \
HTMLLegendElement.h \
@ -103,7 +103,7 @@ CPPSRCS = \
HTMLFrameSetElement.cpp \
HTMLHRElement.cpp \
HTMLHeadingElement.cpp \
nsHTMLIFrameElement.cpp \
HTMLIFrameElement.cpp \
HTMLImageElement.cpp \
nsHTMLInputElement.cpp \
HTMLLIElement.cpp \

View File

@ -78,7 +78,7 @@ addLoadEvent(function() {
is(d.testAncestor, "ancestor",
"test1" + ": Empty field should not override ancestor binding");
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.counter = 0;
d.testEvalOnce;
d.testEvalOnce;

View File

@ -135,6 +135,14 @@ AudioChannelService::UnregisterType(AudioChannelType aType,
// In order to avoid race conditions, it's safer to notify any existing
// agent any time a new one is registered.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
// We only remove ChildID when it is in the foreground.
// If in the background, we kept ChildID for allowing it to play next song.
if (aType == AUDIO_CHANNEL_CONTENT &&
mActiveContentChildIDs.Contains(aChildID) &&
(!aElementHidden &&
!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID))) {
mActiveContentChildIDs.RemoveElement(aChildID);
}
SendAudioChannelChangedNotification();
Notify();
}
@ -175,23 +183,31 @@ AudioChannelService::GetMutedInternal(AudioChannelType aType, uint64_t aChildID,
// If the audio content channel is visible, let's remember this ChildID.
if (newType == AUDIO_CHANNEL_INT_CONTENT &&
oldType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
!mActiveContentChildIDs.Contains(aChildID)) {
oldType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN) {
if (mActiveContentChildIDsFrozen) {
mActiveContentChildIDsFrozen = false;
mActiveContentChildIDs.Clear();
}
mActiveContentChildIDs.AppendElement(aChildID);
if (!mActiveContentChildIDs.Contains(aChildID)) {
mActiveContentChildIDs.AppendElement(aChildID);
}
}
// If nothing is visible, the list has to been frozen.
else if (newType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
oldType == AUDIO_CHANNEL_INT_CONTENT &&
!mActiveContentChildIDsFrozen &&
mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
mActiveContentChildIDsFrozen = true;
!mActiveContentChildIDsFrozen) {
// If nothing is visible, the list has to been frozen.
// Or if there is still any one with other ChildID in foreground then
// it should be removed from list and left other ChildIDs in the foreground
// to keep playing. Finally only last one childID which go to background
// will be in list.
if (mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
mActiveContentChildIDsFrozen = true;
} else if (!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID)) {
mActiveContentChildIDs.RemoveElement(aChildID);
}
}
if (newType != oldType && aType == AUDIO_CHANNEL_CONTENT) {
@ -291,8 +307,12 @@ AudioChannelService::SendAudioChannelChangedNotification()
higher = AUDIO_CHANNEL_NOTIFICATION;
}
// Content channels play in background if just one is active.
else if (!mActiveContentChildIDs.IsEmpty()) {
// There is only one Child can play content channel in the background.
// And need to check whether there is any content channels under playing
// now.
else if (!mActiveContentChildIDs.IsEmpty() &&
mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(
mActiveContentChildIDs[0])) {
higher = AUDIO_CHANNEL_CONTENT;
}
}

View File

@ -1,6 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef XP_WIN
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "TestHarness.h"
@ -19,19 +24,25 @@
using namespace mozilla::dom;
class Agent
class Agent : public nsIAudioChannelAgentCallback
{
public:
NS_DECL_ISUPPORTS
Agent(AudioChannelType aType)
: mType(aType)
, mWaitCallback(false)
, mRegistered(false)
, mCanPlay(false)
{
mAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
}
virtual ~Agent() {}
nsresult Init()
{
nsresult rv = mAgent->Init(mType, nullptr);
nsresult rv = mAgent->Init(mType, this);
NS_ENSURE_SUCCESS(rv, rv);
return mAgent->SetVisibilityState(false);
@ -50,26 +61,74 @@ public:
nsresult StopPlaying()
{
mRegistered = false;
int loop = 0;
while (mWaitCallback) {
#ifdef XP_WIN
Sleep(1000);
#else
sleep(1);
#endif
if (loop++ == 5) {
TEST_ENSURE_BASE(false, "StopPlaying timeout");
}
}
return mAgent->StopPlaying();
}
nsresult SetVisibilityState(bool visible)
{
if (mRegistered) {
mWaitCallback = true;
}
return mAgent->SetVisibilityState(visible);
}
NS_IMETHODIMP CanPlayChanged(bool canPlay)
{
mCanPlay = canPlay;
mWaitCallback = false;
return NS_OK;
}
nsresult GetCanPlay(bool *_ret)
{
int loop = 0;
while (mWaitCallback) {
#ifdef XP_WIN
Sleep(1000);
#else
sleep(1);
#endif
if (loop++ == 5) {
TEST_ENSURE_BASE(false, "GetCanPlay timeout");
}
}
*_ret = mCanPlay;
return NS_OK;
}
nsCOMPtr<AudioChannelAgent> mAgent;
AudioChannelType mType;
bool mWaitCallback;
bool mRegistered;
bool mCanPlay;
};
NS_IMPL_ISUPPORTS1(Agent, nsIAudioChannelAgentCallback)
nsresult
TestDoubleStartPlaying()
{
Agent agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent.Init();
nsCOMPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent->Init();
NS_ENSURE_SUCCESS(rv, rv);
bool playing;
rv = agent.mAgent->StartPlaying(&playing);
rv = agent->mAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent.mAgent->StartPlaying(&playing);
rv = agent->mAgent->StartPlaying(&playing);
TEST_ENSURE_BASE(NS_FAILED(rv), "Test0: StartPlaying calling twice should return error");
return NS_OK;
@ -78,19 +137,19 @@ TestDoubleStartPlaying()
nsresult
TestOneNormalChannel()
{
Agent agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent.Init();
nsCOMPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent->Init();
NS_ENSURE_SUCCESS(rv, rv);
bool playing;
rv = agent.StartPlaying(&playing);
rv = agent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test1: A normal channel unvisible agent must not be playing");
rv = agent.mAgent->SetVisibilityState(true);
rv = agent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent.StartPlaying(&playing);
rv = agent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test1: A normal channel visible agent should be playing");
@ -100,34 +159,34 @@ TestOneNormalChannel()
nsresult
TestTwoNormalChannels()
{
Agent agent1(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent1.Init();
nsCOMPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = agent1->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent agent2(AUDIO_CHANNEL_NORMAL);
rv = agent2.Init();
nsCOMPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_NORMAL);
rv = agent2->Init();
NS_ENSURE_SUCCESS(rv, rv);
bool playing;
rv = agent1.StartPlaying(&playing);
rv = agent1->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test2: A normal channel unvisible agent1 must not be playing");
rv = agent2.StartPlaying(&playing);
rv = agent2->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test2: A normal channel unvisible agent2 must not be playing");
rv = agent1.mAgent->SetVisibilityState(true);
rv = agent1->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2.mAgent->SetVisibilityState(true);
rv = agent2->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1.StartPlaying(&playing);
rv = agent1->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test2: A normal channel visible agent1 should be playing");
rv = agent2.StartPlaying(&playing);
rv = agent2->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test2: A normal channel visible agent2 should be playing");
@ -137,213 +196,230 @@ TestTwoNormalChannels()
nsresult
TestContentChannels()
{
Agent agent1(AUDIO_CHANNEL_CONTENT);
nsresult rv = agent1.Init();
nsCOMPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_CONTENT);
nsresult rv = agent1->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent agent2(AUDIO_CHANNEL_CONTENT);
rv = agent2.Init();
nsCOMPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
rv = agent2->Init();
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1.mAgent->SetVisibilityState(true);
/* All content channels in the foreground can be allowed to play */
rv = agent1->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2.mAgent->SetVisibilityState(true);
rv = agent2->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
bool playing;
rv = agent1.StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel unvisible agent1 should be playing");
rv = agent2.StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel unvisible agent2 should be playing");
rv = agent1.mAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2.mAgent->SetVisibilityState(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1.StartPlaying(&playing);
rv = agent1->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel visible agent1 should be playing");
rv = agent2.StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel unvisible agent2 should be playing");
rv = agent1.mAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2.mAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1.StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel visible agent1 should be playing");
rv = agent2.StartPlaying(&playing);
rv = agent2->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel visible agent2 should be playing");
/* Test the transition state of one content channel tried to set non-visible
* state first when app is going to background. */
rv = agent1->SetVisibilityState(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel unvisible agent1 should be playing from foreground to background");
/* Test all content channels set non-visible already */
rv = agent2->SetVisibilityState(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test3: A content channel unvisible agent2 should be playing from foreground to background");
/* Clear the content channels & mActiveContentChildIDs in AudioChannelService.
* If agent stop playing in the background, we will reserve it's childID in
* mActiveContentChildIDs, then it can allow to play next song. So we set agents
* to foreground first then stopping to play */
rv = agent1->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1->StopPlaying();
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2->StopPlaying();
NS_ENSURE_SUCCESS(rv, rv);
/* Test that content channels can't be allow to play when they starts from the background state */
rv = agent1->SetVisibilityState(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent2->SetVisibilityState(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = agent1->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test3: A content channel unvisible agent1 must not be playing from background state");
rv = agent2->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test3: A content channel unvisible agent2 must not be playing from background state");
return rv;
}
nsresult
TestPriorities()
{
Agent normalAgent(AUDIO_CHANNEL_NORMAL);
nsresult rv = normalAgent.Init();
nsCOMPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
nsresult rv = normalAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent contentAgent(AUDIO_CHANNEL_CONTENT);
rv = contentAgent.Init();
nsCOMPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
rv = contentAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent notificationAgent(AUDIO_CHANNEL_NOTIFICATION);
rv = notificationAgent.Init();
nsCOMPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
rv = notificationAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent alarmAgent(AUDIO_CHANNEL_ALARM);
rv = alarmAgent.Init();
nsCOMPtr<Agent> alarmAgent = new Agent(AUDIO_CHANNEL_ALARM);
rv = alarmAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent telephonyAgent(AUDIO_CHANNEL_TELEPHONY);
rv = telephonyAgent.Init();
nsCOMPtr<Agent> telephonyAgent = new Agent(AUDIO_CHANNEL_TELEPHONY);
rv = telephonyAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent ringerAgent(AUDIO_CHANNEL_RINGER);
rv = ringerAgent.Init();
nsCOMPtr<Agent> ringerAgent = new Agent(AUDIO_CHANNEL_RINGER);
rv = ringerAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
Agent pNotificationAgent(AUDIO_CHANNEL_PUBLICNOTIFICATION);
rv = pNotificationAgent.Init();
nsCOMPtr<Agent> pNotificationAgent = new Agent(AUDIO_CHANNEL_PUBLICNOTIFICATION);
rv = pNotificationAgent->Init();
NS_ENSURE_SUCCESS(rv, rv);
bool playing;
// Normal should not be playing because not visible.
rv = normalAgent.StartPlaying(&playing);
rv = normalAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A normal channel unvisible agent should not be playing");
TEST_ENSURE_BASE(!playing, "Test4: A normal channel unvisible agent must not be playing");
// Content should be playing.
rv = contentAgent.StartPlaying(&playing);
rv = contentAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A content channel unvisible agent should be playing");
TEST_ENSURE_BASE(!playing, "Test4: A content channel unvisible agent must not be playing from background state");
// Notification should be playing.
rv = notificationAgent.StartPlaying(&playing);
rv = notificationAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: An notification channel unvisible agent should be playing");
// Now content should be not playing because of the notification playing.
rv = contentAgent.StartPlaying(&playing);
rv = contentAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A content channel unvisible agent should not be playing when notification channel is playing");
// Adding an alarm.
rv = alarmAgent.StartPlaying(&playing);
rv = alarmAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: An alarm channel unvisible agent should be playing");
// Now notification should be not playing because of the alarm playing.
rv = notificationAgent.StartPlaying(&playing);
rv = notificationAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A notification channel unvisible agent should not be playing when an alarm is playing");
// Adding an telephony.
rv = telephonyAgent.StartPlaying(&playing);
rv = telephonyAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: An telephony channel unvisible agent should be playing");
// Now alarm should be not playing because of the telephony playing.
rv = alarmAgent.StartPlaying(&playing);
rv = alarmAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A alarm channel unvisible agent should not be playing when a telephony is playing");
// Adding an ringer.
rv = ringerAgent.StartPlaying(&playing);
rv = ringerAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: An ringer channel unvisible agent should be playing");
// Now telephony should be not playing because of the ringer playing.
rv = telephonyAgent.StartPlaying(&playing);
rv = telephonyAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A telephony channel unvisible agent should not be playing when a riger is playing");
// Adding an pNotification.
rv = pNotificationAgent.StartPlaying(&playing);
rv = pNotificationAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: An pNotification channel unvisible agent should be playing");
// Now ringer should be not playing because of the public notification playing.
rv = ringerAgent.StartPlaying(&playing);
rv = ringerAgent->StartPlaying(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(!playing, "Test4: A ringer channel unvisible agent should not be playing when a public notification is playing");
// Settings visible the normal channel.
rv = normalAgent.mAgent->SetVisibilityState(true);
rv = normalAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Normal should be playing because visible.
rv = normalAgent.StartPlaying(&playing);
rv = normalAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A normal channel visible agent should be playing");
// Settings visible the content channel.
rv = contentAgent.mAgent->SetVisibilityState(true);
rv = contentAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Content should be playing because visible.
rv = contentAgent.StartPlaying(&playing);
rv = contentAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A content channel visible agent should be playing");
// Settings visible the notification channel.
rv = notificationAgent.mAgent->SetVisibilityState(true);
rv = notificationAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Notification should be playing because visible.
rv = notificationAgent.StartPlaying(&playing);
rv = notificationAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A notification channel visible agent should be playing");
// Settings visible the alarm channel.
rv = alarmAgent.mAgent->SetVisibilityState(true);
rv = alarmAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Alarm should be playing because visible.
rv = alarmAgent.StartPlaying(&playing);
rv = alarmAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A alarm channel visible agent should be playing");
// Settings visible the telephony channel.
rv = telephonyAgent.mAgent->SetVisibilityState(true);
rv = telephonyAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Telephony should be playing because visible.
rv = telephonyAgent.StartPlaying(&playing);
rv = telephonyAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A telephony channel visible agent should be playing");
// Settings visible the ringer channel.
rv = ringerAgent.mAgent->SetVisibilityState(true);
rv = ringerAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// Ringer should be playing because visible.
rv = ringerAgent.StartPlaying(&playing);
rv = ringerAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A ringer channel visible agent should be playing");
// Settings visible the pNotification channel.
rv = pNotificationAgent.mAgent->SetVisibilityState(true);
rv = pNotificationAgent->SetVisibilityState(true);
NS_ENSURE_SUCCESS(rv, rv);
// pNotification should be playing because visible.
rv = pNotificationAgent.StartPlaying(&playing);
rv = pNotificationAgent->GetCanPlay(&playing);
NS_ENSURE_SUCCESS(rv, rv);
TEST_ENSURE_BASE(playing, "Test4: A pNotification channel visible agent should be playing");

View File

@ -0,0 +1,3 @@
<script>
Components.lookupMethod(Image, "x")
</script>

View File

@ -39,3 +39,4 @@ load 697643.html
load 706283-1.html
load 708405-1.html
load 745495.html
load 844559.html

View File

@ -5,46 +5,53 @@
import os
import cPickle
from Configuration import Configuration
from Codegen import CGBindingRoot, replaceFileIfChanged
from Codegen import CGBindingRoot
def generate_binding_header(config, outputprefix, webidlfile):
def generate_binding_header(config, outputprefix, srcprefix, webidlfile):
"""
|config| Is the configuration object.
|outputprefix| is a prefix to use for the header guards and filename.
"""
filename = outputprefix + ".h"
depsname = ".deps/" + filename + ".pp"
root = CGBindingRoot(config, outputprefix, webidlfile)
if replaceFileIfChanged(filename, root.declare()):
print "Generating binding header: %s" % (filename)
with open(filename, 'wb') as f:
f.write(root.declare())
with open(depsname, 'wb') as f:
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for x in root.deps()))
def generate_binding_cpp(config, outputprefix, webidlfile):
def generate_binding_cpp(config, outputprefix, srcprefix, webidlfile):
"""
|config| Is the configuration object.
|outputprefix| is a prefix to use for the header guards and filename.
"""
filename = outputprefix + ".cpp"
depsname = ".deps/" + filename + ".pp"
root = CGBindingRoot(config, outputprefix, webidlfile)
if replaceFileIfChanged(filename, root.define()):
print "Generating binding implementation: %s" % (filename)
with open(filename, 'wb') as f:
f.write(root.define())
with open(depsname, 'wb') as f:
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for x in root.deps()))
def main():
# Parse arguments.
from optparse import OptionParser
usagestring = "usage: %prog [header|cpp] configFile outputPrefix webIDLFile"
usagestring = "usage: %prog [header|cpp] configFile outputPrefix srcPrefix webIDLFile"
o = OptionParser(usage=usagestring)
o.add_option("--verbose-errors", action='store_true', default=False,
help="When an error happens, display the Python traceback.")
(options, args) = o.parse_args()
if len(args) != 4 or (args[0] != "header" and args[0] != "cpp"):
if len(args) != 5 or (args[0] != "header" and args[0] != "cpp"):
o.error(usagestring)
buildTarget = args[0]
configFile = os.path.normpath(args[1])
outputPrefix = args[2]
webIDLFile = os.path.normpath(args[3])
srcPrefix = os.path.normpath(args[3])
webIDLFile = os.path.normpath(args[4])
# Load the parsing results
f = open('ParserResults.pkl', 'rb')
@ -56,9 +63,9 @@ def main():
# Generate the prototype classes.
if buildTarget == "header":
generate_binding_header(config, outputPrefix, webIDLFile);
generate_binding_header(config, outputPrefix, srcPrefix, webIDLFile);
elif buildTarget == "cpp":
generate_binding_cpp(config, outputPrefix, webIDLFile);
generate_binding_cpp(config, outputPrefix, srcPrefix, webIDLFile);
else:
assert False # not reached

View File

@ -59,6 +59,9 @@ class CGThing():
def define(self):
"""Produce code for a cpp file."""
assert(False) # Override me!
def deps(self):
"""Produce the deps for a pp file"""
assert(False) # Override me!
class CGNativePropertyHooks(CGThing):
"""
@ -309,6 +312,13 @@ class CGList(CGThing):
return self.join(child.declare() for child in self.children if child is not None)
def define(self):
return self.join(child.define() for child in self.children if child is not None)
def deps(self):
deps = set()
for child in self.children:
if child is None:
continue
deps = deps.union(child.deps())
return deps
class CGGeneric(CGThing):
"""
@ -322,6 +332,8 @@ class CGGeneric(CGThing):
return self.declareText
def define(self):
return self.defineText
def deps(self):
return set()
# We'll want to insert the indent at the beginnings of lines, but we
# don't want to indent empty lines. So only indent lines that have a
@ -387,6 +399,9 @@ class CGWrapper(CGThing):
defn.replace("\n", "\n" + (" " * len(self.definePre))))
return self.definePre + defn + self.definePost
def deps(self):
return self.child.deps()
class CGIfWrapper(CGWrapper):
def __init__(self, child, condition):
pre = CGWrapper(CGGeneric(condition), pre="if (", post=") {\n",
@ -985,14 +1000,30 @@ class CGNamedConstructors(CGThing):
def define(self):
if len(self.descriptor.interface.namedConstructors) == 0:
return ""
constructorID = "constructors::id::"
if self.descriptor.interface.hasInterfaceObject():
constructorID += self.descriptor.name
else:
constructorID += "_ID_Count"
nativePropertyHooks = """const NativePropertyHooks sNamedConstructorNativePropertyHooks = {
nullptr,
nullptr,
{ nullptr, nullptr },
prototypes::id::%s,
%s,
nullptr
};
""" % (self.descriptor.name, constructorID)
namedConstructors = CGList([], ",\n")
for n in self.descriptor.interface.namedConstructors:
namedConstructors.append(CGGeneric("{ \"%s\", { %s, nullptr }, %i }" % (n.identifier.name, NamedConstructorName(n), methodLength(n))))
namedConstructors.append(CGGeneric("{ \"%s\", { %s, &sNamedConstructorNativePropertyHooks }, %i }" % (n.identifier.name, NamedConstructorName(n), methodLength(n))))
namedConstructors.append(CGGeneric("{ nullptr, { nullptr, nullptr }, 0 }"))
namedConstructors = CGWrapper(CGIndenter(namedConstructors),
pre="static const NamedConstructor namedConstructors[] = {\n",
post="\n};\n")
return namedConstructors.define()
return nativePropertyHooks + namedConstructors.define()
class CGClassHasInstanceHook(CGAbstractStaticMethod):
def __init__(self, descriptor):
@ -4853,6 +4884,9 @@ class CGEnum(CGThing):
""" % (len(self.enum.values()) + 1,
",\n ".join(['{"' + val + '", ' + str(len(val)) + '}' for val in self.enum.values()]))
def deps(self):
return self.enum.getDeps()
def getUnionAccessorSignatureType(type, descriptorProvider):
"""
Returns the types that are used in the getter and setter signatures for
@ -5743,6 +5777,8 @@ class CGPrototypeTraitsClass(CGClass):
templateArgs=templateArgs,
templateSpecialization=templateSpecialization,
enums=enums, typedefs=typedefs, isStruct=True)
def deps(self):
return set()
class CGPrototypeIDMapClass(CGClass):
def __init__(self, descriptor, indent=''):
@ -5754,6 +5790,8 @@ class CGPrototypeIDMapClass(CGClass):
templateArgs=templateArgs,
templateSpecialization=templateSpecialization,
enums=enums, isStruct=True)
def deps(self):
return set()
class CGClassForwardDeclare(CGThing):
def __init__(self, name, isStruct=False):
@ -5766,6 +5804,8 @@ class CGClassForwardDeclare(CGThing):
def define(self):
# Header only
return ''
def deps(self):
return set()
class CGProxySpecialOperation(CGPerSignatureCall):
"""
@ -6442,6 +6482,8 @@ class CGDescriptor(CGThing):
assert not descriptor.concrete or descriptor.interface.hasInterfacePrototypeObject()
self._deps = descriptor.interface.getDeps()
cgThings = []
# These are set to true if at least one non-static
# method/getter/setter exist on the interface.
@ -6578,6 +6620,8 @@ class CGDescriptor(CGThing):
return self.cgRoot.declare()
def define(self):
return self.cgRoot.define()
def deps(self):
return self._deps
class CGNamespacedEnum(CGThing):
def __init__(self, namespace, enumName, names, values, comment=""):
@ -6782,6 +6826,9 @@ class CGDictionary(CGThing):
"defineMembers": "\n\n".join(memberDefines)
})
def deps(self):
return self.dictionary.getDeps()
@staticmethod
def makeDictionaryName(dictionary, workers):
suffix = "Workers" if workers else ""
@ -7203,6 +7250,9 @@ class CGBindingRoot(CGThing):
def define(self):
return stripTrailingWhitespace(self.root.define())
def deps(self):
return self.root.deps()
class CGNativeMember(ClassMethod):
def __init__(self, descriptor, member, name, signature, extendedAttrs,
breakAfter=True, passCxAsNeeded=True, visibility="public",
@ -7778,6 +7828,7 @@ class CGCallback(CGClass):
def __init__(self, idlObject, descriptorProvider, baseName, methods,
getters=[], setters=[]):
self.baseName = baseName
self._deps = idlObject.getDeps()
name = idlObject.identifier.name
if descriptorProvider.workers:
name += "Workers"
@ -7867,6 +7918,9 @@ class CGCallback(CGClass):
body=bodyWithoutThis),
method]
def deps(self):
return self._deps
class CGCallbackFunction(CGCallback):
def __init__(self, callback, descriptorProvider):
CGCallback.__init__(self, callback, descriptorProvider,

View File

@ -65,12 +65,14 @@ class Configuration:
# Figure out what our main-thread and worker dictionaries and callbacks
# are.
mainTypes = set()
for descriptor in self.getDescriptors(workers=False, isExternal=False):
for descriptor in ([self.getDescriptor("DummyInterface", workers=False)] +
self.getDescriptors(workers=False, isExternal=False, skipGen=False)):
mainTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
(mainCallbacks, mainDictionaries) = findCallbacksAndDictionaries(mainTypes)
workerTypes = set();
for descriptor in self.getDescriptors(workers=True, isExternal=False):
for descriptor in ([self.getDescriptor("DummyInterfaceWorkers", workers=True)] +
self.getDescriptors(workers=True, isExternal=False, skipGen=False)):
workerTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
(workerCallbacks, workerDictionaries) = findCallbacksAndDictionaries(workerTypes)

View File

@ -75,7 +75,6 @@ EXPORTS_$(binding_include_path) = \
TypedArray.h \
UnionConversions.h \
UnionTypes.h \
$(exported_binding_headers) \
$(NULL)
LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
@ -97,8 +96,34 @@ LOCAL_INCLUDES += \
$(NULL)
endif
# XXXkhuey this is a terrible hack to avoid blowing out the command line
ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
$(shell echo "$(addsuffix .pp,$(binding_header_files))" > pp.list)
$(shell echo "$(addsuffix .pp,$(binding_cpp_files))" >> pp.list)
# The script mddepend.pl checks the dependencies and writes to stdout
# one rule to force out-of-date objects. For example,
# foo.o boo.o: FORCE
# The script has an advantage over including the *.pp files directly
# because it handles the case when header files are removed from the build.
# 'make' would complain that there is no way to build missing headers.
ALL_PP_RESULTS = $(shell cat pp.list | $(PERL) $(BUILD_TOOLS)/mddepend.pl)
$(eval $(ALL_PP_RESULTS))
endif
EXPORTS_GENERATED_FILES := $(exported_binding_headers)
EXPORTS_GENERATED_DEST := $(DIST)/include/$(binding_include_path)
EXPORTS_GENERATED_TARGET := webidl-export
INSTALL_TARGETS += EXPORTS_GENERATED
include $(topsrcdir)/config/rules.mk
# We need to create a separate target so we can ensure that the pickle is
# done before generating headers.
export:: ParserResults.pkl
$(MAKE) webidl-export
# If you change bindinggen_dependencies here, change it in
# dom/bindings/test/Makefile.in too.
bindinggen_dependencies := \
@ -107,7 +132,6 @@ bindinggen_dependencies := \
Configuration.py \
Codegen.py \
parser/WebIDL.py \
ParserResults.pkl \
$(GLOBAL_DEPS) \
$(NULL)
@ -129,20 +153,26 @@ $(test_webidl_files): %: $(srcdir)/test/%
$(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
%.webidl \
$(call mkdir_deps,$(MDDEPDIR)) \
$(NULL)
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) -I$(srcdir)/parser \
$(srcdir)/BindingGen.py header \
$(srcdir)/Bindings.conf $*Binding \
$(srcdir)/Bindings.conf \
$*Binding \
$(topsrcdir)/dom/webidl/ \
$*.webidl
$(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \
%.webidl \
$(call mkdir_deps,$(MDDEPDIR)) \
$(NULL)
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) -I$(srcdir)/parser \
$(srcdir)/BindingGen.py cpp \
$(srcdir)/Bindings.conf $*Binding \
$(srcdir)/Bindings.conf \
$*Binding \
$(topsrcdir)/dom/webidl/ \
$*.webidl
$(globalgen_targets): ParserResults.pkl
@ -195,4 +225,6 @@ GARBAGE += \
# don't have issues with .cpp files being compiled before we've generated the
# headers they depend on. This is really only needed for the test files, since
# the non-test headers are all exported above anyway.
export:: $(binding_header_files)
webidl-export:: $(binding_header_files)
.PHONY: webidl-export

View File

@ -174,6 +174,38 @@ class IDLObject(object):
def handleExtendedAttribute(self, attr):
assert False # Override me!
def _getDependentObjects(self):
assert False # Override me!
def getDeps(self, visited=None):
""" Return a set of files that this object depends on. If any of
these files are changed the parser needs to be rerun to regenerate
a new IDLObject.
The visited argument is a set of all the objects already visited.
We must test to see if we are in it, and if so, do nothing. This
prevents infinite recursion."""
# NB: We can't use visited=set() above because the default value is
# evaluated when the def statement is evaluated, not when the function
# is executed, so there would be one set for all invocations.
if visited == None:
visited = set()
if self in visited:
return set()
visited.add(self)
deps = set()
if self.filename() != "<builtin>":
deps.add(self.filename())
for d in self._getDependentObjects():
deps = deps.union(d.getDeps(visited))
return deps
class IDLScope(IDLObject):
def __init__(self, location, parentScope, identifier):
IDLObject.__init__(self, location)
@ -443,6 +475,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier):
def resolve(self, parentScope):
pass
def _getDependentObjects(self):
return set()
class IDLInterface(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members,
isPartial):
@ -916,6 +951,13 @@ class IDLInterface(IDLObjectWithScope):
# Put the new members at the beginning
self.members = members + self.members
def _getDependentObjects(self):
deps = set(self.members)
deps.union(self.implementedInterfaces)
if self.parent:
deps.add(self.parent)
return deps
class IDLDictionary(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members):
assert isinstance(parentScope, IDLScope)
@ -986,6 +1028,11 @@ class IDLDictionary(IDLObjectWithScope):
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
def _getDependentObjects(self):
deps = set(self.members)
if (self.parent):
deps.add(self.parent)
return deps
class IDLEnum(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, name, values):
@ -1014,6 +1061,9 @@ class IDLEnum(IDLObjectWithIdentifier):
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
def _getDependentObjects(self):
return set()
class IDLType(IDLObject):
Tags = enum(
# The integer types
@ -1303,6 +1353,9 @@ class IDLNullableType(IDLType):
return False
return self.inner.isDistinguishableFrom(other)
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLSequenceType(IDLType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
@ -1373,6 +1426,9 @@ class IDLSequenceType(IDLType):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isNonCallbackInterface())
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLUnionType(IDLType):
def __init__(self, location, memberTypes):
IDLType.__init__(self, location, "")
@ -1476,6 +1532,9 @@ class IDLUnionType(IDLType):
return False
return True
def _getDependentObjects(self):
return set(self.memberTypes)
class IDLArrayType(IDLType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
@ -1551,6 +1610,9 @@ class IDLArrayType(IDLType):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isNonCallbackInterface())
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def __init__(self, location, innerType, name):
IDLType.__init__(self, location, innerType.name)
@ -1638,6 +1700,9 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def isDistinguishableFrom(self, other):
return self.inner.isDistinguishableFrom(other)
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLWrapperType(IDLType):
def __init__(self, location, inner):
IDLType.__init__(self, location, inner.identifier.name)
@ -1741,6 +1806,23 @@ class IDLWrapperType(IDLType):
assert other.isObject()
return False
def _getDependentObjects(self):
# NB: The codegen for an interface type depends on
# a) That the identifier is in fact an interface (as opposed to
# a dictionary or something else).
# b) The native type of the interface.
# If we depend on the interface object we will also depend on
# anything the interface depends on which is undesirable. We
# considered implementing a dependency just on the interface type
# file, but then every modification to an interface would cause this
# to be regenerated which is still undesirable. We decided not to
# depend on anything, reasoning that:
# 1) Changing the concrete type of the interface requires modifying
# Bindings.conf, which is still a global dependency.
# 2) Changing an interface to a dictionary (or vice versa) with the
# same identifier should be incredibly rare.
return set()
class IDLBuiltinType(IDLType):
Types = enum(
@ -1906,6 +1988,9 @@ class IDLBuiltinType(IDLType):
(self.isTypedArray() and not other.isArrayBufferView() and not
(other.isTypedArray() and other.name == self.name)))))
def _getDependentObjects(self):
return set()
BuiltinTypes = {
IDLBuiltinType.Types.byte:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
@ -2064,6 +2149,9 @@ class IDLValue(IDLObject):
raise WebIDLError("Cannot coerce type %s to type %s." %
(self.type, type), [location])
def _getDependentObjects(self):
return set()
class IDLNullValue(IDLObject):
def __init__(self, location):
IDLObject.__init__(self, location)
@ -2081,7 +2169,10 @@ class IDLNullValue(IDLObject):
nullValue = IDLNullValue(self.location)
nullValue.type = type
return nullValue
def _getDependentObjects(self):
return set()
class IDLInterfaceMember(IDLObjectWithIdentifier):
@ -2162,6 +2253,9 @@ class IDLConst(IDLInterfaceMember):
def validate(self):
pass
def _getDependentObjects(self):
return set([self.type, self.value])
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit=False,
static=False, stringifier=False):
@ -2307,6 +2401,9 @@ class IDLAttribute(IDLInterfaceMember):
def isUnforgeable(self):
return self._unforgeable
def _getDependentObjects(self):
return set([self.type])
class IDLArgument(IDLObjectWithIdentifier):
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
@ -2379,6 +2476,12 @@ class IDLArgument(IDLObjectWithIdentifier):
self.location)
assert self.defaultValue
def _getDependentObjects(self):
deps = set([self.type])
if self.defaultValue:
deps.add(self.defaultValue)
return deps
class IDLCallbackType(IDLType, IDLObjectWithScope):
def __init__(self, location, parentScope, identifier, returnType, arguments):
assert isinstance(returnType, IDLType)
@ -2446,6 +2549,9 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
if len(unhandledAttrs) != 0:
IDLType.addExtendedAttributes(self, unhandledAttrs)
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)
class IDLMethodOverload:
"""
A class that represents a single overload of a WebIDL method. This is not
@ -2461,6 +2567,11 @@ class IDLMethodOverload:
self.arguments = list(arguments)
self.location = location
def _getDependentObjects(self):
deps = set(self.arguments)
deps.add(self.returnType)
return deps
class IDLMethod(IDLInterfaceMember, IDLScope):
Special = enum(
@ -2808,6 +2919,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
[attr.location, self.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
def _getDependentObjects(self):
deps = set()
for overload in self._overloads:
deps.union(overload._getDependentObjects())
return deps
class IDLImplementsStatement(IDLObject):
def __init__(self, location, implementor, implementee):
IDLObject.__init__(self, location)

View File

@ -90,7 +90,7 @@ def checkEquivalent(iface, harness):
for attr in dir(type1):
if attr.startswith('_') or \
attr in ['nullable', 'builtin', 'filename', 'location',
'inner', 'QName'] or \
'inner', 'QName', 'getDeps'] or \
(hasattr(type(type1), attr) and not callable(getattr(type1, attr))):
continue

View File

@ -44,7 +44,6 @@ bindinggen_dependencies := \
../Configuration.py \
../Codegen.py \
../parser/WebIDL.py \
../ParserResults.pkl \
../Makefile \
$(GLOBAL_DEPS) \
$(NULL)

View File

@ -13,7 +13,7 @@
#endif
#include "BrowserElementParent.h"
#include "nsHTMLIFrameElement.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "nsOpenWindowEventDetail.h"
#include "nsEventDispatcher.h"
#include "nsIDOMCustomEvent.h"
@ -22,6 +22,7 @@
#include "nsAsyncScrollEventDetail.h"
using mozilla::dom::Element;
using mozilla::dom::HTMLIFrameElement;
using mozilla::dom::TabParent;
namespace {
@ -30,7 +31,7 @@ namespace {
* Create an <iframe mozbrowser> owned by the same document as
* aOpenerFrameElement.
*/
already_AddRefed<nsHTMLIFrameElement>
already_AddRefed<HTMLIFrameElement>
CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
{
nsNodeInfoManager *nodeInfoManager =
@ -42,8 +43,8 @@ CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
static_cast<nsHTMLIFrameElement*>(
nsRefPtr<HTMLIFrameElement> popupFrameElement =
static_cast<HTMLIFrameElement*>(
NS_NewHTMLIFrameElement(nodeInfo.forget(), mozilla::dom::NOT_FROM_PARSER));
popupFrameElement->SetMozbrowser(true);
@ -151,7 +152,7 @@ BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent,
nsCOMPtr<Element> openerFrameElement =
do_QueryInterface(aOpenerTabParent->GetOwnerElement());
NS_ENSURE_TRUE(openerFrameElement, false);
nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
nsRefPtr<HTMLIFrameElement> popupFrameElement =
CreateIframe(openerFrameElement, aName, /* aRemote = */ true);
// Normally an <iframe> element will try to create a frameLoader when the
@ -209,7 +210,7 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
nsCOMPtr<Element> openerFrameElement =
do_QueryInterface(openerFrameDOMElement);
nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
nsRefPtr<HTMLIFrameElement> popupFrameElement =
CreateIframe(openerFrameElement, aName, /* aRemote = */ false);
NS_ENSURE_TRUE(popupFrameElement, false);

View File

@ -8,7 +8,7 @@ SimpleTest.waitForExplicitFinish();
function makeAllAppsLaunchable() {
var Webapps = {};
SpecialPowers.wrap(Components).utils.import("resource://gre/modules/Webapps.jsm", Webapps);
SpecialPowers.Cu.import("resource://gre/modules/Webapps.jsm", Webapps);
var appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
var originalValue = appRegistry.allAppsLaunchable;

View File

@ -54,7 +54,7 @@ function getRandomView(size)
function getBlob(type, view)
{
return utils.getBlob([view], {type: type});
return SpecialPowers.unwrap(utils.getBlob([view], {type: type}));
}
function getRandomBlob(size)

View File

@ -179,7 +179,7 @@ function compareBuffers(buffer1, buffer2)
function getBlob(type, buffer)
{
return utils.getBlob([buffer], {type: type});
return SpecialPowers.unwrap(utils.getBlob([buffer], {type: type}));
}
function getRandomBlob(size)
@ -189,5 +189,5 @@ function getRandomBlob(size)
function getFileId(blob)
{
return utils.getFileId(blob);
return SpecialPowers.unwrap(utils.getFileId(blob));
}

View File

@ -11,8 +11,8 @@
<script type="text/javascript;version=1.7">
function createNonUnicodeData() {
const Cc = SpecialPowers.wrap(Components).classes;
const Ci = SpecialPowers.wrap(Components).interfaces;
const Cc = SpecialPowers.Cc;
const Ci = SpecialPowers.Ci;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);

View File

@ -49,12 +49,12 @@ function compareBuffers(buffer1, buffer2)
function getBlob(type, view)
{
return utils.getBlob([view], {type: type});
return SpecialPowers.unwrap(utils.getBlob([view], {type: type}));
}
function getFile(name, type, view)
{
return utils.getFile(name, [view], {type: type});
return SpecialPowers.unwrap(utils.getFile(name, [view], {type: type}));
}
function getRandomBlob(size)

View File

@ -10,7 +10,7 @@ var archiveReaderEnabled = false;
// and content mochitests (where the |Components| object is accessible only as
// SpecialPowers.Components). Expose Components if necessary here to make things
// work everywhere.
if (typeof Components === 'undefined')
if (typeof Components === 'undefined' && typeof SpecialPowers === 'object')
Components = SpecialPowers.Components;
function executeSoon(aFun)

View File

@ -84,6 +84,7 @@ RemovedFullScreenElement=Exited full-screen because full-screen element was remo
FocusedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was focused.
HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
MultipartXHRWarning=Support for multipart responses in XMLHttpRequest is going to be removed in an upcoming version. Please migrate to chunked responses or to Web Sockets.
InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
ReportOnlyCSPIgnored=Report-only CSP policy will be ignored because there are other non-report-only CSP policies applied.
ResponseTypeSyncXHRWarning=Use of XMLHttpRequest's responseType attribute is no longer supported in the synchronous mode in window context.

View File

@ -4,7 +4,8 @@
ChildCountIncorrect=Invalid markup: Incorrect number of children for <%1$S/> tag.
DuplicateMprescripts=Invalid markup: More than one <mprescripts/> in <mmultiscripts/>.
NoSubSup=Invalid markup: Expected at least one subscript/superscript pair in <mmultiscripts/>. Found none.
# LOCALIZATION NOTE: The first child of <mmultiscript/> is the base, that is the element to which scripts are attached.
NoBase=Invalid markup: Expected exactly one Base element in <mmultiscripts/>. Found none.
SubSupMismatch=Invalid markup: Incomplete subscript/superscript pair in <mmultiscripts/>.
# LOCALIZATION NOTE: When localizing the single quotes ('), follow the conventions in css.properties for your target locale.

View File

@ -912,7 +912,7 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
uint32_t permission;
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
pm->TestPermission(doc->NodePrincipal(), &permission);
if ((permission == nsIPopupWindowManager::DENY_POPUP)) {
if (permission == nsIPopupWindowManager::DENY_POPUP) {
nsCOMPtr<nsIDOMDocument> domDoc = aWindow->GetExtantDocument();
nsGlobalWindow::FirePopupBlockedEvent(
domDoc, aWindow, nullptr, EmptyString(), EmptyString()

View File

@ -2,30 +2,42 @@
* 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 "domstubs.idl"
#include "nsISupports.idl"
#include "nsIMobileMessageDatabaseService.idl"
interface nsIDOMMozSmsMessage;
[scriptable, function, uuid(9cd80750-6a08-11e2-ac93-bf895e53f40e)]
[scriptable, function, uuid(0bffae74-71db-11e2-962a-73cf64d6393e)]
interface nsIRilMobileMessageDatabaseCallback : nsISupports
{
void notify(in nsresult aRv, in nsIDOMMozSmsMessage aSms);
/**
* |aRecord| Object: the mobile-message database record
*/
void notify(in nsresult aRv, in jsval aRecord);
};
[scriptable, uuid(89528354-6a08-11e2-8243-af4cf90404a9)]
[scriptable, uuid(3592525a-71d6-11e2-82ca-f75ae6e08ee2)]
interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
{
long saveReceivedMessage(in DOMString aSender,
in DOMString aBody,
in DOMString aMessageClass,
in unsigned long long aDate,
/**
* |aMessage| Object: should contain the following properties for internal use:
* - |type| DOMString: "sms" or "mms"
* - |sender| DOMString: the phone number of sender
* - |timestamp| Number: the timestamp of received message
* - |messageClass| DOMString: the message class of received message
*/
long saveReceivedMessage(in jsval aMessage,
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
long saveSendingMessage(in DOMString aReceiver,
in DOMString aBody,
in DOMString aDeliveryStatus,
in unsigned long long aDate,
/**
* |aMessage| Object: should contain the following properties for internal use:
* - |type| DOMString: "sms" or "mms"
* - |receiver| DOMString: the phone number of receiver
* - |timestamp| Number: the timestamp of sending message
* - |deliveryStatus| DOMString: the delivery status of sending message
*/
long saveSendingMessage(in jsval aMessage,
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
void setMessageDelivery(in long aMessageId,
in DOMString aDelivery,
in DOMString aDeliveryStatus,

View File

@ -413,8 +413,8 @@ MobileMessageDatabaseService.prototype = {
};
},
createMessageFromRecord: function createMessageFromRecord(aRecord) {
if (DEBUG) debug("createMessageFromRecord: " + JSON.stringify(aRecord));
createSmsMessageFromRecord: function createSmsMessageFromRecord(aRecord) {
if (DEBUG) debug("createSmsMessageFromRecord: " + JSON.stringify(aRecord));
return gSmsService.createSmsMessage(aRecord.id,
aRecord.delivery,
aRecord.deliveryStatus,
@ -482,7 +482,7 @@ MobileMessageDatabaseService.prototype = {
let getRequest = aObjectStore.get(firstMessageId);
let self = this;
getRequest.onsuccess = function onsuccess(event) {
let sms = self.createMessageFromRecord(event.target.result);
let sms = self.createSmsMessageFromRecord(event.target.result);
if (aMessageList.listId >= 0) {
if (DEBUG) {
debug("notifyNextMessageInListGot - listId: "
@ -657,8 +657,7 @@ MobileMessageDatabaseService.prototype = {
if (!aCallback) {
return;
}
let sms = self.createMessageFromRecord(aRecord);
aCallback.notify(rv, sms);
aCallback.notify(rv, aRecord);
}
this.newTxn(READ_WRITE, function(error, txn, stores) {
@ -678,9 +677,8 @@ MobileMessageDatabaseService.prototype = {
// First add to main objectStore.
stores[0].put(aRecord);
let number = getNumberFromRecord(aRecord);
// Next update the other objectStore.
let number = getNumberFromRecord(aRecord);
stores[1].get(number).onsuccess = function onsuccess(event) {
let mostRecentEntry = event.target.result;
if (mostRecentEntry) {
@ -713,100 +711,96 @@ MobileMessageDatabaseService.prototype = {
return aRecord.id;
},
getRilIccInfoMsisdn: function getRilIccInfoMsisdn() {
let iccInfo = this.mRIL.rilContext.iccInfo;
let number = iccInfo ? iccInfo.msisdn : null;
// Workaround an xpconnect issue with undefined string objects.
// See bug 808220
if (number === undefined || number === "undefined") {
return null;
}
return number;
},
makePhoneNumberInternational: function makePhoneNumberInternational(aNumber) {
if (!aNumber) {
return aNumber;
}
let parsedNumber = PhoneNumberUtils.parse(aNumber.toString());
if (!parsedNumber || !parsedNumber.internationalNumber) {
return aNumber;
}
return parsedNumber.internationalNumber;
},
/**
* nsIRilMobileMessageDatabaseService API
*/
saveReceivedMessage: function saveReceivedMessage(
aSender, aBody, aMessageClass, aDate, aCallback) {
let iccInfo = this.mRIL.rilContext.iccInfo;
let receiver = iccInfo ? iccInfo.msisdn : null;
// Workaround an xpconnect issue with undefined string objects.
// See bug 808220
if (receiver === undefined || receiver === "undefined") {
receiver = null;
saveReceivedMessage: function saveReceivedMessage(aMessage, aCallback) {
if (aMessage.type === undefined ||
aMessage.sender === undefined ||
aMessage.messageClass === undefined ||
aMessage.timestamp === undefined) {
if (aCallback) {
aCallback.notify(Cr.NS_ERROR_FAILURE, null);
}
return;
}
if (receiver) {
let parsedNumber = PhoneNumberUtils.parse(receiver);
receiver = (parsedNumber && parsedNumber.internationalNumber)
? parsedNumber.internationalNumber
: receiver;
}
let receiver = this.getRilIccInfoMsisdn();
receiver = this.makePhoneNumberInternational(receiver);
let sender = aSender;
if (sender) {
let parsedNumber = PhoneNumberUtils.parse(sender);
sender = (parsedNumber && parsedNumber.internationalNumber)
? parsedNumber.internationalNumber
: sender;
}
let sender = aMessage.sender =
this.makePhoneNumberInternational(aMessage.sender);
let record = {
deliveryIndex: [DELIVERY_RECEIVED, aDate],
numberIndex: [[sender, aDate], [receiver, aDate]],
readIndex: [FILTER_READ_UNREAD, aDate],
let timestamp = aMessage.timestamp;
delivery: DELIVERY_RECEIVED,
deliveryStatus: DELIVERY_STATUS_SUCCESS,
sender: sender,
receiver: receiver,
body: aBody,
messageClass: aMessageClass,
timestamp: aDate,
read: FILTER_READ_UNREAD
};
return this.saveRecord(record, aCallback);
// Adding needed indexes and extra attributes for internal use.
aMessage.deliveryIndex = [DELIVERY_RECEIVED, timestamp];
aMessage.numberIndex = [[sender, timestamp], [receiver, timestamp]];
aMessage.readIndex = [FILTER_READ_UNREAD, timestamp];
aMessage.delivery = DELIVERY_RECEIVED;
aMessage.deliveryStatus = DELIVERY_STATUS_SUCCESS;
aMessage.receiver = receiver;
aMessage.read = FILTER_READ_UNREAD;
return this.saveRecord(aMessage, aCallback);
},
saveSendingMessage: function saveSendingMessage(
aReceiver, aBody, aDeliveryStatus, aDate, aCallback) {
saveSendingMessage: function saveSendingMessage(aMessage, aCallback) {
if (aMessage.type === undefined ||
aMessage.receiver === undefined ||
aMessage.deliveryStatus === undefined ||
aMessage.timestamp === undefined) {
if (aCallback) {
aCallback.notify(Cr.NS_ERROR_FAILURE, null);
}
return;
}
let sender = this.getRilIccInfoMsisdn();
let receiver = aMessage.receiver;
let rilContext = this.mRIL.rilContext;
let sender = rilContext.iccInfo
? rilContext.iccInfo.msisdn
: null;
// Workaround an xpconnect issue with undefined string objects.
// See bug 808220
if (sender === undefined || sender === "undefined") {
sender = null;
}
let receiver = aReceiver;
if (rilContext.voice.network.mcc === rilContext.iccInfo.mcc) {
if (receiver) {
let parsedNumber = PhoneNumberUtils.parse(receiver.toString());
receiver = (parsedNumber && parsedNumber.internationalNumber)
? parsedNumber.internationalNumber
: receiver;
}
if (sender) {
let parsedNumber = PhoneNumberUtils.parse(sender.toString());
sender = (parsedNumber && parsedNumber.internationalNumber)
? parsedNumber.internationalNumber
: sender;
}
receiver = aMessage.receiver = this.makePhoneNumberInternational(receiver);
sender = this.makePhoneNumberInternational(sender);
}
let record = {
deliveryIndex: [DELIVERY_SENDING, aDate],
numberIndex: [[sender, aDate], [receiver, aDate]],
readIndex: [FILTER_READ_READ, aDate],
let timestamp = aMessage.timestamp;
delivery: DELIVERY_SENDING,
deliveryStatus: aDeliveryStatus,
sender: sender,
receiver: receiver,
body: aBody,
messageClass: MESSAGE_CLASS_NORMAL,
timestamp: aDate,
read: FILTER_READ_READ
};
return this.saveRecord(record, aCallback);
// Adding needed indexes and extra attributes for internal use.
aMessage.deliveryIndex = [DELIVERY_SENDING, timestamp];
aMessage.numberIndex = [[sender, timestamp], [receiver, timestamp]];
aMessage.readIndex = [FILTER_READ_READ, timestamp];
aMessage.delivery = DELIVERY_SENDING;
aMessage.sender = sender;
aMessage.messageClass = MESSAGE_CLASS_NORMAL;
aMessage.read = FILTER_READ_READ;
return this.saveRecord(aMessage, aCallback);
},
setMessageDelivery: function setMessageDelivery(
@ -822,11 +816,7 @@ MobileMessageDatabaseService.prototype = {
if (!callback) {
return;
}
let sms = null;
if (record) {
sms = self.createMessageFromRecord(record);
}
callback.notify(rv, sms);
callback.notify(rv, record);
}
this.newTxn(READ_WRITE, function (error, txn, store) {
@ -914,7 +904,7 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyGetMessageFailed(Ci.nsISmsRequest.UNKNOWN_ERROR);
return;
}
let sms = self.createMessageFromRecord(record);
let sms = self.createSmsMessageFromRecord(record);
aRequest.notifyMessageGot(sms);
};
@ -1220,7 +1210,7 @@ MobileMessageDatabaseService.prototype = {
// For all numbers.
processing: filter.numbers.length,
results: []
}];
}];
let timeRange = null;
if (filter.startDate != null && filter.endDate != null) {
@ -1327,7 +1317,7 @@ MobileMessageDatabaseService.prototype = {
if (DEBUG) debug("Could not get message id " + messageId);
aRequest.notifyReadMessageListFailed(Ci.nsISmsRequest.NOT_FOUND_ERROR);
}
let sms = self.createMessageFromRecord(record);
let sms = self.createSmsMessageFromRecord(record);
aRequest.notifyNextMessageInListGot(sms);
};

View File

@ -30,13 +30,12 @@ var testCertApp = {
};
SpecialPowers.addPermission("permissions", true, document);
var comp = SpecialPowers.wrap(Components);
SpecialPowers.pushPrefEnv({ "set": [["dom.mozPermissionSettings.enabled", true]] },
function() {
SpecialPowers.removePermission("permissions", document);
});
comp.utils.import("resource://gre/modules/PermissionSettings.jsm");
SpecialPowers.Cu.import("resource://gre/modules/PermissionSettings.jsm");
var mozPermissions = window.navigator.mozPermissionSettings;
function permissionTest() {

View File

@ -21,8 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={678695}
"use strict";
var comp = SpecialPowers.wrap(Components);
comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
SpecialPowers.Cu.import("resource://gre/modules/SettingsChangeNotifier.jsm");
SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
SpecialPowers.addPermission("settings-write", true, document);
SpecialPowers.addPermission("settings-read", true, document);

View File

@ -177,21 +177,27 @@ function newRandomId() {
let sms = [
{
type: "sms",
sender: "+34666000000",
receiver: "+34666111000",
body: "message 0",
messageClass: "normal",
timestamp: 1329999861762
},
{
type: "sms",
sender: "+34666000111",
receiver: "+34666111111",
body: "message 1",
messageClass: "normal",
timestamp: 1329999861763
},
{
type: "sms",
sender: "+34666000222",
receiver: "+34666111222",
body: "message 2",
messageClass: "normal",
timestamp: 1329999861764
},
];
@ -201,9 +207,7 @@ let sms = [
*/
add_test(function test_saveReceivedMessage() {
info("test_saveReceivedMessage");
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0].sender,
sms[0].body,
sms[0].timestamp);
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]);
checkDB(function (store) {
let request = store.get(messageId);
request.onsuccess = function onsuccess() {
@ -262,9 +266,7 @@ add_test(function test_getMessage_success() {
run_next_test();
}
});
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2].sender,
sms[2].body,
sms[2].timestamp);
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]);
SimpleTest.executeSoon(function () {
gMobileMessageDatabaseService.getMessage(messageId, fakeRequestId);
});
@ -821,9 +823,7 @@ add_test(function test_deleteMessage_success() {
run_next_test();
}
});
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0].sender,
sms[0].body,
sms[0].timestamp);
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]);
SimpleTest.executeSoon(function () {
gMobileMessageDatabaseService.deleteMessage(messageId, fakeRequestId);
});
@ -852,9 +852,7 @@ add_test(function test_markMessageRead_success() {
run_next_test();
}
});
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2].sender,
sms[2].body,
sms[2].timestamp);
let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]);
SimpleTest.executeSoon(function () {
gMobileMessageDatabaseService.markMessageRead(messageId, true, fakeRequestId);
});

View File

@ -1476,6 +1476,18 @@ RadioInterfaceLayer.prototype = {
0, options);
},
createSmsMessageFromRecord: function createSmsMessageFromRecord(aRecord) {
return gSmsService.createSmsMessage(aRecord.id,
aRecord.delivery,
aRecord.deliveryStatus,
aRecord.sender,
aRecord.receiver,
aRecord.body,
aRecord.messageClass,
aRecord.timestamp,
aRecord.read);
},
portAddressedSmsApps: null,
handleSmsReceived: function handleSmsReceived(message) {
debug("handleSmsReceived: " + JSON.stringify(message));
@ -1501,6 +1513,11 @@ RadioInterfaceLayer.prototype = {
return true;
}
message.type = "sms";
message.sender = message.sender || null;
message.receiver = message.receiver || null;
message.body = message.fullBody = message.fullBody || null;
// TODO: Bug #768441
// For now we don't store indicators persistently. When the mwi.discard
// flag is false, we'll need to persist the indicator to EFmwis.
@ -1508,13 +1525,14 @@ RadioInterfaceLayer.prototype = {
let mwi = message.mwi;
if (mwi) {
mwi.returnNumber = message.sender || null;
mwi.returnMessage = message.fullBody || null;
mwi.returnNumber = message.sender;
mwi.returnMessage = message.fullBody;
this._sendTargetMessage("voicemail", "RIL:VoicemailNotification", mwi);
return true;
}
let notifyReceived = function notifyReceived(rv, sms) {
let notifyReceived = function notifyReceived(rv, record) {
let sms = this.createSmsMessageFromRecord(record);
let success = Components.isSuccessCode(rv);
// Acknowledge the reception of the SMS.
@ -1532,38 +1550,30 @@ RadioInterfaceLayer.prototype = {
}
gSystemMessenger.broadcastMessage("sms-received", {
id: message.id,
delivery: DOM_SMS_DELIVERY_RECEIVED,
deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
sender: message.sender || null,
receiver: message.receiver || null,
body: message.fullBody || null,
messageClass: message.messageClass,
timestamp: message.timestamp,
read: false
id: message.id,
delivery: DOM_SMS_DELIVERY_RECEIVED,
deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
sender: message.sender,
receiver: message.receiver,
body: message.fullBody,
messageClass: message.messageClass,
timestamp: message.timestamp,
read: false
});
Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
}.bind(this);
if (message.messageClass != RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_0]) {
message.id = gMobileMessageDatabaseService.saveReceivedMessage(
message.sender || null,
message.fullBody || null,
message.messageClass,
message.timestamp,
notifyReceived);
message.id = gMobileMessageDatabaseService.saveReceivedMessage(message,
notifyReceived);
} else {
message.id = -1;
let sms = gSmsService.createSmsMessage(message.id,
DOM_SMS_DELIVERY_RECEIVED,
RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
message.sender || null,
message.receiver || null,
message.fullBody || null,
message.messageClass,
message.timestamp,
false);
notifyReceived(Cr.NS_OK, sms);
message.delivery = DOM_SMS_DELIVERY_RECEIVED;
message.deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS;
message.read = false;
notifyReceived(Cr.NS_OK, message);
}
// SMS ACK will be sent in notifyReceived. Return false here.
@ -1596,7 +1606,8 @@ RadioInterfaceLayer.prototype = {
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
DOM_SMS_DELIVERY_SENT,
options.sms.deliveryStatus,
function notifyResult(rv, sms) {
function notifyResult(rv, record) {
let sms = this.createSmsMessageFromRecord(record);
//TODO bug 832140 handle !Components.isSuccessCode(rv)
gSystemMessenger.broadcastMessage("sms-sent",
{id: options.sms.id,
@ -1634,13 +1645,14 @@ RadioInterfaceLayer.prototype = {
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
options.sms.delivery,
message.deliveryStatus,
function notifyResult(rv, sms) {
function notifyResult(rv, record) {
let sms = this.createSmsMessageFromRecord(record);
//TODO bug 832140 handle !Components.isSuccessCode(rv)
let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
? kSmsDeliverySuccessObserverTopic
: kSmsDeliveryErrorObserverTopic;
Services.obs.notifyObservers(sms, topic, null);
});
}.bind(this));
},
handleSmsSendFailed: function handleSmsSendFailed(message) {
@ -1662,11 +1674,12 @@ RadioInterfaceLayer.prototype = {
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
DOM_SMS_DELIVERY_ERROR,
RIL.GECKO_SMS_DELIVERY_STATUS_ERROR,
function notifyResult(rv, sms) {
function notifyResult(rv, record) {
let sms = this.createSmsMessageFromRecord(record);
//TODO bug 832140 handle !Components.isSuccessCode(rv)
options.request.notifySendMessageFailed(error);
Services.obs.notifyObservers(sms, kSmsFailedObserverTopic, null);
});
}.bind(this));
},
/**
@ -2645,8 +2658,17 @@ RadioInterfaceLayer.prototype = {
let deliveryStatus = options.requestStatusReport
? RIL.GECKO_SMS_DELIVERY_STATUS_PENDING
: RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE;
let id = gMobileMessageDatabaseService.saveSendingMessage(number, message, deliveryStatus, timestamp,
function notifyResult(rv, sms) {
let sendingMessage = {
type: "sms",
receiver: number,
body: message,
deliveryStatus: deliveryStatus,
timestamp: timestamp
};
let id = gMobileMessageDatabaseService.saveSendingMessage(sendingMessage,
function notifyResult(rv, record) {
let sms = this.createSmsMessageFromRecord(record);
//TODO bug 832140 handle !Components.isSuccessCode(rv)
Services.obs.notifyObservers(sms, kSmsSendingObserverTopic, null);

View File

@ -49,6 +49,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
} catch (e) {
ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox");
}
try {
var img = Components.utils.evalInSandbox("Image.prototype", sandbox);
ok(img, "'Image.prototype' in a sandbox should return the interface prototype object");
ok(isXrayWrapper(img), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
} catch (e) {
ok(false, "'Image.prototype' shouldn't throw in a sandbox");
}
try {
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
xhr.prototype = false;

View File

@ -85,7 +85,8 @@ function testElementFromPoint() {
moveEl.style.left = moveX + "px";
moveEl.style.top = moveY + "px";
}
let found = domWindowUtils.elementFromPoint(x, y, ignoreScroll, flushLayout);
let found = SpecialPowers.unwrap(domWindowUtils.elementFromPoint(
x, y, ignoreScroll, flushLayout));
is(found, expected, "at index " + i + " for data " + testData[i][0].toSource());
}

View File

@ -1,6 +1,6 @@
function makeAllAppsLaunchable() {
var Webapps = {};
SpecialPowers.wrap(Components).utils.import("resource://gre/modules/Webapps.jsm", Webapps);
SpecialPowers.Cu.import("resource://gre/modules/Webapps.jsm", Webapps);
var appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
var originalValue = appRegistry.allAppsLaunchable;

View File

@ -1489,6 +1489,14 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
mMaxZoom = aMaxZoom;
}
void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
if (!mGeckoContentController) {
return;
}
mGeckoContentController->PostDelayedTask(aTask, aDelayMs);
}
void AsyncPanZoomController::SendAsyncScrollEvent() {
if (!mGeckoContentController) {
return;

View File

@ -151,6 +151,12 @@ public:
*/
void UpdateZoomConstraints(bool aAllowZoom, float aMinScale, float aMaxScale);
/**
* Schedules a runnable to run on the controller/UI thread at some time
* in the future.
*/
void PostDelayedTask(Task* aTask, int aDelayMs);
// --------------------------------------------------------------------------
// These methods must only be called on the compositor thread.
//

View File

@ -10,6 +10,8 @@
#include "FrameMetrics.h"
#include "nsISupportsImpl.h"
class Task;
namespace mozilla {
namespace layers {
@ -52,6 +54,12 @@ public:
virtual void SendAsyncScrollDOMEvent(const gfx::Rect &aContentRect,
const gfx::Size &aScrollableSize) = 0;
/**
* Schedules a runnable to run on the controller/UI thread at some time
* in the future.
*/
virtual void PostDelayedTask(Task* aTask, int aDelayMs) = 0;
GeckoContentController() {}
virtual ~GeckoContentController() {}
};

View File

@ -88,8 +88,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
mLongTapTimeoutTask =
NewRunnableMethod(this, &GestureEventListener::TimeoutLongTap);
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
mAsyncPanZoomController->PostDelayedTask(
mLongTapTimeoutTask,
Preferences::GetInt("ui.click_hold_context_menus.delay", 500));
}
@ -169,8 +168,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
mDoubleTapTimeoutTask =
NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap);
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
mAsyncPanZoomController->PostDelayedTask(
mDoubleTapTimeoutTask,
MAX_TAP_TIME);
}

View File

@ -1,4 +1,7 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=4 ts=8 et tw=80 : */ /* 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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#ifndef mozilla_layers_GestureEventListener_h

View File

@ -121,7 +121,7 @@ CanvasLayerOGL::Initialize(const Data& aData)
return;
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mCanvasSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
mNeedsYFlip = false;
} else if (aData.mSurface) {
mCanvasSurface = aData.mSurface;

View File

@ -302,6 +302,7 @@ VectorImage::VectorImage(imgStatusTracker* aStatusTracker,
VectorImage::~VectorImage()
{
CancelAllListeners();
}
//------------------------------------------------------------------------------
@ -899,9 +900,6 @@ VectorImage::OnSVGDocumentParsed()
void
VectorImage::CancelAllListeners()
{
NS_ABORT_IF_FALSE(mParseCompleteListener, "Should have the parse complete listener");
NS_ABORT_IF_FALSE(mLoadEventListener, "Should have the load event listener");
if (mParseCompleteListener) {
mParseCompleteListener->Cancel();
mParseCompleteListener = nullptr;

View File

@ -6,8 +6,8 @@
<iframe src=discardframe.htm></iframe>
</div>
<script>
const Ci = Components.interfaces;
const Cc = SpecialPowers.wrap(Components).classes;
const Ci = SpecialPowers.Ci;
const Cc = SpecialPowers.Cc;
function ImageDecoderObserverStub()
{

View File

@ -480,7 +480,7 @@ ObjectWrapperChild::AnswerNewEnumerateNext(const JSVariant& in_state,
int32_t i = JSVAL_TO_INT(v);
NS_ASSERTION(i >= 0, "Index of next jsid negative?");
NS_ASSERTION(i <= strIds->Length(), "Index of next jsid too large?");
NS_ASSERTION(size_t(i) <= strIds->Length(), "Index of next jsid too large?");
if (size_t(i) == strIds->Length()) {
*status = JS_TRUE;

View File

@ -94,6 +94,15 @@ if test "$CLANG_CXX"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-mismatched-tags"
fi
if test -z "$GNU_CC"; then
case "$target" in
*-mingw*)
## Warning 4099 (equivalent of mismatched-tags) is disabled (bug 780474)
## for the same reasons as above.
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -wd4099"
esac
fi
if test "$GNU_CC"; then
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fno-exceptions"

View File

@ -1684,7 +1684,8 @@ ia64*-hpux*)
CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
CXXFLAGS="$CXXFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
# MSVC warning C4244 is ubiquitous, useless, and annoying.
CXXFLAGS="$CXXFLAGS -wd4244"
# khuey says we can safely ignore MSVC warning C4251
CXXFLAGS="$CXXFLAGS -wd4244 -wd4251"
# make 'foo == bar;' error out
CFLAGS="$CFLAGS -we4553"
CXXFLAGS="$CXXFLAGS -we4553"

View File

@ -1472,8 +1472,7 @@ ion::CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp,
}
MethodStatus
ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
bool isConstructing, bool newType)
ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing)
{
JS_ASSERT(ion::IsEnabled(cx));
@ -1495,8 +1494,8 @@ ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
if (isConstructing && fp.thisValue().isPrimitive()) {
RootedScript scriptRoot(cx, script);
RootedObject callee(cx, &fp.callee());
RootedObject obj(cx, CreateThisForFunction(cx, callee, newType));
if (!obj)
RootedObject obj(cx, CreateThisForFunction(cx, callee, fp.useNewType()));
if (!obj || !ion::IsEnabled(cx)) // Note: OOM under CreateThis can disable TI.
return Method_Skipped;
fp.thisValue().setObject(*obj);
script = scriptRoot;

View File

@ -261,8 +261,7 @@ bool SetIonContext(IonContext *ctx);
MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script,
AbstractFramePtr fp, jsbytecode *pc, bool isConstructing);
MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
bool isConstructing, bool newType);
MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing);
MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs);
enum IonExecStatus

View File

@ -4488,15 +4488,14 @@ IonBuilder::jsop_eval(uint32_t argc)
return abort("Direct eval in global code");
types::StackTypeSet *thisTypes = oracle->thisTypeSet(script());
if (!thisTypes) {
// The 'this' value for the outer and eval scripts must be the
// same. This is not guaranteed if a primitive string/number/etc.
// is passed through to the eval invoke as the primitive may be
// boxed into different objects if accessed via 'this'.
JSValueType type = thisTypes->getKnownTypeTag();
if (type != JSVAL_TYPE_OBJECT && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED)
return abort("Direct eval from script with maybe-primitive 'this'");
}
// The 'this' value for the outer and eval scripts must be the
// same. This is not guaranteed if a primitive string/number/etc.
// is passed through to the eval invoke as the primitive may be
// boxed into different objects if accessed via 'this'.
JSValueType type = thisTypes->getKnownTypeTag();
if (type != JSVAL_TYPE_OBJECT && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED)
return abort("Direct eval from script with maybe-primitive 'this'");
CallInfo callInfo(cx, /* constructing = */ false);
if (!callInfo.init(current, argc))

View File

@ -0,0 +1,19 @@
// getColumnOffsets correctly places the various parts of a ForStatement.
var global = newGlobal('new-compartment');
Debugger(global).onDebuggerStatement = function (frame) {
var script = frame.eval("f").return.script;
script.getAllColumnOffsets().forEach(function (offset) {
script.setBreakpoint(offset.offset, {
hit: function (frame) {
assertEq(offset.lineNumber, 17);
global.log += offset.columnNumber + " ";
}
});
});
};
global.log = '';
global.eval("function f(n) { for (var i = 0; i < n; ++i) log += '. '; log += '! '; } debugger;");
global.f(3);
assertEq(global.log, "21 32 44 . 39 32 44 . 39 32 44 . 39 32 57 ! 69 ");

View File

@ -0,0 +1,6 @@
function f() {
eval("this")
}
f()
f()

View File

@ -0,0 +1,7 @@
function testEvalThrow(x, y) {
eval("");
}
for (var i = 0; i < 5; i++)
testEvalThrow.call("");

View File

@ -79,8 +79,8 @@ MSG_DEF(JSMSG_TOO_DEEP, 25, 1, JSEXN_INTERNALERR, "{0} nested too
MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion")
MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}")
MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
MSG_DEF(JSMSG_UNUSED29, 29, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED30, 30, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED, 29, 0, JSEXN_ERR, "Permission denied to access object")
MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED, 30, 1, JSEXN_ERR, "Permission denied to access property '{0}'")
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
MSG_DEF(JSMSG_BAD_RADIX, 33, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")

View File

@ -881,6 +881,9 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
ionReturnOverride_(MagicValue(JS_ARG_POISON)),
useHelperThreads_(useHelperThreads),
requestedHelperThreadCount(-1),
#ifdef DEBUG
enteredPolicy(NULL),
#endif
rngNonce(0)
{
/* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */

View File

@ -569,7 +569,7 @@ struct MallocProvider
namespace gc {
class MarkingValidator;
} // namespace gc
class AutoEnterPolicy;
} // namespace js
struct JSRuntime : js::RuntimeFriendFields,
@ -1301,7 +1301,11 @@ struct JSRuntime : js::RuntimeFriendFields,
return 0;
#endif
}
#ifdef DEBUG
public:
js::AutoEnterPolicy *enteredPolicy;
#endif
private:
/*
* Used to ensure that compartments created at the same time get different

View File

@ -432,6 +432,7 @@ JSCompartment::wrap(JSContext *cx, JSObject **objp, JSObject *existingArg)
bool
JSCompartment::wrapId(JSContext *cx, jsid *idp)
{
MOZ_ASSERT(*idp != JSID_VOID, "JSID_VOID is an out-of-band sentinel value");
if (JSID_IS_INT(*idp))
return true;
RootedValue value(cx, IdToValue(*idp));

View File

@ -1416,6 +1416,13 @@ class JS_FRIEND_API(AutoCTypesActivityCallback) {
}
};
#ifdef DEBUG
extern JS_FRIEND_API(void)
assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id);
#else
inline JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id) {};
#endif
} /* namespace js */
#endif /* jsfriendapi_h___ */

View File

@ -276,6 +276,22 @@ js::RunScript(JSContext *cx, StackFrame *fp)
JS_CHECK_RECURSION(cx, return false);
// Check to see if useNewType flag should be set for this frame.
if (fp->isFunctionFrame() && fp->isConstructing() && !fp->isGeneratorFrame() &&
cx->typeInferenceEnabled())
{
StackIter iter(cx);
if (!iter.done()) {
++iter;
if (iter.isScript()) {
RawScript script = iter.script();
jsbytecode *pc = iter.pc();
if (UseNewType(cx, script, pc))
fp->setUseNewType();
}
}
}
#ifdef DEBUG
struct CheckStackBalance {
JSContext *cx;
@ -294,7 +310,7 @@ js::RunScript(JSContext *cx, StackFrame *fp)
#ifdef JS_ION
if (ion::IsEnabled(cx)) {
ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(fp),
fp->isConstructing(), false);
fp->isConstructing());
if (status == ion::Method_Error)
return false;
if (status == ion::Method_Compiled) {
@ -1159,7 +1175,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
if (interpMode == JSINTERP_NORMAL) {
StackFrame *fp = regs.fp();
if (!fp->isGeneratorFrame()) {
if (!fp->prologue(cx, UseNewTypeAtEntry(cx, fp)))
if (!fp->prologue(cx))
goto error;
} else {
Probes::enterScript(cx, script, script->function(), fp);
@ -2361,6 +2377,9 @@ BEGIN_CASE(JSOP_FUNCALL)
funScript = fun->nonLazyScript();
if (!cx->stack.pushInlineFrame(cx, regs, args, fun, funScript, initial))
goto error;
if (newType)
regs.fp()->setUseNewType();
SET_SCRIPT(regs.fp()->script());
#ifdef JS_METHODJIT
@ -2370,7 +2389,7 @@ BEGIN_CASE(JSOP_FUNCALL)
#ifdef JS_ION
if (!newType && ion::IsEnabled(cx)) {
ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(regs.fp()),
regs.fp()->isConstructing(), newType);
regs.fp()->isConstructing());
if (status == ion::Method_Error)
goto error;
if (status == ion::Method_Compiled) {
@ -2405,7 +2424,7 @@ BEGIN_CASE(JSOP_FUNCALL)
}
#endif
if (!regs.fp()->prologue(cx, newType))
if (!regs.fp()->prologue(cx))
goto error;
if (cx->compartment->debugMode()) {
switch (ScriptDebugPrologue(cx, regs.fp())) {

View File

@ -97,9 +97,11 @@ ComputeThis(JSContext *cx, AbstractFramePtr frame)
* |this| slot. If we lazily wrap a primitive |this| in an eval function frame, the
* eval's frame will get the wrapper, but the function's frame will not. To prevent
* this, we always wrap a function's |this| before pushing an eval frame, and should
* thus never see an unwrapped primitive in a non-strict eval function frame.
* thus never see an unwrapped primitive in a non-strict eval function frame. Null
* and undefined |this| values will unwrap to the same object in the function and
* eval frames, so are not required to be wrapped.
*/
JS_ASSERT(!frame.isEvalFrame());
JS_ASSERT_IF(frame.isEvalFrame(), thisv.isUndefined() || thisv.isNull());
}
bool modified;
if (!BoxNonStrictThis(cx, &thisv, &modified))

View File

@ -1226,9 +1226,6 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc)
JSOp op = (JSOp)*pc;
// None of these stack-writing ops generates novel values.
JS_ASSERT(op != JSOP_CASE && op != JSOP_DUP && op != JSOP_DUP2);
if (const char *token = CodeToken[op]) {
// Handle simple cases of binary and unary operators.
switch (js_CodeSpec[op].nuses) {
@ -2257,6 +2254,9 @@ GetPCCountJSON(JSContext *cx, const ScriptAndCounts &sac, StringBuffer &buf)
buf.append(str);
AppendJSONProperty(buf, "line");
NumberValueToStringBuffer(cx, Int32Value(script->lineno), buf);
AppendJSONProperty(buf, "opcodes");
buf.append('[');
bool comma = false;

View File

@ -49,9 +49,56 @@ GetFunctionProxyConstruct(UnrootedObject proxy)
return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT);
}
void
js::AutoEnterPolicy::reportError(JSContext *cx, jsid id)
{
if (JSID_IS_VOID(id)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_OBJECT_ACCESS_DENIED);
} else {
JSString *str = IdToString(cx, id);
const jschar *prop = str ? str->getCharsZ(cx) : NULL;
JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
JSMSG_PROPERTY_ACCESS_DENIED, prop);
}
}
#ifdef DEBUG
void
js::AutoEnterPolicy::recordEnter(JSContext *cx, JSObject *proxy, jsid id)
{
if (allowed()) {
context = cx;
enteredProxy.construct(cx, proxy);
enteredId.construct(cx, id);
prev = cx->runtime->enteredPolicy;
cx->runtime->enteredPolicy = this;
}
}
void
js::AutoEnterPolicy::recordLeave()
{
if (!enteredProxy.empty()) {
JS_ASSERT(context->runtime->enteredPolicy == this);
context->runtime->enteredPolicy = prev;
}
}
JS_FRIEND_API(void)
js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id)
{
MOZ_ASSERT(proxy->isProxy());
MOZ_ASSERT(cx->runtime->enteredPolicy);
MOZ_ASSERT(cx->runtime->enteredPolicy->enteredProxy.ref().get() == proxy);
MOZ_ASSERT(cx->runtime->enteredPolicy->enteredId.ref().get() == id);
}
#endif
BaseProxyHandler::BaseProxyHandler(void *family)
: mFamily(family),
mHasPrototype(false)
mHasPrototype(false),
mHasPolicy(false)
{
}
@ -59,9 +106,18 @@ BaseProxyHandler::~BaseProxyHandler()
{
}
bool
BaseProxyHandler::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
bool *bp)
{
*bp = true;
return true;
}
bool
BaseProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
{
assertEnteredPolicy(cx, proxy_, id_);
RootedObject proxy(cx, proxy_);
RootedId id(cx, id_);
AutoPropertyDescriptorRooter desc(cx);
@ -74,6 +130,7 @@ BaseProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
bool
BaseProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
{
assertEnteredPolicy(cx, proxy_, id_);
RootedObject proxy(cx, proxy_);
RootedId id(cx, id_);
AutoPropertyDescriptorRooter desc(cx);
@ -86,6 +143,7 @@ BaseProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
bool
BaseProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_, jsid id_, Value *vp)
{
assertEnteredPolicy(cx, proxy, id_);
RootedObject receiver(cx, receiver_);
RootedId id(cx, id_);
@ -127,6 +185,7 @@ BaseProxyHandler::getElementIfPresent(JSContext *cx, JSObject *proxy_, JSObject
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
assertEnteredPolicy(cx, proxy, id);
if (!has(cx, proxy, id, present))
return false;
@ -143,6 +202,7 @@ bool
BaseProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid id_, bool strict,
Value *vp)
{
assertEnteredPolicy(cx, proxy_, id_);
RootedObject proxy(cx, proxy_), receiver(cx, receiver_);
RootedId id(cx, id_);
@ -219,6 +279,7 @@ BaseProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid
bool
BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
{
assertEnteredPolicy(cx, proxyArg, JSID_VOID);
JS_ASSERT(props.length() == 0);
RootedObject proxy(cx, proxyArg);
@ -232,6 +293,7 @@ BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
for (size_t j = 0, len = props.length(); j < len; j++) {
JS_ASSERT(i <= j);
jsid id = props[j];
AutoWaivePolicy policy(cx, proxy, id);
if (!getOwnPropertyDescriptor(cx, proxy, id, &desc, 0))
return false;
if (desc.obj && (desc.attrs & JSPROP_ENUMERATE))
@ -247,6 +309,7 @@ BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
bool
BaseProxyHandler::iterate(JSContext *cx, JSObject *proxy_, unsigned flags, Value *vp)
{
assertEnteredPolicy(cx, proxy_, JSID_VOID);
RootedObject proxy(cx, proxy_);
AutoIdVector props(cx);
@ -268,6 +331,7 @@ bool
BaseProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc,
Value *vp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
AutoValueRooter rval(cx);
RootedValue call(cx, GetCall(proxy));
JSBool ok = Invoke(cx, vp[1], call, argc, JS_ARGV(cx, vp), rval.addr());
@ -280,6 +344,7 @@ bool
BaseProxyHandler::construct(JSContext *cx, JSObject *proxy_, unsigned argc,
Value *argv, Value *rval)
{
assertEnteredPolicy(cx, proxy_, JSID_VOID);
RootedObject proxy(cx, proxy_);
RootedValue fval(cx, GetConstruct(proxy_));
if (fval.isUndefined())
@ -298,6 +363,7 @@ BaseProxyHandler::obj_toString(JSContext *cx, JSObject *proxy)
JSString *
BaseProxyHandler::fun_toString(JSContext *cx, JSObject *proxy, unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
Value fval = GetCall(proxy);
if (IsFunctionProxy(proxy) &&
(fval.isPrimitive() || !fval.toObject().isFunction())) {
@ -343,6 +409,7 @@ BaseProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl im
bool
BaseProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue val(cx, ObjectValue(*proxy.get()));
js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
JSDVG_SEARCH_STACK, val, NullPtr());
@ -379,6 +446,8 @@ bool
DirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
jsid id, PropertyDescriptor *desc, unsigned flags)
{
assertEnteredPolicy(cx, proxy, id);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
RootedObject target(cx, GetProxyTargetObject(proxy));
return JS_GetPropertyDescriptorById(cx, target, id, 0, desc);
}
@ -403,6 +472,7 @@ bool
DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
jsid id, PropertyDescriptor *desc, unsigned flags)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
return GetOwnPropertyDescriptor(cx, target, id, 0, desc);
}
@ -411,6 +481,7 @@ bool
DirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_,
PropertyDescriptor *desc)
{
assertEnteredPolicy(cx, proxy, id_);
RootedObject obj(cx, GetProxyTargetObject(proxy));
Rooted<jsid> id(cx, id_);
Rooted<Value> v(cx, desc->value);
@ -422,6 +493,7 @@ bool
DirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy,
AutoIdVector &props)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props);
}
@ -430,6 +502,7 @@ bool
DirectProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
RootedValue v(cx);
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
if (!JS_DeletePropertyById2(cx, target, id, v.address()))
return false;
@ -444,6 +517,8 @@ bool
DirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy,
AutoIdVector &props)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
RootedObject target(cx, GetProxyTargetObject(proxy));
return GetPropertyNames(cx, target, 0, &props);
}
@ -465,6 +540,7 @@ bool
DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
bool *bp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JSBool b;
RootedObject target(cx, GetProxyTargetObject(proxy));
if (!JS_HasInstance(cx, target, v, &b))
@ -485,6 +561,7 @@ DirectProxyHandler::objectClassIs(JSObject *proxy, ESClassValue classValue,
JSString *
DirectProxyHandler::obj_toString(JSContext *cx, JSObject *proxy)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
return obj_toStringHelper(cx, GetProxyTargetObject(proxy));
}
@ -492,6 +569,7 @@ JSString *
DirectProxyHandler::fun_toString(JSContext *cx, JSObject *proxy,
unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
return fun_toStringHelper(cx, target, indent);
}
@ -527,6 +605,8 @@ DirectProxyHandler::DirectProxyHandler(void *family)
bool
DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
assertEnteredPolicy(cx, proxy, id);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
JSBool found;
RootedObject target(cx, GetProxyTargetObject(proxy));
if (!JS_HasPropertyById(cx, target, id, &found))
@ -538,6 +618,7 @@ DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
bool
DirectProxyHandler::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
AutoPropertyDescriptorRooter desc(cx);
if (!JS_GetPropertyDescriptorById(cx, target, id, 0, &desc))
@ -550,6 +631,7 @@ bool
DirectProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_,
jsid id_, Value *vp)
{
assertEnteredPolicy(cx, proxy, id_);
RootedObject receiver(cx, receiver_);
RootedId id(cx, id_);
RootedValue value(cx);
@ -565,6 +647,7 @@ bool
DirectProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiverArg,
jsid id_, bool strict, Value *vp)
{
assertEnteredPolicy(cx, proxy, id_);
RootedId id(cx, id_);
Rooted<JSObject*> receiver(cx, receiverArg);
RootedValue value(cx, *vp);
@ -579,6 +662,7 @@ DirectProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiverArg,
bool
DirectProxyHandler::keys(JSContext *cx, JSObject *proxy, AutoIdVector &props)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
return GetPropertyNames(cx, GetProxyTargetObject(proxy), JSITER_OWNONLY, &props);
}
@ -586,6 +670,8 @@ bool
DirectProxyHandler::iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
Rooted<JSObject*> target(cx, GetProxyTargetObject(proxy));
RootedValue value(cx);
if (!GetIterator(cx, target, flags, &value))
@ -2177,7 +2263,6 @@ ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton;
return protoCall; \
JS_END_MACRO \
bool
Proxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, PropertyDescriptor *desc,
unsigned flags)
@ -2186,6 +2271,10 @@ Proxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, Property
RootedObject proxy(cx, proxy_);
RootedId id(cx, id_);
BaseProxyHandler *handler = GetProxyHandler(proxy);
desc->obj = NULL; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
if (!handler->hasPrototype())
return handler->getPropertyDescriptor(cx, proxy, id, desc, flags);
if (!handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags))
@ -2218,7 +2307,12 @@ Proxy::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id, Proper
{
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
BaseProxyHandler *handler = GetProxyHandler(proxy);
desc->obj = NULL; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
}
bool
@ -2242,7 +2336,11 @@ bool
Proxy::defineProperty(JSContext *cx, JSObject *proxy_, jsid id, PropertyDescriptor *desc)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy_);
RootedObject proxy(cx, proxy_);
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->defineProperty(cx, proxy, id, desc);
}
@ -2261,7 +2359,11 @@ bool
Proxy::getOwnPropertyNames(JSContext *cx, JSObject *proxy_, AutoIdVector &props)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy_);
RootedObject proxy(cx, proxy_);
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->getOwnPropertyNames(cx, proxy, props);
}
@ -2269,7 +2371,12 @@ bool
Proxy::delete_(JSContext *cx, JSObject *proxy_, jsid id, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy_);
RootedObject proxy(cx, proxy_);
*bp = true; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->delete_(cx, proxy, id, bp);
}
@ -2299,6 +2406,9 @@ Proxy::enumerate(JSContext *cx, JSObject *proxy_, AutoIdVector &props)
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
if (!handler->hasPrototype())
return GetProxyHandler(proxy)->enumerate(cx, proxy, props);
if (!handler->keys(cx, proxy, props))
@ -2316,6 +2426,10 @@ Proxy::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
RootedObject proxy(cx, proxy_);
RootedId id(cx, id_);
BaseProxyHandler *handler = GetProxyHandler(proxy);
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
if (!handler->hasPrototype())
return handler->has(cx, proxy, id, bp);
if (!handler->hasOwn(cx, proxy, id, bp))
@ -2333,7 +2447,12 @@ Proxy::hasOwn(JSContext *cx, JSObject *proxy_, jsid id, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->hasOwn(cx, proxy, id, bp);
BaseProxyHandler *handler = GetProxyHandler(proxy);
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return handler->hasOwn(cx, proxy, id, bp);
}
bool
@ -2342,6 +2461,10 @@ Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
vp.setUndefined(); // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
bool own;
if (!handler->hasPrototype()) {
own = true;
@ -2360,17 +2483,20 @@ Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject recei
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
if (!handler->hasPrototype()) {
return GetProxyHandler(proxy)->getElementIfPresent(cx, proxy, receiver, index,
vp.address(), present);
}
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
if (!handler->hasPrototype()) {
return handler->getElementIfPresent(cx, proxy, receiver, index,
vp.address(), present);
}
bool hasOwn;
if (!handler->hasOwn(cx, proxy, id, &hasOwn))
return false;
@ -2390,6 +2516,9 @@ Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
if (handler->hasPrototype()) {
// If we're using a prototype, we still want to use the proxy trap unless
// we have a non-own property with a setter.
@ -2417,7 +2546,11 @@ Proxy::keys(JSContext *cx, JSObject *proxy_, AutoIdVector &props)
{
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->keys(cx, proxy, props);
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return handler->keys(cx, proxy, props);
}
bool
@ -2425,8 +2558,19 @@ Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleV
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
if (!handler->hasPrototype())
return GetProxyHandler(proxy)->iterate(cx, proxy, flags, vp.address());
vp.setUndefined(); // default result if we refuse to perform this action
if (!handler->hasPrototype()) {
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID,
BaseProxyHandler::GET, /* mayThrow = */ false);
// If the policy denies access but wants us to return true, we need
// to hand a valid (empty) iterator object to the caller.
if (!policy.allowed()) {
AutoIdVector props(cx);
return policy.returnValue() &&
EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp);
}
return handler->iterate(cx, proxy, flags, vp.address());
}
AutoIdVector props(cx);
// The other Proxy::foo methods do the prototype-aware work for us here.
if ((flags & JSITER_OWNONLY)
@ -2442,7 +2586,19 @@ Proxy::call(JSContext *cx, JSObject *proxy_, unsigned argc, Value *vp)
{
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->call(cx, proxy, argc, vp);
BaseProxyHandler *handler = GetProxyHandler(proxy);
// Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we
// can only set our default value once we're sure that we're not calling the
// trap.
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID,
BaseProxyHandler::CALL, true);
if (!policy.allowed()) {
vp->setUndefined();
return policy.returnValue();
}
return handler->call(cx, proxy, argc, vp);
}
bool
@ -2450,7 +2606,19 @@ Proxy::construct(JSContext *cx, JSObject *proxy_, unsigned argc, Value *argv, Va
{
JS_CHECK_RECURSION(cx, return false);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->construct(cx, proxy, argc, argv, rval);
BaseProxyHandler *handler = GetProxyHandler(proxy);
// Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we
// can only set our default value once we're sure that we're not calling the
// trap.
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID,
BaseProxyHandler::CALL, true);
if (!policy.allowed()) {
rval->setUndefined();
return policy.returnValue();
}
return handler->construct(cx, proxy, argc, argv, rval);
}
bool
@ -2458,6 +2626,9 @@ Proxy::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArg
{
JS_CHECK_RECURSION(cx, return false);
Rooted<JSObject*> proxy(cx, &args.thisv().toObject());
// Note - we don't enter a policy here because our security architecture
// guards against nativeCall by overriding the trap itself in the right
// circumstances.
return GetProxyHandler(proxy)->nativeCall(cx, test, impl, args);
}
@ -2465,6 +2636,11 @@ bool
Proxy::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->hasInstance(cx, proxy, v, bp);
}
@ -2480,7 +2656,14 @@ Proxy::obj_toString(JSContext *cx, JSObject *proxy_)
{
JS_CHECK_RECURSION(cx, return NULL);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->obj_toString(cx, proxy);
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID,
BaseProxyHandler::GET, /* mayThrow = */ false);
// Do the safe thing if the policy rejects.
if (!policy.allowed()) {
return handler->BaseProxyHandler::obj_toString(cx, proxy);
}
return handler->obj_toString(cx, proxy);
}
JSString *
@ -2488,7 +2671,17 @@ Proxy::fun_toString(JSContext *cx, JSObject *proxy_, unsigned indent)
{
JS_CHECK_RECURSION(cx, return NULL);
RootedObject proxy(cx, proxy_);
return GetProxyHandler(proxy)->fun_toString(cx, proxy, indent);
BaseProxyHandler *handler = GetProxyHandler(proxy);
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOID,
BaseProxyHandler::GET, /* mayThrow = */ false);
// Do the safe thing if the policy rejects.
if (!policy.allowed()) {
if (proxy->isCallable())
return JS_NewStringCopyZ(cx, "function () {\n [native code]\n}");
ReportIsNotFunction(cx, ObjectValue(*proxy));
return NULL;
}
return handler->fun_toString(cx, proxy, indent);
}
bool

View File

@ -51,9 +51,11 @@ class JS_FRIEND_API(Wrapper);
class JS_FRIEND_API(BaseProxyHandler) {
void *mFamily;
bool mHasPrototype;
bool mHasPolicy;
protected:
// Subclasses may set this in their constructor.
void setHasPrototype(bool aHasPrototype) { mHasPrototype = aHasPrototype; }
void setHasPolicy(bool aHasPolicy) { mHasPolicy = aHasPolicy; }
public:
explicit BaseProxyHandler(void *family);
@ -63,6 +65,10 @@ class JS_FRIEND_API(BaseProxyHandler) {
return mHasPrototype;
}
bool hasPolicy() {
return mHasPolicy;
}
inline void *family() {
return mFamily;
}
@ -71,6 +77,24 @@ class JS_FRIEND_API(BaseProxyHandler) {
return false;
}
/* Policy enforcement traps.
*
* enter() allows the policy to specify whether the caller may perform |act|
* on the proxy's |id| property. In the case when |act| is CALL, |id| is
* generally JSID_VOID.
*
* The |act| parameter to enter() specifies the action being performed.
* If |bp| is false, the trap suggests that the caller throw (though it
* may still decide to squelch the error).
*/
enum Action {
GET,
SET,
CALL
};
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
bool *bp);
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
PropertyDescriptor *desc, unsigned flags) = 0;
@ -319,6 +343,72 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
JSObject *
RenewProxyObject(JSContext *cx, JSObject *obj, BaseProxyHandler *handler, Value priv);
class JS_FRIEND_API(AutoEnterPolicy)
{
public:
typedef BaseProxyHandler::Action Action;
AutoEnterPolicy(JSContext *cx, BaseProxyHandler *handler,
JSObject *wrapper, jsid id, Action act, bool mayThrow)
#ifdef DEBUG
: context(NULL)
#endif
{
allow = handler->hasPolicy() ? handler->enter(cx, wrapper, id, act, &rv)
: true;
recordEnter(cx, wrapper, id);
if (!allow && !rv && mayThrow)
reportError(cx, id);
}
virtual ~AutoEnterPolicy() { recordLeave(); }
inline bool allowed() { return allow; }
inline bool returnValue() { JS_ASSERT(!allowed()); return rv; }
protected:
// no-op constructor for subclass
AutoEnterPolicy()
#ifdef DEBUG
: context(NULL)
#endif
{};
void reportError(JSContext *cx, jsid id);
bool allow;
bool rv;
#ifdef DEBUG
JSContext *context;
mozilla::Maybe<RootedObject> enteredProxy;
mozilla::Maybe<RootedId> enteredId;
// NB: We explicitly don't track the entered action here, because sometimes
// SET traps do an implicit GET during their implementation, leading to
// spurious assertions.
AutoEnterPolicy *prev;
void recordEnter(JSContext *cx, JSObject *proxy, jsid id);
void recordLeave();
friend JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id);
#else
inline void recordEnter(JSContext *cx, JSObject *proxy, jsid id) {}
inline void recordLeave() {}
#endif
};
#ifdef DEBUG
class JS_FRIEND_API(AutoWaivePolicy) : public AutoEnterPolicy {
public:
AutoWaivePolicy(JSContext *cx, JSObject *proxy, jsid id)
{
allow = true;
recordEnter(cx, proxy, id);
}
};
#else
class JS_FRIEND_API(AutoWaivePolicy) {
public: AutoWaivePolicy(JSContext *cx, JSObject *proxy, jsid id) {};
};
#endif
} /* namespace js */
extern JS_FRIEND_API(JSObject *)

View File

@ -70,13 +70,6 @@ Wrapper::wrappedObject(RawObject wrapper)
return GetProxyTargetObject(wrapper);
}
bool
Wrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp)
{
*bp = true;
return true;
}
JS_FRIEND_API(JSObject *)
js::UnwrapObject(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
{
@ -122,17 +115,6 @@ js::IsCrossCompartmentWrapper(RawObject wrapper)
!!(Wrapper::wrapperHandler(wrapper)->flags() & Wrapper::CROSS_COMPARTMENT);
}
#define CHECKED(op, act) \
JS_BEGIN_MACRO \
bool status; \
if (!enter(cx, wrapper, id, act, &status)) \
return status; \
return (op); \
JS_END_MACRO
#define SET(action) CHECKED(action, SET)
#define GET(action) CHECKED(action, GET)
Wrapper::Wrapper(unsigned flags, bool hasPrototype) : DirectProxyHandler(&sWrapperFamily)
, mFlags(flags)
, mSafeToUnwrap(true)
@ -144,62 +126,6 @@ Wrapper::~Wrapper()
{
}
bool
Wrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapperArg,
jsid id, PropertyDescriptor *desc, unsigned flags)
{
RootedObject wrapper(cx, wrapperArg);
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
desc->obj = NULL; // default result if we refuse to perform this action
CHECKED(DirectProxyHandler::getPropertyDescriptor(cx, wrapper, id, desc, flags),
(flags & JSRESOLVE_ASSIGNING) ? SET : GET);
}
bool
Wrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapperArg,
jsid id, PropertyDescriptor *desc, unsigned flags)
{
RootedObject wrapper(cx, wrapperArg);
desc->obj = NULL; // default result if we refuse to perform this action
CHECKED(DirectProxyHandler::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags), GET);
}
bool
Wrapper::defineProperty(JSContext *cx, JSObject *wrapperArg, jsid id,
PropertyDescriptor *desc)
{
RootedObject wrapper(cx, wrapperArg);
SET(DirectProxyHandler::defineProperty(cx, wrapper, id, desc));
}
bool
Wrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapperArg,
AutoIdVector &props)
{
RootedObject wrapper(cx, wrapperArg);
// if we refuse to perform this action, props remains empty
jsid id = JSID_VOID;
GET(DirectProxyHandler::getOwnPropertyNames(cx, wrapper, props));
}
bool
Wrapper::delete_(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
{
RootedObject wrapper(cx, wrapperArg);
*bp = true; // default result if we refuse to perform this action
SET(DirectProxyHandler::delete_(cx, wrapper, id, bp));
}
bool
Wrapper::enumerate(JSContext *cx, JSObject *wrapperArg, AutoIdVector &props)
{
RootedObject wrapper(cx, wrapperArg);
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
// if we refuse to perform this action, props remains empty
static jsid id = JSID_VOID;
GET(DirectProxyHandler::enumerate(cx, wrapper, props));
}
/*
* Ordinarily, the convert trap would require unwrapping. However, the default
* implementation of convert, JS_ConvertStub, obtains a default value by calling
@ -234,126 +160,6 @@ Wrapper::defaultValue(JSContext *cx, JSObject *wrapperArg, JSType hint, Value *v
return DirectProxyHandler::defaultValue(cx, wrapper, hint, vp);
}
bool
Wrapper::has(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
{
RootedObject wrapper(cx, wrapperArg);
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
*bp = false; // default result if we refuse to perform this action
GET(DirectProxyHandler::has(cx, wrapper, id, bp));
}
bool
Wrapper::hasOwn(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
{
RootedObject wrapper(cx, wrapperArg);
*bp = false; // default result if we refuse to perform this action
GET(DirectProxyHandler::hasOwn(cx, wrapper, id, bp));
}
bool
Wrapper::get(JSContext *cx, JSObject *wrapperArg, JSObject *receiver, jsid id, Value *vp)
{
RootedObject wrapper(cx, wrapperArg);
vp->setUndefined(); // default result if we refuse to perform this action
GET(DirectProxyHandler::get(cx, wrapper, receiver, id, vp));
}
bool
Wrapper::set(JSContext *cx, JSObject *wrapperArg, JSObject *receiver, jsid id, bool strict,
Value *vp)
{
RootedObject wrapper(cx, wrapperArg);
SET(DirectProxyHandler::set(cx, wrapper, receiver, id, strict, vp));
}
bool
Wrapper::keys(JSContext *cx, JSObject *wrapperArg, AutoIdVector &props)
{
RootedObject wrapper(cx, wrapperArg);
// if we refuse to perform this action, props remains empty
const jsid id = JSID_VOID;
GET(DirectProxyHandler::keys(cx, wrapper, props));
}
bool
Wrapper::iterate(JSContext *cx, JSObject *wrapperArg, unsigned flags, Value *vp)
{
RootedObject wrapper(cx, wrapperArg);
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
vp->setUndefined(); // default result if we refuse to perform this action
const jsid id = JSID_VOID;
GET(DirectProxyHandler::iterate(cx, wrapper, flags, vp));
}
bool
Wrapper::call(JSContext *cx, JSObject *wrapperArg, unsigned argc, Value *vp)
{
RootedObject wrapper(cx, wrapperArg);
vp->setUndefined(); // default result if we refuse to perform this action
const jsid id = JSID_VOID;
CHECKED(DirectProxyHandler::call(cx, wrapper, argc, vp), CALL);
}
bool
Wrapper::construct(JSContext *cx, JSObject *wrapperArg, unsigned argc, Value *argv, Value *vp)
{
RootedObject wrapper(cx, wrapperArg);
vp->setUndefined(); // default result if we refuse to perform this action
const jsid id = JSID_VOID;
CHECKED(DirectProxyHandler::construct(cx, wrapper, argc, argv, vp), CALL);
}
bool
Wrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args)
{
const jsid id = JSID_VOID;
RootedObject wrapper(cx, &args.thisv().toObject());
CHECKED(DirectProxyHandler::nativeCall(cx, test, impl, args), CALL);
}
bool
Wrapper::hasInstance(JSContext *cx, HandleObject wrapper, MutableHandleValue v, bool *bp)
{
*bp = false; // default result if we refuse to perform this action
const jsid id = JSID_VOID;
GET(DirectProxyHandler::hasInstance(cx, wrapper, v, bp));
}
JSString *
Wrapper::obj_toString(JSContext *cx, JSObject *wrapperArg)
{
RootedObject wrapper(cx, wrapperArg);
bool status;
if (!enter(cx, wrapper, JSID_VOID, GET, &status)) {
if (status) {
// Perform some default behavior that doesn't leak any information.
return JS_NewStringCopyZ(cx, "[object Object]");
}
return NULL;
}
JSString *str = DirectProxyHandler::obj_toString(cx, wrapper);
return str;
}
JSString *
Wrapper::fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent)
{
bool status;
if (!enter(cx, wrapper, JSID_VOID, GET, &status)) {
if (status) {
// Perform some default behavior that doesn't leak any information.
if (wrapper->isCallable())
return JS_NewStringCopyZ(cx, "function () {\n [native code]\n}");
ReportIsNotFunction(cx, ObjectValue(*wrapper));
return NULL;
}
return NULL;
}
JSString *str = DirectProxyHandler::fun_toString(cx, wrapper, indent);
return str;
}
Wrapper Wrapper::singleton((unsigned)0);
Wrapper Wrapper::singletonWithPrototype((unsigned)0, true);
@ -838,6 +644,7 @@ SecurityWrapper<Base>::SecurityWrapper(unsigned flags)
: Base(flags)
{
Base::setSafeToUnwrap(false);
BaseProxyHandler::setHasPolicy(true);
}
template <class Base>

View File

@ -32,11 +32,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
bool mSafeToUnwrap;
public:
enum Action {
GET,
SET,
CALL
};
using BaseProxyHandler::Action;
enum Flags {
CROSS_COMPARTMENT = 1 << 0,
@ -65,54 +61,11 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
return mFlags;
}
/* Policy enforcement traps.
*
* enter() allows the policy to specify whether the caller may perform |act|
* on the underlying object's |id| property. In the case when |act| is CALL,
* |id| is generally JSID_VOID.
*
* The |act| parameter to enter() specifies the action being performed.
*/
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
bool *bp);
explicit Wrapper(unsigned flags, bool hasPrototype = false);
virtual ~Wrapper();
/* ES5 Harmony fundamental wrapper traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
jsid id, PropertyDescriptor *desc,
unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper,
jsid id, PropertyDescriptor *desc,
unsigned flags) MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JSObject *wrapper,
AutoIdVector &props) MOZ_OVERRIDE;
/* ES5 Harmony derived wrapper traps. */
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
Value *vp) MOZ_OVERRIDE;
virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
virtual bool iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, HandleObject wrapper, MutableHandleValue v, bool *bp) MOZ_OVERRIDE;
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
Value *vp) MOZ_OVERRIDE;

View File

@ -940,7 +940,9 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
return js_InternalThrow(f);
fp->initVarsToUndefined();
fp->scopeChain();
if (!fp->prologue(cx, types::UseNewTypeAtEntry(cx, fp)))
if (types::UseNewTypeAtEntry(cx, fp))
fp->setUseNewType();
if (!fp->prologue(cx))
return js_InternalThrow(f);
/*

View File

@ -778,7 +778,7 @@ stubs::TriggerIonCompile(VMFrame &f)
AssertCanGC();
RootedScript script(f.cx, f.script());
if (ion::js_IonOptions.parallelCompilation) {
if (ion::js_IonOptions.parallelCompilation && !f.cx->runtime->profilingScripts) {
if (script->hasIonScript()) {
/*
* Normally TriggerIonCompile is not called if !script->ion, but the
@ -808,8 +808,7 @@ stubs::TriggerIonCompile(VMFrame &f)
compileStatus = ion::CanEnterAtBranch(f.cx, script, f.cx->fp(), osrPC,
f.fp()->isConstructing());
} else {
compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing(),
/* newType = */ false);
compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing());
}
if (compileStatus != ion::Method_Compiled) {

View File

@ -3185,6 +3185,59 @@ DebuggerScript_getAllOffsets(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static JSBool
DebuggerScript_getAllColumnOffsets(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "getAllColumnOffsets", args, obj, script);
/*
* First pass: determine which offsets in this script are jump targets and
* which positions jump to them.
*/
FlowGraphSummary flowData(cx);
if (!flowData.populate(cx, script))
return false;
/* Second pass: build the result array. */
RootedObject result(cx, NewDenseEmptyArray(cx));
if (!result)
return false;
for (BytecodeRangeWithPosition r(cx, script); !r.empty(); r.popFront()) {
size_t lineno = r.frontLineNumber();
size_t column = r.frontColumnNumber();
size_t offset = r.frontOffset();
/* Make a note, if the current instruction is an entry point for the current position. */
if (!flowData[offset].hasNoEdges() &&
(flowData[offset].lineno() != lineno ||
flowData[offset].column() != column)) {
RootedObject entry(cx, NewBuiltinClassInstance(cx, &ObjectClass));
if (!entry)
return false;
RootedId id(cx, NameToId(cx->names().lineNumber));
RootedValue value(cx, NumberValue(lineno));
if (!JSObject::defineGeneric(cx, entry, id, value))
return false;
value = NumberValue(column);
if (!JSObject::defineProperty(cx, entry, cx->names().columnNumber, value))
return false;
id = NameToId(cx->names().offset);
value = NumberValue(offset);
if (!JSObject::defineGeneric(cx, entry, id, value))
return false;
if (!js_NewbornArrayPush(cx, result, ObjectValue(*entry)))
return false;
}
}
args.rval().setObject(*result);
return true;
}
static JSBool
DebuggerScript_getLineOffsets(JSContext *cx, unsigned argc, Value *vp)
{
@ -3356,6 +3409,7 @@ static JSPropertySpec DebuggerScript_properties[] = {
static JSFunctionSpec DebuggerScript_methods[] = {
JS_FN("getChildScripts", DebuggerScript_getChildScripts, 0, 0),
JS_FN("getAllOffsets", DebuggerScript_getAllOffsets, 0, 0),
JS_FN("getAllColumnOffsets", DebuggerScript_getAllColumnOffsets, 0, 0),
JS_FN("getLineOffsets", DebuggerScript_getLineOffsets, 1, 0),
JS_FN("getOffsetLine", DebuggerScript_getOffsetLine, 0, 0),
JS_FN("setBreakpoint", DebuggerScript_setBreakpoint, 2, 0),

View File

@ -738,6 +738,13 @@ AbstractFramePtr::hasCallObj() const
return false;
}
inline bool
AbstractFramePtr::useNewType() const
{
if (isStackFrame())
return asStackFrame()->useNewType();
return false;
}
inline bool
AbstractFramePtr::isGeneratorFrame() const
{
if (isStackFrame())

View File

@ -307,7 +307,7 @@ StackFrame::initFunctionScopeObjects(JSContext *cx)
}
bool
StackFrame::prologue(JSContext *cx, bool newType)
StackFrame::prologue(JSContext *cx)
{
RootedScript script(cx, this->script());
@ -339,7 +339,7 @@ StackFrame::prologue(JSContext *cx, bool newType)
if (isConstructing()) {
RootedObject callee(cx, &this->callee());
JSObject *obj = CreateThisForFunction(cx, callee, newType);
JSObject *obj = CreateThisForFunction(cx, callee, useNewType());
if (!obj)
return false;
functionThis() = ObjectValue(*obj);

View File

@ -297,6 +297,7 @@ class AbstractFramePtr
inline bool hasArgsObj() const;
inline ArgumentsObject &argsObj() const;
inline void initArgsObj(ArgumentsObject &argsobj) const;
inline bool useNewType() const;
inline bool copyRawFrameSlots(AutoValueVector *vec) const;
@ -389,10 +390,13 @@ class StackFrame
HAS_PUSHED_SPS_FRAME = 0x100000, /* SPS was notified of enty */
/* Ion frame state */
RUNNING_IN_ION = 0x200000, /* frame is running in Ion */
CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */
RUNNING_IN_ION = 0x200000, /* frame is running in Ion */
CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */
JIT_REVISED_STACK = 0x800000 /* sp was revised by JIT for lowered apply */
JIT_REVISED_STACK = 0x800000, /* sp was revised by JIT for lowered apply */
/* Miscellaneous state. */
USE_NEW_TYPE = 0x1000000 /* Use new type for constructed |this| object. */
};
private:
@ -489,12 +493,9 @@ class StackFrame
* over-recursed) after pushing the stack frame but before 'prologue' is
* called or completes fully. To simplify usage, 'epilogue' does not assume
* 'prologue' has completed and handles all the intermediate state details.
*
* The 'newType' option indicates whether the constructed 'this' value (if
* there is one) should be given a new singleton type.
*/
bool prologue(JSContext *cx, bool newType);
bool prologue(JSContext *cx);
void epilogue(JSContext *cx);
/* Subsets of 'prologue' called from jit code. */
@ -1052,6 +1053,15 @@ class StackFrame
return flags_ & HAS_ARGS_OBJ;
}
void setUseNewType() {
JS_ASSERT(isConstructing());
flags_ |= USE_NEW_TYPE;
}
bool useNewType() const {
JS_ASSERT(isConstructing());
return flags_ & USE_NEW_TYPE;
}
/*
* The method JIT call/apply optimization can erase Function.{call,apply}
* invocations from the stack and push the callee frame directly. The base

View File

@ -31,12 +31,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=760109
ok(protoProto === Object.prototype,
"Object prototype remapped properly");
// Check |constructor|. The semantics of this weird for the case of an
// object with a custom chrome-implemented prototype, because we'll end up
// bouncing up the prototype chain to Object, even though that's not fully
// accurate. It's unlikely to be a problem though, so we just verify that
// it does what we expect.
ok(chromeObject.constructor === Object, "Object constructor does what we expect");
// Check |constructor|.
// Note that the 'constructor' property of the underlying chrome object
// will be resolved on SomeConstructor.prototype, which has an empty
// __exposedProps__. This means that we shouldn't remap the property, even
// though we'd also be able to find it on Object.prototype. Some recent
// refactoring has made it possible to do the right thing here.
is(typeof chromeObject.constructor, "undefined", "Object constructor does what we expect");
ok(chromeArray.constructor === Array, "Array constructor remapped properly");
// We should be able to .forEach on the Array.

View File

@ -43,7 +43,6 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \
bug504877_helper.html \
test_bug505915.html \
file_bug505915.html \
test_bug553407.html \
test_bug560351.html \
bug571849_helper.html \
test_bug585745.html \

View File

@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=478438
return;
test.calledAlready = true;
var iwin = (new XPCNativeWrapper(document)).getElementById("f").contentWindow;
var iwin = document.getElementById("f").contentWindow;
function testOne(fn, onAllow, infinitive) {
try { fn(); onAllow("able " + infinitive, "") }

View File

@ -1,31 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=517163
-->
<head>
<title>Test for Bug 553407</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=553407">Mozilla Bug 553407</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 553407 **/
is(typeof new XPCNativeWrapper(location), "object", "XPCNativeWrapper(location) is an object")
is(typeof new XPCNativeWrapper(XMLHttpRequest), "function", "XPCNativeWrapper(XMLHttpRequest) is a function")
// We no longer support .wrappedJSObject on NW since for same-origin there is no wrapper in between.
// is(typeof new XPCNativeWrapper(location).wrappedJSObject, "object", "XPCNativeWrapper(location).wrappedJSObject is an object")
// is(typeof new XPCNativeWrapper(XMLHttpRequest).wrappedJSObject, "function", "XPCNativeWrapper(XMLHttpRequest).wrappedJSObject is a function")
ok("a".replace("a", new XPCNativeWrapper(location)).indexOf("mochi.test") >= 0, "XPCNativeWrappers can be used as the replacement value for .replace");
</script>
</pre>
</body>
</html>

View File

@ -24,10 +24,10 @@ function test()
option.text="Fubar";
sel.options.add(option);
try {
Components.lookupMethod(sel.options, "add")(option);
SpecialPowers.Components.lookupMethod(sel.options, "add")(option);
ok(true, "function call should not throw")
} catch(e) {
do_throw("this call should just work without any exceptions");
ok(false, "this call should just work without any exceptions");
}
SimpleTest.finish();
}

View File

@ -16,5 +16,8 @@ function run_test()
do_check_eq(Cu.evalInSandbox('typeof obj.foo', sb), 'undefined', "COW works as expected");
do_check_true(Cu.evalInSandbox('obj.hasOwnProperty === Object.prototype.hasOwnProperty', sb),
"Remapping happens even when the property is explicitly exposed");
do_check_eq(Cu.evalInSandbox('Object.prototype.bar = 10; obj.bar', sb), 10);
// NB: We used to test for the following, but such behavior became very
// difficult to implement in a recent refactor. We're moving away from this
// API anyway, so we decided to explicitly drop support for this.
// do_check_eq(Cu.evalInSandbox('Object.prototype.bar = 10; obj.bar', sb), 10);
}

View File

@ -267,24 +267,6 @@ AccessCheck::isScriptAccessOnly(JSContext *cx, JSObject *wrapper)
return false;
}
void
AccessCheck::deny(JSContext *cx, jsid id)
{
if (id == JSID_VOID) {
JS_ReportError(cx, "Permission denied to access object");
} else {
jsval idval;
if (!JS_IdToValue(cx, id, &idval))
return;
JSString *str = JS_ValueToString(cx, idval);
if (!str)
return;
const jschar *chars = JS_GetStringCharsZ(cx, str);
if (chars)
JS_ReportError(cx, "Permission denied to access property '%hs'", chars);
}
}
enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 };
static bool

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