This commit is contained in:
Phil Ringnalda 2015-04-19 20:35:40 -07:00
Родитель 5eda97b0fc 640567be24
Коммит 3addbd04c3
96 изменённых файлов: 2435 добавлений и 1263 удалений

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>

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

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc",
"git_revision": "cb41d8421da5dc4f16ea566ea2917a9b7f828154",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "31b41a3f708e732cbcf8fab8a51d1620ae1ebe82",
"revision": "06ea3f1fb3f2706336c6b32d31663db0ec690cd9",
"repo_path": "integration/gaia-central"
}

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c6b04efa0f31a584e6ee0a46dd2b64c1e3c29adc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -25,6 +25,7 @@
#include "nsCycleCollectionParticipant.h"
#include "mozilla/dom/NameSpaceConstants.h"
#include "nsStringGlue.h"
#include "mozilla/Attributes.h"
class nsIAtom;
class nsIDocument;
@ -262,18 +263,22 @@ protected:
{
}
nsIAtom* mName;
nsIAtom* mPrefix;
// These atoms hold pointers to nsGkAtoms members, and are therefore safe
// as a non-owning reference.
nsIAtom* MOZ_NON_OWNING_REF mName;
nsIAtom* MOZ_NON_OWNING_REF mPrefix;
int32_t mNamespaceID;
uint16_t mNodeType; // As defined by nsIDOMNode.nodeType
const nsAString* mNameString;
nsIAtom* mExtraName; // Only used by PIs and DocTypes
nsIAtom* MOZ_NON_OWNING_REF mExtraName; // Only used by PIs and DocTypes
};
// nsNodeInfoManager needs to pass mInner to the hash table.
friend class ::nsNodeInfoManager;
nsIDocument* mDocument; // Weak. Cache of mOwnerManager->mDocument
// This is a non-owning reference, but it's safe since it's set to nullptr
// by nsNodeInfoManager::DropDocumentReference when the document is destroyed.
nsIDocument* MOZ_NON_OWNING_REF mDocument; // Cache of mOwnerManager->mDocument
NodeInfoInner mInner;

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

@ -33,6 +33,9 @@
GK_ATOM(_empty, "")
GK_ATOM(moz, "_moz")
GK_ATOM(mozframetype, "mozframetype")
GK_ATOM(_moz_abspos, "_moz_activated")
GK_ATOM(_moz_activated, "_moz_activated")
GK_ATOM(_moz_resizing, "_moz_resizing")
GK_ATOM(mozallowfullscreen, "mozallowfullscreen")
GK_ATOM(moztype, "_moz-type")
GK_ATOM(mozdirty, "_moz_dirty")
@ -90,6 +93,7 @@ GK_ATOM(anchor, "anchor")
GK_ATOM(_and, "and")
GK_ATOM(animations, "animations")
GK_ATOM(anonid, "anonid")
GK_ATOM(anonlocation, "anonlocation")
GK_ATOM(any, "any")
GK_ATOM(mozapp, "mozapp")
GK_ATOM(mozwidget, "mozwidget")

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

@ -13676,6 +13676,14 @@ nsGlobalWindow::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel,
aError = widget->BeginMoveDrag(mouseEvent);
}
already_AddRefed<nsWindowRoot>
nsGlobalWindow::GetWindowRoot(mozilla::ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetWindowRoot, (aError), aError, nullptr);
nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
return root.forget().downcast<nsWindowRoot>();
}
//Note: This call will lock the cursor, it will not change as it moves.
//To unlock, the cursor must be set back to CURSOR_AUTO.
NS_IMETHODIMP

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

@ -1098,6 +1098,8 @@ public:
JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aError);
already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
protected:
// Web IDL helpers

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

@ -275,8 +275,10 @@ public:
private:
~nsChildContentList() {}
// The node whose children make up the list (weak reference)
nsINode* mNode;
// The node whose children make up the list.
// This is a non-owning ref which is safe because it's set to nullptr by
// DropReference() by the node slots get destroyed.
nsINode* MOZ_NON_OWNING_REF mNode;
};
// This should be used for any nsINode sub-class that has fields of its own
@ -1976,16 +1978,23 @@ private:
uint32_t mBoolFlags;
protected:
nsIContent* mNextSibling;
nsIContent* mPreviousSibling;
nsIContent* mFirstChild;
// These references are non-owning and safe, as they are managed by
// nsAttrAndChildArray.
nsIContent* MOZ_NON_OWNING_REF mNextSibling;
nsIContent* MOZ_NON_OWNING_REF mPreviousSibling;
// This reference is non-owning and safe, since in the case of documents,
// it is set to null when the document gets destroyed, and in the case of
// other nodes, the children keep the parents alive.
nsIContent* MOZ_NON_OWNING_REF mFirstChild;
union {
// Pointer to our primary frame. Might be null.
nsIFrame* mPrimaryFrame;
// Pointer to the root of our subtree. Might be null.
nsINode* mSubtreeRoot;
// This reference is non-owning and safe, since it either points to the
// object itself, or is reset by ClearSubtreeRootPointer.
nsINode* MOZ_NON_OWNING_REF mSubtreeRoot;
};
// Storage for more members that are usually not needed; allocated lazily.

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

@ -70,3 +70,4 @@ skip-if = buildapp == 'mulet'
[test_fileconstructor_tempfile.xul]
[test_nsITextInputProcessor.xul]
[test_title.xul]
[test_windowroot.xul]

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

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Test window.windowRoot"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
var root = window.windowRoot;
ok(root instanceof WindowRoot, "windowRoot should be a WindowRoot");
]]></script>
</window>

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

@ -38,14 +38,21 @@
};
var dummy = new DummyHelperSubclass();
var isDOMRequestHelperDestroyed = false;
/**
* Init & destroy.
*/
function initDOMRequestHelperTest(aMessages) {
is_loosely(dummy._requests, undefined, "Request is undefined");
// If we haven't initialized the DOMRequestHelper object, its private
// properties will be undefined, but once destroyDOMRequestHelper is
// called, they're set to null.
var expectedPrivatePropertyValues =
isDOMRequestHelperDestroyed ? null : undefined;
is(dummy._requests, expectedPrivatePropertyValues, "Request is expected");
is(dummy._messages, undefined, "Messages is undefined");
is_loosely(dummy._window, undefined, "Window is undefined");
is(dummy._window, expectedPrivatePropertyValues, "Window is expected");
dummy.initDOMRequestHelper(window, aMessages);
@ -58,10 +65,11 @@
function destroyDOMRequestHelperTest() {
dummy.destroyDOMRequestHelper();
isDOMRequestHelperDestroyed = true;
is_loosely(dummy._requests, undefined, "Request is undefined");
is(dummy._requests, null, "Request is null");
is(dummy._messages, undefined, "Messages is undefined");
is_loosely(dummy._window, undefined, "Window is undefined");
is(dummy._window, null, "Window is null");
}
/**

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

@ -8195,8 +8195,8 @@ class CGMemberJITInfo(CGThing):
return ""
def defineJitInfo(self, infoName, opName, opType, infallible, movable,
aliasSet, alwaysInSlot, lazilyInSlot, slotIndex,
returnTypes, args):
eliminatable, aliasSet, alwaysInSlot, lazilyInSlot,
slotIndex, returnTypes, args):
"""
aliasSet is a JSJitInfo::AliasSet value, without the "JSJitInfo::" bit.
@ -8206,12 +8206,14 @@ class CGMemberJITInfo(CGThing):
"""
assert(not movable or aliasSet != "AliasEverything") # Can't move write-aliasing things
assert(not alwaysInSlot or movable) # Things always in slots had better be movable
assert(not eliminatable or aliasSet != "AliasEverything") # Can't eliminate write-aliasing things
assert(not alwaysInSlot or eliminatable) # Things always in slots had better be eliminatable
def jitInfoInitializer(isTypedMethod):
initializer = fill(
"""
{
{ ${opName} },
{ ${opName} },
prototypes::id::${name},
PrototypeTraits<prototypes::id::${name}>::Depth,
JSJitInfo::${opType},
@ -8219,6 +8221,7 @@ class CGMemberJITInfo(CGThing):
${returnType}, /* returnType. Not relevant for setters. */
${isInfallible}, /* isInfallible. False in setters. */
${isMovable}, /* isMovable. Not relevant for setters. */
${isEliminatable}, /* isEliminatable. Not relevant for setters. */
${isAlwaysInSlot}, /* isAlwaysInSlot. Only relevant for getters. */
${isLazilyCachedInSlot}, /* isLazilyCachedInSlot. Only relevant for getters. */
${isTypedMethod}, /* isTypedMethod. Only relevant for methods. */
@ -8233,12 +8236,17 @@ class CGMemberJITInfo(CGThing):
""),
isInfallible=toStringBool(infallible),
isMovable=toStringBool(movable),
isEliminatable=toStringBool(eliminatable),
isAlwaysInSlot=toStringBool(alwaysInSlot),
isLazilyCachedInSlot=toStringBool(lazilyInSlot),
isTypedMethod=toStringBool(isTypedMethod),
slotIndex=slotIndex)
return initializer.rstrip()
slotAssert = dedent(
"""
static_assert(%s <= JSJitInfo::maxSlotIndex, "We won't fit");
""" % slotIndex)
if args is not None:
argTypes = "%s_argTypes" % infoName
args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args]
@ -8248,21 +8256,27 @@ class CGMemberJITInfo(CGThing):
(argTypes, ", ".join(args)))
return fill(
"""
$*{argTypesDecl}
static const JSTypedMethodJitInfo ${infoName} = {
${jitInfo},
${jitInfo},
${argTypes}
};
$*{slotAssert}
""",
argTypesDecl=argTypesDecl,
infoName=infoName,
jitInfo=jitInfoInitializer(True),
argTypes=argTypes)
jitInfo=indent(jitInfoInitializer(True)),
argTypes=argTypes,
slotAssert=slotAssert)
return ("\n"
"static const JSJitInfo %s = %s;\n"
% (infoName, jitInfoInitializer(False)))
return fill(
"""
static const JSJitInfo ${infoName} = ${jitInfo};
$*{slotAssert}
""",
infoName=infoName,
jitInfo=jitInfoInitializer(False),
slotAssert=slotAssert)
def define(self):
if self.member.isAttr():
@ -8275,6 +8289,7 @@ class CGMemberJITInfo(CGThing):
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
movable = self.mayBeMovable() and getterinfal
eliminatable = self.mayBeEliminatable() and getterinfal
aliasSet = self.aliasSet()
getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
@ -8291,9 +8306,9 @@ class CGMemberJITInfo(CGThing):
slotIndex = "0"
result = self.defineJitInfo(getterinfo, getter, "Getter",
getterinfal, movable, aliasSet,
isAlwaysInSlot, isLazilyCachedInSlot,
slotIndex,
getterinfal, movable, eliminatable,
aliasSet, isAlwaysInSlot,
isLazilyCachedInSlot, slotIndex,
[self.member.type], None)
if (not self.member.readonly or
self.member.getExtendedAttribute("PutForwards") is not None or
@ -8306,7 +8321,7 @@ class CGMemberJITInfo(CGThing):
IDLToCIdentifier(self.member.identifier.name))
# Setters are always fallible, since they have to do a typed unwrap.
result += self.defineJitInfo(setterinfo, setter, "Setter",
False, False, "AliasEverything",
False, False, False, "AliasEverything",
False, False, "0",
[BuiltinTypes[IDLBuiltinType.Types.void]],
None)
@ -8331,6 +8346,7 @@ class CGMemberJITInfo(CGThing):
methodInfal = False
args = None
movable = False
eliminatable = False
else:
sig = sigs[0]
# For methods that affect nothing, it's OK to set movable to our
@ -8340,6 +8356,7 @@ class CGMemberJITInfo(CGThing):
# move effectful things.
hasInfallibleImpl = "infallible" in self.descriptor.getExtendedAttributes(self.member)
movable = self.mayBeMovable() and hasInfallibleImpl
eliminatable = self.mayBeEliminatable() and hasInfallibleImpl
# XXXbz can we move the smarts about fallibility due to arg
# conversions into the JIT, using our new args stuff?
if (len(sig[1]) != 0 or
@ -8356,8 +8373,8 @@ class CGMemberJITInfo(CGThing):
aliasSet = self.aliasSet()
result = self.defineJitInfo(methodinfo, method, "Method",
methodInfal, movable, aliasSet,
False, False, "0",
methodInfal, movable, eliminatable,
aliasSet, False, False, "0",
[s[0] for s in sigs], args)
return result
raise TypeError("Illegal member type to CGPropertyJITInfo")
@ -8378,12 +8395,33 @@ class CGMemberJITInfo(CGThing):
return (affects == "Nothing" and
(dependsOn != "Everything" and dependsOn != "DeviceState"))
def mayBeEliminatable(self):
"""
Returns whether this attribute or method may be eliminatable, just
based on Affects/DependsOn annotations.
"""
# dependsOn shouldn't affect this decision at all, except in jitinfo we
# have no way to express "Depends on everything, affects nothing",
# because we only have three alias set values: AliasNone ("depends on
# nothing, affects nothing"), AliasDOMSets ("depends on DOM sets,
# affects nothing"), AliasEverything ("depends on everything, affects
# everything"). So the [Affects=Nothing, DependsOn=Everything] case
# gets encoded as AliasEverything and defineJitInfo asserts that if our
# alias state is AliasEverything then we're not eliminatable (because it
# thinks we might have side-effects at that point). Bug 1155796 is
# tracking possible solutions for this.
affects = self.member.affects
dependsOn = self.member.dependsOn
assert affects in IDLInterfaceMember.AffectsValues
assert dependsOn in IDLInterfaceMember.DependsOnValues
return affects == "Nothing" and dependsOn != "Everything"
def aliasSet(self):
"""Returns the alias set to store in the jitinfo. This may not be the
"""
Returns the alias set to store in the jitinfo. This may not be the
effective alias set the JIT uses, depending on whether we have enough
information about our args to allow the JIT to prove that effectful
argument conversions won't happen.
"""
dependsOn = self.member.dependsOn
assert dependsOn in IDLInterfaceMember.DependsOnValues

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

@ -19,11 +19,18 @@ template<class T>
class OwningNonNull
{
public:
OwningNonNull()
#ifdef DEBUG
: mInited(false)
#endif
{}
OwningNonNull() {}
MOZ_IMPLICIT OwningNonNull(T& aValue)
{
init(&aValue);
}
template<class U>
MOZ_IMPLICIT OwningNonNull(already_AddRefed<U>&& aValue)
{
init(aValue.take());
}
// This is no worse than get() in terms of const handling.
operator T&() const
@ -40,21 +47,41 @@ public:
return mPtr;
}
void operator=(T* aValue)
// Conversion to bool is always true, so delete to catch errors
explicit operator bool() const = delete;
T*
operator->() const
{
init(aValue);
MOZ_ASSERT(mInited);
MOZ_ASSERT(mPtr, "OwningNonNull<T> was set to null");
return mPtr;
}
void operator=(T& aValue)
OwningNonNull<T>&
operator=(T* aValue)
{
init(aValue);
return *this;
}
OwningNonNull<T>&
operator=(T& aValue)
{
init(&aValue);
return *this;
}
void operator=(const already_AddRefed<T>& aValue)
OwningNonNull<T>&
operator=(const already_AddRefed<T>& aValue)
{
init(aValue);
return *this;
}
// Don't allow assigning nullptr, it makes no sense
void operator=(decltype(nullptr)) = delete;
already_AddRefed<T> forget()
{
#ifdef DEBUG
@ -71,6 +98,12 @@ public:
return mPtr;
}
template<typename U>
void swap(U& aOther)
{
mPtr.swap(aOther);
}
protected:
template<typename U>
void init(U aValue)
@ -84,7 +117,7 @@ protected:
nsRefPtr<T> mPtr;
#ifdef DEBUG
bool mInited;
bool mInited = false;
#endif
};
@ -101,4 +134,30 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
} // namespace dom
} // namespace mozilla
// Declared in nsCOMPtr.h
template<class T> template<class U>
nsCOMPtr<T>::nsCOMPtr(const mozilla::dom::OwningNonNull<U>& aOther)
: nsCOMPtr(aOther.get())
{}
template<class T> template<class U>
nsCOMPtr<T>&
nsCOMPtr<T>::operator=(const mozilla::dom::OwningNonNull<U>& aOther)
{
return operator=(aOther.get());
}
// Declared in nsRefPtr.h
template<class T> template<class U>
nsRefPtr<T>::nsRefPtr(const mozilla::dom::OwningNonNull<U>& aOther)
: nsRefPtr(aOther.get())
{}
template<class T> template<class U>
nsRefPtr<T>&
nsRefPtr<T>::operator=(const mozilla::dom::OwningNonNull<U>& aOther)
{
return operator=(aOther.get());
}
#endif // mozilla_dom_OwningNonNull_h

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

@ -74,9 +74,15 @@ MozCameraTestHardware.prototype = {
},
dispatchEvent: function(evt) {
if (this._handler) {
this._handler.handleEvent(evt);
}
var self = this;
/* We should not dispatch the event in the current thread
context because it may be directly from a driver call
and we could hit a deadlock situation. */
this._window.setTimeout(function() {
if (self._handler) {
self._handler.handleEvent(evt);
}
}, 0);
},
reset: function(aWindow) {

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

@ -958,8 +958,10 @@ nsDOMCameraControl::TakePicture(const CameraPictureOptions& aOptions,
if (s.width && s.height) {
mCameraControl->Set(CAMERA_PARAM_PICTURE_SIZE, s);
}
if (!aOptions.mFileFormat.IsEmpty()) {
mCameraControl->Set(CAMERA_PARAM_PICTURE_FILEFORMAT, aOptions.mFileFormat);
}
mCameraControl->Set(CAMERA_PARAM_PICTURE_ROTATION, aOptions.mRotation);
mCameraControl->Set(CAMERA_PARAM_PICTURE_FILEFORMAT, aOptions.mFileFormat);
mCameraControl->Set(CAMERA_PARAM_PICTURE_DATETIME, aOptions.mDateTime);
mCameraControl->SetLocation(p);
}

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

@ -269,6 +269,8 @@ namespace android {
return 320;
} else if (strcmp(aParameter, "vid.height") == 0) {
return 240;
} else if (strcmp(aParameter, "vid.fps") == 0) {
return 30;
}
return 0;
case CAMCORDER_QUALITY_HIGH:
@ -277,6 +279,8 @@ namespace android {
return 640;
} else if (strcmp(aParameter, "vid.height") == 0) {
return 480;
} else if (strcmp(aParameter, "vid.fps") == 0) {
return 30;
}
return 0;
default:

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

@ -1255,7 +1255,7 @@ nsGonkCameraControl::StopRecordingImpl()
class RecordingComplete : public nsRunnable
{
public:
RecordingComplete(DeviceStorageFile* aFile)
RecordingComplete(already_AddRefed<DeviceStorageFile> aFile)
: mFile(aFile)
{ }
@ -1285,6 +1285,11 @@ nsGonkCameraControl::StopRecordingImpl()
mRecorder->stop();
mRecorder = nullptr;
#else
if (!mVideoFile) {
return NS_OK;
}
#endif
OnRecorderStateChange(CameraControlListener::kRecorderStopped);
{
@ -1299,10 +1304,7 @@ nsGonkCameraControl::StopRecordingImpl()
}
// notify DeviceStorage that the new video file is closed and ready
return NS_DispatchToMainThread(new RecordingComplete(mVideoFile));
#else
return NS_OK;
#endif
return NS_DispatchToMainThread(new RecordingComplete(mVideoFile.forget()));
}
nsresult

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

@ -412,6 +412,32 @@ TestGonkCameraHardware::AutoFocus()
return OK;
}
int
TestGonkCameraHardware::CancelAutoFocus()
{
class Delegate : public ControlMessage
{
public:
Delegate(TestGonkCameraHardware* aTestHw)
: ControlMessage(aTestHw)
{ }
protected:
NS_IMETHOD
RunImpl() override
{
return mJSTestWrapper->CancelAutoFocus();
}
};
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
nsresult rv = WaitWhileRunningOnMainThread(new Delegate(this));
if (NS_WARN_IF(NS_FAILED(rv))) {
return UNKNOWN_ERROR;
}
return OK;
}
int
TestGonkCameraHardware::StartFaceDetection()
{

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

@ -33,6 +33,7 @@ class TestGonkCameraHardware : public android::GonkCameraHardware
public:
virtual nsresult Init() override;
virtual int AutoFocus() override;
virtual int CancelAutoFocus() override;
virtual int StartFaceDetection() override;
virtual int StopFaceDetection() override;
virtual int TakePicture() override;

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

@ -103,6 +103,14 @@ CameraTestSuite.prototype = {
_lowMemSet: false,
_reloading: false,
_setupPermission: function(permission) {
if (!SpecialPowers.hasPermission(permission, document)) {
info("requesting " + permission + " permission");
SpecialPowers.addPermission(permission, true, document);
this._reloading = true;
}
},
/* Returns a promise which is resolved when the test suite is ready
to be executing individual test cases. One may provide the expected
hardware type here if desired; the default is to use the JS test
@ -111,24 +119,28 @@ CameraTestSuite.prototype = {
/* Depending on how we run the mochitest, we may not have the necessary
permissions yet. If we do need to request them, then we have to reload
the window to ensure the reconfiguration propogated properly. */
if (!SpecialPowers.hasPermission("camera", document)) {
info("requesting camera permission");
this._reloading = true;
SpecialPowers.addPermission("camera", true, document);
this._setupPermission("camera");
this._setupPermission("device-storage:videos");
this._setupPermission("device-storage:videos-create");
this._setupPermission("device-storage:videos-write");
if (this._reloading) {
window.location.reload();
return Promise.reject();
}
info("has camera permission");
info("has necessary permissions");
if (!isDefined(hwType)) {
hwType = 'hardware';
}
this._hwType = hwType;
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() {
resolve();
SpecialPowers.pushPrefEnv({'set': [['device.storage.prompt.testing', true]]}, function() {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() {
resolve();
});
});
});
});

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

@ -1,21 +1,20 @@
[DEFAULT]
support-files = camera_common.js
[test_camera_configuration.html]
[test_camera_release.html]
[test_camera_auto_focus.html]
[test_camera_take_picture.html]
[test_camera_record.html]
skip-if = toolkit == 'gonk'
[test_camera_face_detection.html]
[test_camera_fake_parameters.html]
[test_camera_hardware_init_failure.html]
[test_camera.html]
skip-if = toolkit != 'gonk'
[test_camera_2.html]
skip-if = toolkit != 'gonk'
[test_camera_3.html]
skip-if = toolkit != 'gonk'
[test_camera_hardware_init_failure.html]
[test_camera_hardware_failures.html]
[test_bug975472.html]
[test_camera_fake_parameters.html]
[test_camera_hardware_face_detection.html]
[test_camera_hardware_auto_focus_moving_cb.html]
[test_bug1022766.html]
[test_bug1037322.html]
[test_bug1099390.html]
[test_bug1104913.html]
skip-if = toolkit != 'gonk'
[test_camera_bad_initial_config.html]

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

@ -1,63 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 1022766</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('bug-1022766', function() {
function triggerAutoFocus(p) {
return new Promise(function(resolve, reject) {
var firstCall = false;
var secondCall = false;
function end() {
if (firstCall && secondCall) {
resolve();
}
}
// It doesn't matter if the emulator supports focus or not;
// this is just testing the sequencing.
suite.camera.autoFocus().then(function(p) {
ok(false, "First call to autoFocus() succeeded unexpectedly");
firstCall = true;
end();
}, function(e) {
ok(e.name === 'NS_ERROR_IN_PROGRESS', 'First call to autoFocus() failed with: ' + e);
firstCall = true;
end();
});
suite.camera.autoFocus().then(function(p) {
ok(true, "Second call to autoFocus() succeeded");
secondCall = true;
end();
}, function(e) {
ok(false, "Second call to autoFocus() failed unexpectedly with: " + e);
secondCall = true;
end();
});
});
}
return suite.getCamera()
.then(triggerAutoFocus, suite.rejectGetCamera)
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -1,69 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 1037322</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('bug-1037322', function() {
var cameraManager = navigator.mozCameras;
var whichCamera = cameraManager.getListOfCameras()[0];
var postConfig = {
mode: 'picture',
recorderProfile: 'low',
previewSize: {
width: 320,
height: 240
}
};
function resolveGetCamera(p) {
suite.camera = p.camera;
// Check the default configuration
var cfg = p.configuration;
ok(cfg.mode === "unspecified", "Initial mode = " + cfg.mode);
ok(cfg.previewSize.width === 0 && cfg.previewSize.height === 0,
"Initial preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === "default",
"Initial recorder profile = '" + cfg.recorderProfile + "'");
}
function configure(p) {
// Apply our specific configuration
return suite.camera.setConfiguration(postConfig);
}
function resolveConfigure(cfg) {
// Check our specific configuration
ok(cfg.mode === postConfig.mode, "Configured mode = " + cfg.mode);
ok(cfg.previewSize.width === postConfig.previewSize.width &&
cfg.previewSize.height === postConfig.previewSize.height,
"Configured preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === postConfig.recorderProfile,
"Configured recorder profile = '" + cfg.recorderProfile + "'");
}
return cameraManager.getCamera(whichCamera, {mode: 'unspecified'})
.then(resolveGetCamera, suite.rejectGetCamera)
.then(configure)
.then(resolveConfigure, suite.rejectConfigure);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -1,55 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 1099390</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('bug-1099390', function() {
function release(p) {
return new Promise(function(resolve, reject) {
var gotCloseEvent = false;
var gotReleasePromise = false;
var onClosed = function(e) {
suite.camera.removeEventListener('close', onClosed);
ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason);
gotCloseEvent = true;
if (gotReleasePromise) {
resolve();
}
};
suite.camera.addEventListener('close', onClosed);
suite.camera.release().then(function(p) {
ok(true, "released camera");
gotReleasePromise = true;
if (gotCloseEvent) {
resolve();
}
}).catch(reject);
});
}
return suite.getCamera()
.then(release, suite.rejectGetCamera);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -1,20 +1,15 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=940424
-->
<head>
<title>Bug 940424 - Test camera hardware API failure handling</title>
<title>Test for auto focus</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.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=940424">Mozilla Bug 940424</a>
<video id="viewfinder" width = "200" height = "200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
@ -129,39 +124,109 @@ suite.test('auto-focus-failures', function() {
.then(suite.expectedRejectAutoFocus, rejectAutoFocusError)
});
suite.test('take-picture-failures', function() {
function startTakePictureProcessError(p) {
suite.hw.attach({
takePicture: function() {
suite.hw.fireTakePictureError();
suite.test('auto-focus-moving', function() {
function triggerAutoFocusMoving(p) {
var sync = new Promise(function(resolve, reject) {
function onEvent(e) {
suite.camera.removeEventListener('focus', onEvent);
ok(e.newState === 'focusing', 'autofocus event state focusing == ' + e.newState);
resolve();
}
suite.camera.addEventListener('focus', onEvent);
});
return suite.camera.takePicture();
suite.hw.fireAutoFocusMoving(true);
return sync;
}
function rejectTakePictureProcessError(e) {
ok(e.name === 'NS_ERROR_FAILURE', 'takePicture() process should fail: ' + e);
}
function startTakePictureError(p) {
suite.hw.attach({
takePicture: function() {
throw SpecialPowers.Cr.NS_ERROR_FAILURE;
function waitAutoFocusComplete(p) {
var sync = new Promise(function(resolve, reject) {
function onEvent(e) {
suite.camera.removeEventListener('focus', onEvent);
ok(e.newState === 'focused', 'autofocus event state focused == ' + e.newState);
resolve();
}
suite.camera.addEventListener('focus', onEvent);
});
return suite.camera.takePicture();
// Missing the fireAutoFocusComplete but it should timeout on its own
suite.hw.fireAutoFocusMoving(false);
return sync;
}
function rejectTakePictureError(e) {
ok(e.name === 'NS_ERROR_FAILURE', 'takePicture() should fail: ' + e);
function runAutoFocusCycle(p) {
return triggerAutoFocusMoving(p)
.then(waitAutoFocusComplete);
}
/* If the driver doesn't supply an onAutoFocusComplete notification,
gecko will timeout and provide it. After three times, it will no
longer rely upon a timeout and fire it immediately. */
return suite.getCamera()
.then(runAutoFocusCycle)
.then(runAutoFocusCycle)
.then(runAutoFocusCycle)
.then(runAutoFocusCycle);
});
suite.test('auto-focus-interrupted', function() {
// bug 1022766
function triggerAutoFocus(p) {
return new Promise(function(resolve, reject) {
var firstCall = false;
var secondCall = false;
function end() {
if (firstCall && secondCall) {
resolve();
}
}
// It doesn't matter if the emulator supports focus or not;
// this is just testing the sequencing.
suite.camera.autoFocus().then(function(p) {
ok(false, "First call to autoFocus() succeeded unexpectedly");
firstCall = true;
end();
}, function(e) {
ok(e.name === 'NS_ERROR_IN_PROGRESS', 'First call to autoFocus() failed with: ' + e);
firstCall = true;
end();
});
suite.camera.autoFocus().then(function(p) {
ok(true, "Second call to autoFocus() succeeded");
secondCall = true;
end();
}, function(e) {
ok(false, "Second call to autoFocus() failed unexpectedly with: " + e);
secondCall = true;
end();
});
});
}
return suite.getCamera()
.catch(suite.rejectGetCamera)
.then(startTakePictureProcessError)
.then(suite.expectedRejectTakePicture, rejectTakePictureProcessError)
.then(startTakePictureError)
.then(suite.expectedRejectTakePicture, rejectTakePictureError)
.then(triggerAutoFocus, suite.rejectGetCamera)
});
suite.test('cancel-auto-focus', function() {
function cancelAutoFocus(p) {
var promise = new Promise(function(resolve, reject) {
suite.hw.attach({
cancelAutoFocus: function() {
ok(true, 'got cancel auto focus');
resolve();
}
});
});
suite.camera.resumeContinuousFocus();
return promise;
}
return suite.getCamera()
.then(cancelAutoFocus, suite.rejectGetCamera);
});
suite.setup()

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

@ -1,44 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bad initial configuration</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('bad-initial-config', function() {
function getCamera() {
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'foobar',
};
return navigator.mozCameras.getCamera(whichCamera, config);
}
function rejectGetCamera(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"getCamera() failed with: " + error.name);
return Promise.resolve();
}
return getCamera()
.then(suite.expectedRejectGetCamera, rejectGetCamera);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -0,0 +1,545 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for camera configuration</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width="200" height="200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
function verifyConfig(cfg, expConfig)
{
ok(cfg.mode === expConfig.mode, "Configured mode = " + cfg.mode +
", expected = " + expConfig.mode);
ok(cfg.previewSize.width === expConfig.previewSize.width &&
cfg.previewSize.height === expConfig.previewSize.height,
"Configured preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height +
", expected = " + expConfig.previewSize.width + "x" + expConfig.previewSize.height);
ok(cfg.pictureSize.width === expConfig.pictureSize.width &&
cfg.pictureSize.height === expConfig.pictureSize.height,
"Configured picture size = " + cfg.pictureSize.width + "x" + cfg.pictureSize.height +
", expected = " + expConfig.pictureSize.width + "x" + expConfig.pictureSize.height);
ok(cfg.recorderProfile === expConfig.recorderProfile,
"Configured recorder profile = '" + cfg.recorderProfile + "'" +
", expected = '" + expConfig.recorderProfile + "'");
}
function setAndVerifyConfig(setConfig, expConfig)
{
return suite.getCamera(undefined, setConfig)
.catch(suite.rejectGetCamera)
.then(function(p) {
verifyConfig(p.configuration, expConfig);
});
}
suite.test('bad-initial-config', function() {
function getCamera() {
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'foobar',
};
return navigator.mozCameras.getCamera(whichCamera, config);
}
function rejectGetCamera(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"getCamera() failed with: " + error.name);
return Promise.resolve();
}
return getCamera()
.then(suite.expectedRejectGetCamera, rejectGetCamera);
});
suite.test('start-unspecified', function() {
// bug 1037322
var cameraManager = navigator.mozCameras;
var whichCamera = cameraManager.getListOfCameras()[0];
var postConfig = {
mode: 'picture',
recorderProfile: 'low',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 320,
height: 240
}
};
function resolveGetCamera(p) {
suite.camera = p.camera;
// Check the default configuration
var cfg = p.configuration;
ok(cfg.mode === "unspecified", "Initial mode = " + cfg.mode);
ok(cfg.previewSize.width === 0 && cfg.previewSize.height === 0,
"Initial preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === "default",
"Initial recorder profile = '" + cfg.recorderProfile + "'");
}
function configure(p) {
// Apply our specific configuration
return suite.camera.setConfiguration(postConfig);
}
function resolveConfigure(cfg) {
// Check our specific configuration
verifyConfig(cfg, postConfig);
}
return cameraManager.getCamera(whichCamera, {mode: 'unspecified'})
.then(resolveGetCamera, suite.rejectGetCamera)
.then(configure)
.then(resolveConfigure, suite.rejectConfigure);
});
suite.test('picture-mode', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '320x240';
var setConfig = {
mode: 'picture',
previewSize: {
width: 640,
height: 480
}
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 640,
height: 480
}
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('picture-mode-larger-picture-size', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '320x240';
var setConfig = {
mode: 'picture',
previewSize: {
width: 640,
height: 480
}
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 1280,
height: 960
}
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('picture-mode-size-unsupported-big', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '320x240';
var setConfig = {
mode: 'picture',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 2000,
height: 2000
},
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 1280,
height: 960
},
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('picture-mode-size-unsupported', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,100x100,1x1';
suite.hw.params['video-size-values'] = '320x240';
var setConfig = {
mode: 'picture',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 641,
height: 481,
},
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 640,
height: 480
},
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('picture-mode-asr-mismatch', function() {
suite.hw.params['preview-size'] = '320x240';
suite.hw.params['picture-size'] = '640x480';
suite.hw.params['preview-size-values'] = '640x480,320x240,50x50';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,100x100';
suite.hw.params['video-size-values'] = '320x240';
var setConfig = {
mode: 'picture',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 100,
height: 100,
},
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 50,
height: 50
},
pictureSize: {
width: 100,
height: 100,
},
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('picture-mode-update-video-size', function() {
suite.hw.params['preview-size'] = '320x240';
suite.hw.params['picture-size'] = '640x480';
suite.hw.params['video-size'] = '50x50';
suite.hw.params['preview-size-values'] = '640x480,320x240,50x50';
suite.hw.params['video-size-values'] = '1280x960,640x480,320x240,50x50';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,100x100';
var setConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 320,
height: 240,
},
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 320,
height: 240,
},
};
function checkVideoSize(p) {
ok(suite.hw.params['video-size'] === '320x240', 'video size reset with picture mode switch');
}
return setAndVerifyConfig(setConfig, expConfig)
.then(checkVideoSize);
});
suite.test('picture-mode-no-update-video-size', function() {
suite.hw.params['preview-size'] = '320x240';
suite.hw.params['picture-size'] = '640x480';
suite.hw.params['video-size'] = '1280x960';
suite.hw.params['preview-size-values'] = '640x480,320x240,50x50';
suite.hw.params['video-size-values'] = '1280x960,640x480,320x240,50x50';
suite.hw.params['picture-size-values'] = '1280x960,640x480,320x240,100x100';
var setConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 640,
height: 480,
},
};
var expConfig = {
mode: 'picture',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
},
pictureSize: {
width: 640,
height: 480,
},
};
function checkVideoSize(p) {
ok(suite.hw.params['video-size'] === '1280x960', 'video size retained with picture mode switch');
}
return setAndVerifyConfig(setConfig, expConfig)
.then(checkVideoSize);
});
suite.test('video-mode-preview-size', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['recording-hint'] = 'false';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '700x700,640x480,320x240,1x1';
var setConfig = {
mode: 'video',
recorderProfile: 'qvga'
};
var expConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 700,
height: 700
}
};
function checkRecordingHint(p) {
ok(suite.hw.params['recording-hint'] === 'true', 'recording hint enabled');
}
return setAndVerifyConfig(setConfig, expConfig)
.then(checkRecordingHint);
});
suite.test('video-mode', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['video-size'] = '1x1';
suite.hw.params['recording-hint'] = 'false';
suite.hw.params['preferred-preview-size-for-video'] = '640x480';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '700x700,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '700x700,640x480,320x240,1x1';
var setConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
}
};
var expConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 700,
height: 700
}
};
function checkRecordingHint(p) {
ok(suite.hw.params['recording-hint'] === 'true', 'recording hint enabled');
}
return setAndVerifyConfig(setConfig, expConfig)
.then(checkRecordingHint);
});
suite.test('video-mode-larger-preview-size', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['video-size'] = '1x1';
suite.hw.params['recording-hint'] = 'false';
suite.hw.params['preferred-preview-size-for-video'] = '640x480';
suite.hw.params['preview-size-values'] = '640x480,320x240,1x1';
suite.hw.params['picture-size-values'] = '700x700,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '700x700,640x480,320x240,1x1';
var setConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 640,
height: 480
}
};
var expConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
},
pictureSize: {
width: 700,
height: 700
}
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('video-mode-smaller-preview-size', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['video-size'] = '1x1';
suite.hw.params['recording-hint'] = 'false';
suite.hw.params['preferred-preview-size-for-video'] = '640x480';
suite.hw.params['preview-size-values'] = '640x480,320x240,160x120,1x1';
suite.hw.params['picture-size-values'] = '700x700,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '700x700,640x480,320x240,1x1';
var setConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 160,
height: 120
}
};
var expConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 160,
height: 120
},
pictureSize: {
width: 700,
height: 700
}
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.test('video-mode-larger-preview-size-than-preferred', function() {
suite.hw.params['preview-size'] = '1x1';
suite.hw.params['picture-size'] = '1x1';
suite.hw.params['video-size'] = '1x1';
suite.hw.params['recording-hint'] = 'false';
suite.hw.params['preferred-preview-size-for-video'] = '200x200';
suite.hw.params['preview-size-values'] = '640x480,320x240,160x120,1x1';
suite.hw.params['picture-size-values'] = '700x700,640x480,320x240,1x1';
suite.hw.params['video-size-values'] = '700x700,640x480,400x400,320x240,1x1';
var setConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 320,
height: 240
}
};
var expConfig = {
mode: 'video',
recorderProfile: 'qvga',
previewSize: {
width: 160,
height: 120
},
pictureSize: {
width: 700,
height: 700
}
};
return setAndVerifyConfig(setConfig, expConfig);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -92,8 +92,93 @@ function compareFace(aFace, expected)
var suite = new CameraTestSuite();
suite.test('face-detection-op', function() {
function start(p) {
return new Promise(function(resolve, reject) {
suite.hw.attach({
startFaceDetection: function() {
ok(true, "startFaceDetection() requested");
resolve();
}
});
try {
suite.camera.startFaceDetection();
ok(true, "startFaceDetection() succeeded");
} catch(e) {
ok(false, "startFaceDetection() failed with: " + e.name);
resolve();
}
});
}
function stop(p) {
return new Promise(function(resolve, reject) {
suite.hw.attach({
stopFaceDetection: function() {
ok(true, "stopFaceDetection() requested");
resolve();
}
});
try {
suite.camera.stopFaceDetection();
ok(true, "stopFaceDetection() succeeded");
} catch(e) {
ok(false, "stopFaceDetection() failed with: " + e.name);
resolve();
}
});
}
function startFailure(p) {
return new Promise(function(resolve, reject) {
suite.hw.attach({
startFaceDetection: function() {
ok(true, "startFaceDetection() requested and failed");
resolve();
throw SpecialPowers.Cr.NS_ERROR_FAILURE;
}
});
try {
suite.camera.startFaceDetection();
ok(true, "startFaceDetection() succeeded and error swallowed");
} catch(e) {
ok(false, "startFaceDetection() failed with: " + e.name);
resolve();
}
});
}
function stopFailure(p) {
return new Promise(function(resolve, reject) {
suite.hw.attach({
stopFaceDetection: function() {
ok(true, "stopFaceDetection() requested and failed");
resolve();
throw SpecialPowers.Cr.NS_ERROR_FAILURE;
}
});
try {
suite.camera.stopFaceDetection();
ok(true, "stopFaceDetection() succeeded and error swallowed");
} catch(e) {
ok(false, "stopFaceDetection() failed with: " + e.name);
resolve();
}
});
}
return suite.getCamera()
.then(start, suite.rejectGetCamera)
.then(stop)
.then(startFailure)
.then(stopFailure);
});
suite.test('face-detection', function() {
function detectFace(msg, expected) {
function detectFace(msg, given, expected) {
if (expected === undefined) {
expected = given;
}
var sync = new Promise(function(resolve, reject) {
function onEvent(evt) {
try {
@ -108,7 +193,7 @@ suite.test('face-detection', function() {
suite.camera.addEventListener('facesdetected', onEvent);
});
suite.hw.fireFacesDetected(expected);
suite.hw.fireFacesDetected(given);
return sync;
}
@ -220,11 +305,47 @@ suite.test('face-detection', function() {
);
}
function detectOneFaceExcessScore() {
return detectFace('one-face-excess-score',
{
faces: [ {
id: 1,
score: 120,
bounds: {
left: 3,
top: 4,
right: 5,
bottom: 6
},
leftEye: null,
rightEye: null,
mouth: null
} ]
},
{
faces: [ {
id: 1,
score: 100,
bounds: {
left: 3,
top: 4,
right: 5,
bottom: 6
},
leftEye: null,
rightEye: null,
mouth: null
} ]
}
);
}
return suite.getCamera()
.then(detectOneFace, suite.rejectGetCamera)
.then(detectTwoFaces)
.then(detectOneFaceNoFeatures)
.then(detectNoFaces);
.then(detectNoFaces)
.then(detectOneFaceExcessScore);
});
suite.setup()

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

@ -132,6 +132,133 @@ suite.test('fake-low-memory-platform', function() {
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-effects', function() {
var supportedValues = ['none', 'mono', 'negative', 'solarize', 'sepia', 'posterize', 'whiteboard', 'blackboard', 'aqua'];
suite.hw.params['effect'] = 'none';
suite.hw.params['effect-values'] = supportedValues.join(',');
function resolve(p) {
var cap = suite.camera.capabilities;
ok(cap.effects.length == supportedValues.length, "Effects length = " + cap.effects.length);
// make sure expected values are present
supportedValues.forEach(function(val) {
ok(cap.effects.indexOf(val) != -1, "Effect '" + val + "' is present");
});
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-flash-modes', function() {
var supportedValues = ['off', 'auto', 'on', 'red-eye', 'torch'];
suite.hw.params['flash-mode'] = 'auto';
suite.hw.params['flash-mode-values'] = supportedValues.join(',');
function resolve(p) {
var cam = suite.camera;
var cap = cam.capabilities;
ok(cap.flashModes.length == supportedValues.length, "Flash modes length = " + cap.flashModes.length);
// make sure expected values are present
supportedValues.forEach(function(val) {
ok(cap.flashModes.indexOf(val) != -1, "Flash mode '" + val + "' is present");
});
// test setters/getters
cap.flashModes.forEach(function(val, index) {
cam.flashMode = val;
ok(cam.flashMode === val,
"Flash Mode [" + index + "] = " + val + ", cam.flashMode = " + cam.flashMode);
});
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-focus-modes', function() {
var supportedValues = ['auto', 'infinity', 'macro', 'fixed', 'edof', 'continuous-video'];
suite.hw.params['focus-mode'] = 'auto';
suite.hw.params['focus-mode-values'] = supportedValues.join(',');
function resolve(p) {
var cam = suite.camera;
var cap = cam.capabilities;
ok(cap.focusModes.length == supportedValues.length, "Focus modes length = " + cap.focusModes.length);
// make sure expected values are present
supportedValues.forEach(function(val) {
ok(cap.focusModes.indexOf(val) != -1, "Focus mode '" + val + "' is present");
});
// test setters/getters
cap.focusModes.forEach(function(val, index) {
cam.focusMode = val;
ok(cam.focusMode === val,
"Focus Mode [" + index + "] = " + val + ", cam.focusMode = " + cam.focusMode);
});
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-white-balance-modes', function() {
var supportedValues = ['auto', 'incandescent', 'fluorescent', 'warm-fluorescent', 'daylight', 'cloudy-daylight', 'twilight', 'shade'];
suite.hw.params['whitebalance'] = 'auto';
suite.hw.params['whitebalance-values'] = supportedValues.join(',');
function resolve(p) {
var cam = suite.camera;
var cap = cam.capabilities;
ok(cap.whiteBalanceModes.length == supportedValues.length, "White balance modes length = " + cap.whiteBalanceModes.length);
// make sure expected values are present
supportedValues.forEach(function(val) {
ok(cap.whiteBalanceModes.indexOf(val) != -1, "White balance mode '" + val + "' is present");
});
// test setters/getters
cap.whiteBalanceModes.forEach(function(val, index) {
cam.whiteBalanceMode = val;
ok(cam.whiteBalanceMode === val,
"White balance mode [" + index + "] = " + val + ", cam.whiteBalanceMode = " + cam.whiteBalanceMode);
});
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-video-sizes', function() {
var supportedValues = ['auto', 'incandescent', 'fluorescent', 'warm-fluorescent', 'daylight', 'cloudy-daylight', 'twilight', 'shade'];
suite.hw.params['whitebalance'] = 'auto';
suite.hw.params['whitebalance-values'] = supportedValues.join(',');
function resolve(p) {
var cam = suite.camera;
var cap = cam.capabilities;
ok(cap.whiteBalanceModes.length == supportedValues.length, "White balance modes length = " + cap.whiteBalanceModes.length);
// make sure expected values are present
supportedValues.forEach(function(val) {
ok(cap.whiteBalanceModes.indexOf(val) != -1, "White balance mode '" + val + "' is present");
});
// test setters/getters
cap.whiteBalanceModes.forEach(function(val, index) {
cam.whiteBalanceMode = val;
ok(cam.whiteBalanceMode === val,
"White balance mode [" + index + "] = " + val + ", cam.whiteBalanceMode = " + cam.whiteBalanceMode);
});
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-iso', function() {
suite.hw.params['iso'] = 'auto';
suite.hw.params['iso-values'] = 'auto,ISO_HJR,ISO100,foo,ISObar,ISO150moz,ISO200,400,ISO800,1600';
@ -158,9 +285,9 @@ suite.test('fake-iso', function() {
// test setters/getters for individual ISO modes
cap.isoModes.forEach(function(iso, index) {
cam.iso = iso;
ok(cam.iso === iso,
"ISO[" + index + "] = " + iso + ", cam.iso = " + cam.iso);
cam.isoMode = iso;
ok(cam.isoMode === iso,
"ISO[" + index + "] = " + iso + ", cam.iso = " + cam.isoMode);
});
}
@ -168,6 +295,19 @@ suite.test('fake-iso', function() {
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-faces-detected', function() {
suite.hw.params['max-num-detected-faces-hw'] = '5';
function resolve(p) {
var cap = suite.camera.capabilities;
ok(cap.maxDetectedFaces == 5, "maxDetectedFaces = " + cap.maxDetectedFaces);
}
return suite.getCamera()
.then(resolve, suite.rejectGetCamera);
});
suite.test('fake-metering-areas', function() {
suite.hw.params['max-num-metering-areas'] = '1';

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

@ -1,73 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=965421
-->
<head>
<title>Bug 965421 - Test camera hardware API for Auto focus moving Callback</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.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=965421">Mozilla Bug 965421</a>
<video id="viewfinder" width = "200" height = "200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('auto-focus-moving', function() {
function triggerAutoFocusMoving(p) {
var sync = new Promise(function(resolve, reject) {
function onEvent(e) {
suite.camera.removeEventListener('focus', onEvent);
ok(e.newState === 'focusing', 'autofocus event state focusing == ' + e.newState);
resolve();
}
suite.camera.addEventListener('focus', onEvent);
});
suite.hw.fireAutoFocusMoving(true);
return sync;
}
function waitAutoFocusComplete(p) {
var sync = new Promise(function(resolve, reject) {
function onEvent(e) {
suite.camera.removeEventListener('focus', onEvent);
ok(e.newState === 'focused', 'autofocus event state focused == ' + e.newState);
resolve();
}
suite.camera.addEventListener('focus', onEvent);
});
// Missing the fireAutoFocusComplete but it should timeout on its own
suite.hw.fireAutoFocusMoving(false);
return sync;
}
function runAutoFocusCycle(p) {
return triggerAutoFocusMoving(p)
.then(waitAutoFocusComplete);
}
/* If the driver doesn't supply an onAutoFocusComplete notification,
gecko will timeout and provide it. After three times, it will no
longer rely upon a timeout and fire it immediately. */
return suite.getCamera()
.then(runAutoFocusCycle)
.then(runAutoFocusCycle)
.then(runAutoFocusCycle)
.then(runAutoFocusCycle);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Camera Recording</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<video id="viewfinder" width = "200" height = "200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
var baseConfig = {
mode: 'video',
};
var storage = navigator.getDeviceStorage("videos");
suite.test('recording', function() {
storage.delete("test.3gp");
function startRecording(p) {
var eventPromise = new Promise(function(resolve, reject) {
function onEvent(evt) {
ok(evt.newState === 'Started', 'recorder state change event = ' + evt.newState);
suite.camera.removeEventListener('recorderstatechange', onEvent);
resolve();
}
suite.camera.addEventListener('recorderstatechange', onEvent);
});
var domPromise = suite.camera.startRecording({}, storage, "test.3gp");
return Promise.all([domPromise, eventPromise]);
}
function stopRecording(p) {
var eventPromise = new Promise(function(resolve, reject) {
function onEvent(evt) {
ok(evt.newState === 'Stopped', 'recorder state change event = ' + evt.newState);
suite.camera.removeEventListener('recorderstatechange', onEvent);
resolve();
}
suite.camera.addEventListener('recorderstatechange', onEvent);
});
var domPromise = new Promise(function(resolve, reject) {
try {
suite.camera.stopRecording();
resolve();
} catch(e) {
reject(e);
}
});
return Promise.all([domPromise, eventPromise]);
}
return suite.getCamera(undefined, baseConfig)
.then(startRecording, suite.rejectGetCamera)
.then(stopRecording, suite.rejectStartRecording)
.catch(suite.rejectStopRecording);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -18,6 +18,39 @@ function cameraRelease(p) {
return suite.camera.release();
}
suite.test('release-close-event', function() {
// bug 1099390
function release(p) {
return new Promise(function(resolve, reject) {
var gotCloseEvent = false;
var gotReleasePromise = false;
var onClosed = function(e) {
suite.camera.removeEventListener('close', onClosed);
ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason);
gotCloseEvent = true;
if (gotReleasePromise) {
resolve();
}
};
suite.camera.addEventListener('close', onClosed);
suite.camera.release().then(function(p) {
ok(true, "released camera");
gotReleasePromise = true;
if (gotCloseEvent) {
resolve();
}
}).catch(reject);
});
}
return suite.getCamera()
.then(release, suite.rejectGetCamera);
});
suite.test('release-after-release', function() {
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
@ -157,6 +190,33 @@ suite.test('stop-recording-after-release', function() {
.then(stopRecording, suite.rejectRelease);
});
suite.test('face-detection-after-release', function() {
function startFaceDetection(p) {
try {
suite.camera.startFaceDetection();
ok(false, "startFaceDetection() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"startFaceDetection() failed with: " + e.name);
}
}
function stopFaceDetection(p) {
try {
suite.camera.stopFaceDetection();
ok(false, "stopFaceDetection() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"stopFaceDetection() failed with: " + e.name);
}
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(startFaceDetection, suite.rejectRelease)
.then(stopFaceDetection);
});
suite.test('set-configuration-after-release', function() {
function configure(p) {
return suite.camera.setConfiguration(null);

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

@ -0,0 +1,165 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=940424
-->
<head>
<title>Bug 940424 - Test camera hardware API failure handling</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="camera_common.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=940424">Mozilla Bug 940424</a>
<video id="viewfinder" width = "200" height = "200" autoplay></video>
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var suite = new CameraTestSuite();
suite.test('take-picture-failures', function() {
function startTakePictureProcessError(p) {
suite.hw.attach({
takePicture: function() {
suite.hw.fireTakePictureError();
}
});
return suite.camera.takePicture();
}
function rejectTakePictureProcessError(e) {
ok(e.name === 'NS_ERROR_FAILURE', 'takePicture() process should fail: ' + e);
}
function startTakePictureError(p) {
suite.hw.attach({
takePicture: function() {
throw SpecialPowers.Cr.NS_ERROR_FAILURE;
}
});
return suite.camera.takePicture();
}
function rejectTakePictureError(e) {
ok(e.name === 'NS_ERROR_FAILURE', 'takePicture() should fail: ' + e);
}
return suite.getCamera()
.catch(suite.rejectGetCamera)
.then(startTakePictureProcessError)
.then(suite.expectedRejectTakePicture, rejectTakePictureProcessError)
.then(startTakePictureError)
.then(suite.expectedRejectTakePicture, rejectTakePictureError)
});
suite.test('shutter', function() {
function shutter(p) {
return new Promise(function(resolve, reject) {
function onShutter(e) {
ok(true, 'received shutter event');
suite.camera.removeEventListener('shutter', onShutter);
resolve();
}
suite.camera.addEventListener('shutter', onShutter);
suite.hw.fireShutter();
});
}
return suite.getCamera()
.then(shutter, suite.rejectGetCamera)
});
suite.test('take-picture', function() {
suite.hw.params['picture-format-values'] = 'jpeg,png';
suite.hw.params['picture-format'] = 'jpeg';
var config = {
fileFormat: 'png',
latitude: 1.0,
longitude: 2.0,
altitude: 3.0,
timestamp: 4
};
var data = 'this is a test';
var eventPromise;
function takePicture(p) {
eventPromise = new Promise(function(resolve, reject) {
function onPicture(evt) {
ok(true, 'got picture event');
try {
verifyPicture(evt.data);
} catch(e) {
reject(e);
}
suite.camera.removeEventListener('picture', onPicture);
resolve();
}
suite.camera.addEventListener('picture', onPicture);
});
suite.hw.attach({
takePicture: function() {
ok(suite.hw.params['picture-format'] === 'png', "requested format is '" + suite.hw.params['picture-format'] + "'");
suite.hw.fireTakePictureComplete(new window.Blob([data], {'type': config.fileFormat}));
}
});
return suite.camera.takePicture(config);
}
function verifyPicture(blob) {
ok(blob.size == data.length, "picture blob is " + blob.size + " bytes");
ok(blob.type === 'image/' + config.fileFormat, "picture blob format is '" + blob.type + "'");
}
function tookPicture(p) {
ok(true, 'got picture promise');
verifyPicture(p);
return eventPromise;
}
return suite.getCamera()
.then(takePicture, suite.rejectGetCamera)
.then(tookPicture, suite.rejectTakePicture);
});
suite.test('take-picture-no-config', function() {
var data = 'this is a test';
var format = 'jpeg';
suite.hw.params['picture-format-values'] = 'jpeg,png';
suite.hw.params['picture-format'] = format;
function takePicture(p) {
suite.hw.attach({
takePicture: function() {
ok(suite.hw.params['picture-format'] === format, "requested format is '" + suite.hw.params['picture-format'] + "'");
suite.hw.fireTakePictureComplete(new window.Blob([data], {'type': format}));
}
});
return suite.camera.takePicture();
}
function verifyPicture(blob) {
ok(blob.size == data.length, "picture blob is " + blob.size + " bytes");
ok(blob.type === 'image/' + format, "picture blob format is '" + blob.type + "'");
}
return suite.getCamera()
.then(takePicture, suite.rejectGetCamera)
.then(verifyPicture, suite.rejectTakePicture);
});
suite.setup()
.then(suite.run);
</script>
</body>
</html>

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

@ -654,6 +654,7 @@ DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
}
if (!data) {
aRetval.setNull();
return;
}

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

@ -168,7 +168,7 @@ function test_DataTransfer(dt)
is(dt.getData(""), "", "invalid type getData"),
dt.mozSetDataAt("", "Invalid Type", 0);
is(dt.types.length, 0, "invalid type setDataAt");
is(dt.mozGetDataAt("", 0), undefined, "invalid type getDataAt"),
is(dt.mozGetDataAt("", 0), null, "invalid type getDataAt"),
// similar with clearDataAt and getDataAt
expectError(function() dt.mozGetDataAt("text/plain", 1),
@ -205,7 +205,7 @@ function test_DataTransfer(dt)
var draggable = $("draggable");
dt.setData("application/-moz-node", draggable);
checkOneDataItem(dt, ["text/plain", "text/html", "application/-moz-node"],
["New Text", "<strong>Modified Text</strong>", draggable],
["New Text", "<strong>Modified Text</strong>", draggable.toString()],
0, "added node");
dt.clearData(""); // null means clear all
@ -501,8 +501,8 @@ function checkOneDataItem(dt, expectedtypes, expecteddata, index, testid)
checkTypes(dt, expectedtypes, index, testid);
for (var f = 0; f < expectedtypes.length; f++) {
if (index == 0)
is_loosely(dt.getData(expectedtypes[f]), expecteddata[f], testid + " getData " + expectedtypes[f]);
is_loosely(dt.mozGetDataAt(expectedtypes[f], index), expecteddata[f] ? expecteddata[f] : null,
is(dt.getData(expectedtypes[f]), expecteddata[f], testid + " getData " + expectedtypes[f]);
is(dt.mozGetDataAt(expectedtypes[f], index), expecteddata[f] ? expecteddata[f] : null,
testid + " getDataAt " + expectedtypes[f]);
}
}

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

@ -401,6 +401,12 @@ partial interface Window {
[ChromeOnly, Throws] readonly attribute object? __content;
[Throws, ChromeOnly] any getInterface(IID iid);
/**
* Same as nsIDOMWindow.windowRoot, useful for event listener targeting.
*/
[ChromeOnly, Throws]
readonly attribute WindowRoot? windowRoot;
};
Window implements TouchEventHandlers;

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

@ -88,20 +88,17 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
NS_ENSURE_SUCCESS(res, res);
nsAutoString positionStr;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
nsCOMPtr<nsINode> node = do_QueryInterface(element);
nsCOMPtr<nsIDOMNode> resultNode;
while (!resultNode && node && !nsEditor::NodeIsType(node, nsGkAtoms::html)) {
res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::position,
while (!resultNode && node && !node->IsHTMLElement(nsGkAtoms::html)) {
res = mHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::position,
positionStr);
NS_ENSURE_SUCCESS(res, res);
if (positionStr.EqualsLiteral("absolute"))
resultNode = node;
resultNode = GetAsDOMNode(node);
else {
nsCOMPtr<nsIDOMNode> parentNode;
res = node->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
node.swap(parentNode);
node = node->GetParentNode();
}
}
@ -195,11 +192,13 @@ NS_IMETHODIMP
nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
int32_t * aZindex)
{
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_STATE(element || !aElement);
nsAutoString zIndexStr;
*aZindex = 0;
nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement,
nsGkAtoms::z_index,
nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(*element,
*nsGkAtoms::z_index,
zIndexStr);
NS_ENSURE_SUCCESS(res, res);
if (zIndexStr.EqualsLiteral("auto")) {
@ -208,24 +207,21 @@ nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
nsCOMPtr<nsIDOMNode> parentNode;
res = aElement->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> node = parentNode;
nsCOMPtr<nsINode> node = do_QueryInterface(parentNode);
nsAutoString positionStr;
while (node &&
zIndexStr.EqualsLiteral("auto") &&
!nsTextEditUtils::IsBody(node)) {
res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::position,
while (node && zIndexStr.EqualsLiteral("auto") &&
!node->IsHTMLElement(nsGkAtoms::body)) {
res = mHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::position,
positionStr);
NS_ENSURE_SUCCESS(res, res);
if (positionStr.EqualsLiteral("absolute")) {
// ah, we found one, what's its z-index ? If its z-index is auto,
// we have to continue climbing the document's tree
res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::z_index,
res = mHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::z_index,
zIndexStr);
NS_ENSURE_SUCCESS(res, res);
}
res = node->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
node = parentNode;
node = node->GetParentNode();
}
}
@ -237,24 +233,24 @@ nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
return NS_OK;
}
nsresult
nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn)
already_AddRefed<Element>
nsHTMLEditor::CreateGrabber(nsINode* aParentNode)
{
// let's create a grabber through the element factory
nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
aParentNode,
NS_LITERAL_STRING("mozGrabber"),
false,
aReturn);
nsCOMPtr<nsIDOMElement> retDOM;
CreateAnonymousElement(NS_LITERAL_STRING("span"), GetAsDOMNode(aParentNode),
NS_LITERAL_STRING("mozGrabber"), false,
getter_AddRefs(retDOM));
NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(retDOM, nullptr);
// add the mouse listener so we can detect a click on a resizer
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(retDOM));
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
mEventListener, false);
return res;
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
return ret.forget();
}
NS_IMETHODIMP
@ -262,7 +258,7 @@ nsHTMLEditor::RefreshGrabber()
{
NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject,
nsresult res = GetPositionAndDimensions(static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject)),
mPositionedObjectX,
mPositionedObjectY,
mPositionedObjectWidth,
@ -276,15 +272,16 @@ nsHTMLEditor::RefreshGrabber()
SetAnonymousElementPosition(mPositionedObjectX+12,
mPositionedObjectY-14,
mGrabber);
static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)));
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::HideGrabber()
{
nsresult res =
mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
nsresult res = mAbsolutelyPositionedObject->UnsetAttr(kNameSpaceID_None,
nsGkAtoms::_moz_abspos,
true);
NS_ENSURE_SUCCESS(res, res);
mAbsolutelyPositionedObject = nullptr;
@ -296,16 +293,12 @@ nsHTMLEditor::HideGrabber()
// are no document observers to notify, but we still want to
// UnbindFromTree.
nsCOMPtr<nsIDOMNode> parentNode;
res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER);
DeleteRefToAnonymousNode(mGrabber, parentContent, ps);
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)), parentContent, ps);
mGrabber = nullptr;
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)), parentContent, ps);
mPositioningShadow = nullptr;
return NS_OK;
@ -314,7 +307,8 @@ nsHTMLEditor::HideGrabber()
NS_IMETHODIMP
nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_ARG_POINTER(element);
if (mGrabber) {
NS_ERROR("call HideGrabber first");
@ -325,19 +319,15 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
nsresult res = CheckPositionedElementBGandFG(aElement, classValue);
NS_ENSURE_SUCCESS(res, res);
res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
classValue);
res = element->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos,
classValue, true);
NS_ENSURE_SUCCESS(res, res);
// first, let's keep track of that element...
mAbsolutelyPositionedObject = aElement;
mAbsolutelyPositionedObject = element;
nsCOMPtr<nsIDOMNode> parentNode;
res = aElement->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
res = CreateGrabber(parentNode, getter_AddRefs(mGrabber));
NS_ENSURE_SUCCESS(res, res);
mGrabber = CreateGrabber(element->GetParentNode());
NS_ENSURE_TRUE(mGrabber, NS_ERROR_FAILURE);
// and set its position
return RefreshGrabber();
@ -346,27 +336,24 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
nsresult
nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
{
nsCOMPtr<nsIDOMNode> parentNode;
nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsINode> parentNode = mGrabber->GetParentNode();
// now, let's create the resizing shadow
res = CreateShadow(getter_AddRefs(mPositioningShadow),
parentNode, mAbsolutelyPositionedObject);
NS_ENSURE_SUCCESS(res,res);
res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
mPositionedObjectX, mPositionedObjectY);
mPositioningShadow = CreateShadow(GetAsDOMNode(parentNode),
static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject)));
NS_ENSURE_TRUE(mPositioningShadow, NS_ERROR_FAILURE);
nsresult res = SetShadowPosition(mPositioningShadow,
mAbsolutelyPositionedObject,
mPositionedObjectX, mPositionedObjectY);
NS_ENSURE_SUCCESS(res,res);
// make the shadow appear
mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
// position it
mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
NS_LITERAL_STRING("width"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::width,
mPositionedObjectWidth);
mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
NS_LITERAL_STRING("height"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::height,
mPositionedObjectHeight);
mIsMoving = true;
@ -411,14 +398,11 @@ nsHTMLEditor::EndMoving()
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIDOMNode> parentNode;
nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIContent> parentContent( do_QueryInterface(parentNode) );
nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)),
parentContent, ps);
mPositioningShadow = nullptr;
}
@ -497,7 +481,7 @@ nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement* aElement,
NS_ENSURE_ARG_POINTER(element);
nsAutoString positionStr;
mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::position,
mHTMLCSSUtils->GetComputedProperty(*element, *nsGkAtoms::position,
positionStr);
bool isPositioned = (positionStr.EqualsLiteral("absolute"));
@ -606,8 +590,9 @@ nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY
NS_IMETHODIMP
nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
{
*aReturn = mAbsolutelyPositionedObject;
NS_IF_ADDREF(*aReturn);
nsCOMPtr<nsIDOMElement> ret =
static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject));
ret.forget(aReturn);
return NS_OK;
}
@ -625,23 +610,25 @@ nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement,
// If the background color is 'auto' and at least one of R G B values of
// the foreground is below #d0, use a white background
// Otherwise don't change background/foreground
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_STATE(element || !aElement);
aReturn.Truncate();
nsAutoString bgImageStr;
nsresult res =
mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::background_image,
mHTMLCSSUtils->GetComputedProperty(*element, *nsGkAtoms::background_image,
bgImageStr);
NS_ENSURE_SUCCESS(res, res);
if (bgImageStr.EqualsLiteral("none")) {
nsAutoString bgColorStr;
res =
mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::backgroundColor,
mHTMLCSSUtils->GetComputedProperty(*element, *nsGkAtoms::backgroundColor,
bgColorStr);
NS_ENSURE_SUCCESS(res, res);
if (bgColorStr.EqualsLiteral("transparent")) {
nsRefPtr<nsComputedDOMStyle> cssDecl =
mHTMLCSSUtils->GetComputedStyle(aElement);
mHTMLCSSUtils->GetComputedStyle(element);
NS_ENSURE_STATE(cssDecl);
// from these declarations, get the one we want and that one only

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

@ -200,7 +200,7 @@ void
nsHTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
nsIDOMEventListener* aListener,
bool aUseCapture,
nsIDOMElement* aElement,
Element* aElement,
nsIContent * aParentContent,
nsIPresShell* aShell)
{
@ -208,7 +208,7 @@ nsHTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
if (evtTarget) {
evtTarget->RemoveEventListener(aEvent, aListener, aUseCapture);
}
DeleteRefToAnonymousNode(aElement, aParentContent, aShell);
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(aElement)), aParentContent, aShell);
}
// Deletes all references to an anonymous element
@ -339,14 +339,14 @@ nsHTMLEditor::CheckSelectionStateForAnonymousButtons(nsISelection * aSelection)
// side effects while this code runs (bug 420439).
if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject &&
absPosElement != mAbsolutelyPositionedObject) {
absPosElement != GetAsDOMNode(mAbsolutelyPositionedObject)) {
res = HideGrabber();
NS_ENSURE_SUCCESS(res, res);
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
}
if (mIsObjectResizingEnabled && mResizedObject &&
mResizedObject != focusElement) {
GetAsDOMNode(mResizedObject) != focusElement) {
res = HideResizers();
NS_ENSURE_SUCCESS(res, res);
NS_ASSERTION(!mResizedObject, "HideResizers failed");
@ -406,7 +406,8 @@ nsHTMLEditor::GetPositionAndDimensions(nsIDOMElement * aElement,
int32_t & aMarginLeft,
int32_t & aMarginTop)
{
NS_ENSURE_ARG_POINTER(aElement);
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_ARG_POINTER(element);
// Is the element positioned ? let's check the cheap way first...
bool isPositioned = false;
@ -415,7 +416,7 @@ nsHTMLEditor::GetPositionAndDimensions(nsIDOMElement * aElement,
if (!isPositioned) {
// hmmm... the expensive way now...
nsAutoString positionStr;
mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::position,
mHTMLCSSUtils->GetComputedProperty(*element, *nsGkAtoms::position,
positionStr);
isPositioned = positionStr.EqualsLiteral("absolute");
}
@ -426,7 +427,7 @@ nsHTMLEditor::GetPositionAndDimensions(nsIDOMElement * aElement,
// Get the all the computed css styles attached to the element node
nsRefPtr<nsComputedDOMStyle> cssDecl =
mHTMLCSSUtils->GetComputedStyle(aElement);
mHTMLCSSUtils->GetComputedStyle(element);
NS_ENSURE_STATE(cssDecl);
aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));

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

@ -301,29 +301,16 @@ nsHTMLCSSUtils::~nsHTMLCSSUtils()
// Answers true if we have some CSS equivalence for the HTML style defined
// by aProperty and/or aAttribute for the node aNode
bool
nsHTMLCSSUtils::IsCSSEditableProperty(nsIDOMNode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute)
{
NS_ASSERTION(aNode, "Shouldn't you pass aNode? - Bug 214025");
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
NS_ENSURE_TRUE(content, false);
return IsCSSEditableProperty(content, aProperty, aAttribute);
}
bool
nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
nsIAtom* aProperty,
nsHTMLCSSUtils::IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
const nsAString* aAttribute)
{
MOZ_ASSERT(aNode);
nsIContent* content = aNode;
nsINode* node = aNode;
// we need an element node here
if (content->NodeType() == nsIDOMNode::TEXT_NODE) {
content = content->GetParent();
NS_ENSURE_TRUE(content, false);
if (node->NodeType() == nsIDOMNode::TEXT_NODE) {
node = node->GetParentNode();
NS_ENSURE_TRUE(node, false);
}
// html inline styles B I TT U STRIKE and COLOR/FACE on FONT
@ -340,43 +327,42 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
// ALIGN attribute on elements supporting it
if (aAttribute && (aAttribute->EqualsLiteral("align")) &&
content->IsAnyOfHTMLElements(nsGkAtoms::div,
nsGkAtoms::p ,
nsGkAtoms::h1,
nsGkAtoms::h2,
nsGkAtoms::h3,
nsGkAtoms::h4,
nsGkAtoms::h5,
nsGkAtoms::h6,
nsGkAtoms::td,
nsGkAtoms::th,
nsGkAtoms::table,
nsGkAtoms::hr,
// brade: for the above, why not use
// nsHTMLEditUtils::SupportsAlignAttr
// brade: but it also checks for tbody,
// tfoot, thead Let's add the following
// elements here even if ALIGN has not the
// same meaning for them
nsGkAtoms::legend,
nsGkAtoms::caption)) {
node->IsAnyOfHTMLElements(nsGkAtoms::div,
nsGkAtoms::p,
nsGkAtoms::h1,
nsGkAtoms::h2,
nsGkAtoms::h3,
nsGkAtoms::h4,
nsGkAtoms::h5,
nsGkAtoms::h6,
nsGkAtoms::td,
nsGkAtoms::th,
nsGkAtoms::table,
nsGkAtoms::hr,
// For the above, why not use
// nsHTMLEditUtils::SupportsAlignAttr?
// It also checks for tbody, tfoot, thead.
// Let's add the following elements here even
// if "align" has a different meaning for them
nsGkAtoms::legend,
nsGkAtoms::caption)) {
return true;
}
if (aAttribute && (aAttribute->EqualsLiteral("valign")) &&
content->IsAnyOfHTMLElements(nsGkAtoms::col,
nsGkAtoms::colgroup,
nsGkAtoms::tbody,
nsGkAtoms::td,
nsGkAtoms::th,
nsGkAtoms::tfoot,
nsGkAtoms::thead,
nsGkAtoms::tr)) {
node->IsAnyOfHTMLElements(nsGkAtoms::col,
nsGkAtoms::colgroup,
nsGkAtoms::tbody,
nsGkAtoms::td,
nsGkAtoms::th,
nsGkAtoms::tfoot,
nsGkAtoms::thead,
nsGkAtoms::tr)) {
return true;
}
// attributes TEXT, BACKGROUND and BGCOLOR on BODY
if (aAttribute && content->IsHTMLElement(nsGkAtoms::body) &&
if (aAttribute && node->IsHTMLElement(nsGkAtoms::body) &&
(aAttribute->EqualsLiteral("text")
|| aAttribute->EqualsLiteral("background")
|| aAttribute->EqualsLiteral("bgcolor"))) {
@ -390,7 +376,7 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
// attributes HEIGHT, WIDTH and NOWRAP on TD and TH
if (aAttribute &&
content->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) &&
node->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) &&
(aAttribute->EqualsLiteral("height")
|| aAttribute->EqualsLiteral("width")
|| aAttribute->EqualsLiteral("nowrap"))) {
@ -398,14 +384,14 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
}
// attributes HEIGHT and WIDTH on TABLE
if (aAttribute && content->IsHTMLElement(nsGkAtoms::table) &&
if (aAttribute && node->IsHTMLElement(nsGkAtoms::table) &&
(aAttribute->EqualsLiteral("height")
|| aAttribute->EqualsLiteral("width"))) {
return true;
}
// attributes SIZE and WIDTH on HR
if (aAttribute && content->IsHTMLElement(nsGkAtoms::hr) &&
if (aAttribute && node->IsHTMLElement(nsGkAtoms::hr) &&
(aAttribute->EqualsLiteral("size")
|| aAttribute->EqualsLiteral("width"))) {
return true;
@ -413,13 +399,13 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
// attribute TYPE on OL UL LI
if (aAttribute &&
content->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul,
nsGkAtoms::li) &&
node->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul,
nsGkAtoms::li) &&
aAttribute->EqualsLiteral("type")) {
return true;
}
if (aAttribute && content->IsHTMLElement(nsGkAtoms::img) &&
if (aAttribute && node->IsHTMLElement(nsGkAtoms::img) &&
(aAttribute->EqualsLiteral("border")
|| aAttribute->EqualsLiteral("width")
|| aAttribute->EqualsLiteral("height"))) {
@ -429,14 +415,14 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
// other elements that we can align using CSS even if they
// can't carry the html ALIGN attribute
if (aAttribute && aAttribute->EqualsLiteral("align") &&
content->IsAnyOfHTMLElements(nsGkAtoms::ul,
nsGkAtoms::ol,
nsGkAtoms::dl,
nsGkAtoms::li,
nsGkAtoms::dd,
nsGkAtoms::dt,
nsGkAtoms::address,
nsGkAtoms::pre)) {
node->IsAnyOfHTMLElements(nsGkAtoms::ul,
nsGkAtoms::ol,
nsGkAtoms::dl,
nsGkAtoms::li,
nsGkAtoms::dd,
nsGkAtoms::dt,
nsGkAtoms::address,
nsGkAtoms::pre)) {
return true;
}
@ -493,26 +479,17 @@ nsHTMLCSSUtils::CreateCSSPropertyTxn(Element& aElement, nsIAtom& aAttribute,
}
nsresult
nsHTMLCSSUtils::GetSpecifiedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
nsAString & aValue)
nsHTMLCSSUtils::GetSpecifiedProperty(nsINode& aNode, nsIAtom& aProperty,
nsAString& aValue)
{
return GetCSSInlinePropertyBase(aNode, aProperty, aValue, eSpecified);
return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eSpecified);
}
nsresult
nsHTMLCSSUtils::GetComputedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
nsAString & aValue)
nsHTMLCSSUtils::GetComputedProperty(nsINode& aNode, nsIAtom& aProperty,
nsAString& aValue)
{
return GetCSSInlinePropertyBase(aNode, aProperty, aValue, eComputed);
}
nsresult
nsHTMLCSSUtils::GetCSSInlinePropertyBase(nsIDOMNode* aNode, nsIAtom* aProperty,
nsAString& aValue,
StyleType aStyleType)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return GetCSSInlinePropertyBase(node, aProperty, aValue, aStyleType);
return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eComputed);
}
nsresult
@ -552,13 +529,6 @@ nsHTMLCSSUtils::GetCSSInlinePropertyBase(nsINode* aNode, nsIAtom* aProperty,
return NS_OK;
}
already_AddRefed<nsComputedDOMStyle>
nsHTMLCSSUtils::GetComputedStyle(nsIDOMElement* aElement)
{
nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
return GetComputedStyle(element);
}
already_AddRefed<nsComputedDOMStyle>
nsHTMLCSSUtils::GetComputedStyle(dom::Element* aElement)
{
@ -596,12 +566,12 @@ nsHTMLCSSUtils::RemoveCSSInlineStyle(nsIDOMNode *aNode, nsIAtom *aProperty, cons
return mHTMLEditor->RemoveContainer(element);
}
// Answers true is the property can be removed by setting a "none" CSS value
// Answers true if the property can be removed by setting a "none" CSS value
// on a node
bool
nsHTMLCSSUtils::IsCSSInvertable(nsIAtom *aProperty, const nsAString *aAttribute)
nsHTMLCSSUtils::IsCSSInvertible(nsIAtom& aProperty, const nsAString* aAttribute)
{
return nsGkAtoms::b == aProperty;
return nsGkAtoms::b == &aProperty;
}
// Get the default browser background color if we need it for GetCSSBackgroundColorState
@ -1031,19 +1001,30 @@ nsHTMLCSSUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
// The nsIContent variant returns aIsSet instead of using an out parameter, and
// does not modify aValue.
bool
nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIContent* aContent,
nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute,
const nsAString& aValue,
StyleType aStyleType)
{
MOZ_ASSERT(aContent && aProperty);
bool isSet;
// Use aValue as only an in param, not in-out
nsAutoString value(aValue);
nsresult res = IsCSSEquivalentToHTMLInlineStyleSet(aContent->AsDOMNode(),
return IsCSSEquivalentToHTMLInlineStyleSet(aNode, aProperty, aAttribute,
value, aStyleType);
}
bool
nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute,
nsAString& aValue,
StyleType aStyleType)
{
MOZ_ASSERT(aNode && aProperty);
bool isSet;
nsresult res = IsCSSEquivalentToHTMLInlineStyleSet(aNode->AsDOMNode(),
aProperty, aAttribute,
isSet, value, aStyleType);
NS_ASSERTION(NS_SUCCEEDED(res), "IsCSSEquivalentToHTMLInlineStyleSet failed");
isSet, aValue, aStyleType);
NS_ENSURE_SUCCESS(res, false);
return isSet;
}

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

@ -83,8 +83,8 @@ public:
* @param aAttribute [IN] a string containing the name of a HTML
* attribute carried by the element above
*/
bool IsCSSEditableProperty(nsIContent* aNode, nsIAtom* aProperty, const nsAString* aAttribute);
bool IsCSSEditableProperty(nsIDOMNode* aNode, nsIAtom* aProperty, const nsAString* aAttribute);
bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
const nsAString* aAttribute);
/** adds/remove a CSS declaration to the STYLE atrribute carried by a given element
*
@ -117,17 +117,17 @@ public:
const nsAString & aProperty,
int32_t aIntValue);
/** gets the specified/computed style value of a CSS property for a given node (or its element
* ancestor if it is not an element)
/** Gets the specified/computed style value of a CSS property for a given
* node (or its element ancestor if it is not an element)
*
* @param aNode [IN] a DOM node
* @param aProperty [IN] an atom containing the CSS property to get
* @param aPropertyValue [OUT] the retrieved value of the property
*/
nsresult GetSpecifiedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
nsAString & aValue);
nsresult GetComputedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
nsAString & aValue);
nsresult GetSpecifiedProperty(nsINode& aNode, nsIAtom& aProperty,
nsAString& aValue);
nsresult GetComputedProperty(nsINode& aNode, nsIAtom& aProperty,
nsAString& aValue);
/** Removes a CSS property from the specified declarations in STYLE attribute
** and removes the node if it is an useless span
@ -146,7 +146,7 @@ public:
* @param aProperty [IN] an atom containing a CSS property
* @param aAttribute [IN] pointer to an attribute name or null if this information is irrelevant
*/
bool IsCSSInvertable(nsIAtom * aProperty, const nsAString * aAttribute);
bool IsCSSInvertible(nsIAtom& aProperty, const nsAString* aAttribute);
/** Get the default browser background color if we need it for GetCSSBackgroundColorState
*
@ -187,12 +187,18 @@ public:
*
* The nsIContent variant returns aIsSet instead of using an out parameter.
*/
bool IsCSSEquivalentToHTMLInlineStyleSet(nsIContent* aContent,
bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
nsIAtom* aProperty,
const nsAString* aAttribute,
const nsAString& aValue,
StyleType aStyleType);
bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
nsIAtom* aProperty,
const nsAString* aAttribute,
nsAString& aValue,
StyleType aStyleType);
nsresult IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
nsIAtom * aHTMLProperty,
const nsAString * aAttribute,
@ -321,8 +327,6 @@ public:
/**
* Gets the computed style for a given element. Can return null.
*/
already_AddRefed<nsComputedDOMStyle>
GetComputedStyle(nsIDOMElement* aElement);
already_AddRefed<nsComputedDOMStyle>
GetComputedStyle(mozilla::dom::Element* aElement);
@ -397,8 +401,6 @@ private:
*/
nsresult GetCSSInlinePropertyBase(nsINode* aNode, nsIAtom* aProperty,
nsAString& aValue, StyleType aStyleType);
nsresult GetCSSInlinePropertyBase(nsIDOMNode* aNode, nsIAtom* aProperty,
nsAString& aValue, StyleType aStyleType);
private:

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

@ -943,9 +943,12 @@ nsHTMLEditRules::GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
return NS_OK;
}
nsIAtom* MarginPropertyAtomForIndent(nsHTMLCSSUtils* aHTMLCSSUtils, nsIDOMNode* aNode) {
static nsIAtom* MarginPropertyAtomForIndent(nsHTMLCSSUtils* aHTMLCSSUtils,
nsIDOMNode* aNode) {
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node || !aNode, nsGkAtoms::marginLeft);
nsAutoString direction;
aHTMLCSSUtils->GetComputedProperty(aNode, nsGkAtoms::direction, direction);
aHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::direction, direction);
return direction.EqualsLiteral("rtl") ?
nsGkAtoms::marginRight : nsGkAtoms::marginLeft;
}
@ -958,9 +961,8 @@ nsHTMLEditRules::GetIndentState(bool *aCanIndent, bool *aCanOutdent)
*aCanOutdent = false;
// get selection
NS_ENSURE_STATE(mHTMLEditor);
nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
NS_ENSURE_STATE(selection);
NS_ENSURE_STATE(mHTMLEditor && mHTMLEditor->GetSelection());
OwningNonNull<Selection> selection = *mHTMLEditor->GetSelection();
// contruct a list of nodes to act on.
nsCOMArray<nsIDOMNode> arrayOfNodes;
@ -977,21 +979,24 @@ nsHTMLEditRules::GetIndentState(bool *aCanIndent, bool *aCanOutdent)
bool useCSS = mHTMLEditor->IsCSSEnabled();
for (i=listCount-1; i>=0; i--)
{
nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
nsCOMPtr<nsINode> curNode = do_QueryInterface(arrayOfNodes[i]);
NS_ENSURE_STATE(curNode || !arrayOfNodes[i]);
if (nsHTMLEditUtils::IsNodeThatCanOutdent(curNode))
{
if (nsHTMLEditUtils::IsNodeThatCanOutdent(GetAsDOMNode(curNode))) {
*aCanOutdent = true;
break;
}
else if (useCSS) {
// we are in CSS mode, indentation is done using the margin-left (or margin-right) property
NS_ENSURE_STATE(mHTMLEditor);
nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, curNode);
nsIAtom* marginProperty =
MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
GetAsDOMNode(curNode));
nsAutoString value;
// retrieve its specified value
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(curNode, marginProperty, value);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode,
*marginProperty, value);
float f;
nsCOMPtr<nsIAtom> unit;
// get its number part and its unit
@ -2006,7 +2011,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
if (wsType == WSType::text) {
// Found normal text to delete.
nsRefPtr<Text> nodeAsText = visNode->GetAsText();
OwningNonNull<Text> nodeAsText = *visNode->GetAsText();
int32_t so = visOffset;
int32_t eo = visOffset + 1;
if (aAction == nsIEditor::ePrevious) {
@ -2040,7 +2045,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
address_of(visNode), &so, address_of(visNode), &eo);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->DeleteText(*nodeAsText, std::min(so, eo),
res = mHTMLEditor->DeleteText(nodeAsText, std::min(so, eo),
DeprecatedAbs(eo - so));
*aHandled = true;
NS_ENSURE_SUCCESS(res, res);
@ -2429,7 +2434,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
uint32_t rangeCount = aSelection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = aSelection->GetRangeAt(rangeIdx);
OwningNonNull<nsRange> range = *aSelection->GetRangeAt(rangeIdx);
// Build a list of nodes in the range
nsTArray<nsCOMPtr<nsINode>> arrayOfNodes;
@ -2474,19 +2479,19 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
if (startNode->GetAsText() &&
startNode->Length() > uint32_t(startOffset)) {
// Delete to last character
nsRefPtr<nsGenericDOMDataNode> dataNode =
static_cast<nsGenericDOMDataNode*>(startNode.get());
OwningNonNull<nsGenericDOMDataNode> dataNode =
*static_cast<nsGenericDOMDataNode*>(startNode.get());
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->DeleteText(*dataNode, startOffset,
res = mHTMLEditor->DeleteText(dataNode, startOffset,
startNode->Length() - startOffset);
NS_ENSURE_SUCCESS(res, res);
}
if (endNode->GetAsText() && endOffset) {
// Delete to first character
NS_ENSURE_STATE(mHTMLEditor);
nsRefPtr<nsGenericDOMDataNode> dataNode =
static_cast<nsGenericDOMDataNode*>(endNode.get());
res = mHTMLEditor->DeleteText(*dataNode, 0, endOffset);
OwningNonNull<nsGenericDOMDataNode> dataNode =
*static_cast<nsGenericDOMDataNode*>(endNode.get());
res = mHTMLEditor->DeleteText(dataNode, 0, endOffset);
NS_ENSURE_SUCCESS(res, res);
}
@ -3056,7 +3061,7 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
if (!aSelection || !aListType || !aCancel || !aHandled) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIAtom> listType = do_GetAtom(*aListType);
OwningNonNull<nsIAtom> listType = do_GetAtom(*aListType);
nsresult res = WillInsert(aSelection, aCancel);
NS_ENSURE_SUCCESS(res, res);
@ -3126,11 +3131,11 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
// make sure we can put a list here
NS_ENSURE_STATE(mHTMLEditor);
if (!mHTMLEditor->CanContainTag(*parent, *listType)) {
if (!mHTMLEditor->CanContainTag(*parent, listType)) {
*aCancel = true;
return NS_OK;
}
res = SplitAsNeeded(*listType, parent, offset);
res = SplitAsNeeded(listType, parent, offset);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> theList =
@ -3300,7 +3305,7 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
// need to make a list to put things in if we haven't already,
if (!curList) {
res = SplitAsNeeded(*listType, curParent, offset);
res = SplitAsNeeded(listType, curParent, offset);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
curList = mHTMLEditor->CreateNode(listType, curParent, offset);
@ -3442,7 +3447,7 @@ nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
bool *aCancel,
bool *aHandled)
{
nsCOMPtr<nsIAtom> blockType = do_GetAtom(*aBlockType);
OwningNonNull<nsIAtom> blockType = do_GetAtom(*aBlockType);
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = false;
@ -3553,7 +3558,7 @@ nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
arrayOfNodes.RemoveObject(brNode);
}
// make sure we can put a block here
res = SplitAsNeeded(*blockType, parent, offset);
res = SplitAsNeeded(blockType, parent, offset);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
theBlock = dont_AddRef(GetAsDOMNode(
@ -4144,7 +4149,9 @@ nsHTMLEditRules::WillOutdent(Selection* aSelection,
nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, curNode);
nsAutoString value;
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(curNode, marginProperty, value);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode_,
*marginProperty,
value);
float f;
nsCOMPtr<nsIAtom> unit;
NS_ENSURE_STATE(mHTMLEditor);
@ -4202,24 +4209,21 @@ nsHTMLEditRules::WillOutdent(Selection* aSelection,
}
// are we inside a blockquote?
nsCOMPtr<nsIDOMNode> n = curNode;
nsCOMPtr<nsIDOMNode> tmp;
nsCOMPtr<nsINode> n = curNode_;
curBlockQuoteIsIndentedWithCSS = false;
// keep looking up the hierarchy as long as we don't hit the body or the
// active editing host or a table element (other than an entire table)
while (!nsTextEditUtils::IsBody(n) && mHTMLEditor &&
mHTMLEditor->IsDescendantOfEditorRoot(n)
&& (nsHTMLEditUtils::IsTable(n) || !nsHTMLEditUtils::IsTableElement(n)))
{
n->GetParentNode(getter_AddRefs(tmp));
if (!tmp) {
while (!n->IsHTMLElement(nsGkAtoms::body) && mHTMLEditor &&
mHTMLEditor->IsDescendantOfEditorRoot(n) &&
(n->IsHTMLElement(nsGkAtoms::table) ||
!nsHTMLEditUtils::IsTableElement(n))) {
if (!n->GetParentNode()) {
break;
}
n = tmp;
if (nsHTMLEditUtils::IsBlockquote(n))
{
n = n->GetParentNode();
if (n->IsHTMLElement(nsGkAtoms::blockquote)) {
// if so, remember it, and remember first node we are taking out of it.
curBlockQuote = n;
curBlockQuote = GetAsDOMNode(n);
firstBQChild = curNode;
lastBQChild = curNode;
break;
@ -4230,14 +4234,15 @@ nsHTMLEditRules::WillOutdent(Selection* aSelection,
nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, curNode);
nsAutoString value;
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(n, marginProperty, value);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*n, *marginProperty,
value);
float f;
nsCOMPtr<nsIAtom> unit;
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
if (f > 0 && !(nsHTMLEditUtils::IsList(curParent) && nsHTMLEditUtils::IsList(curNode)))
{
curBlockQuote = n;
curBlockQuote = GetAsDOMNode(n);
firstBQChild = curNode;
lastBQChild = curNode;
curBlockQuoteIsIndentedWithCSS = true;
@ -4564,7 +4569,7 @@ nsHTMLEditRules::CreateStyleForInsertText(Selection* aSelection,
// never be able to unbold, for instance.
nsAutoString curValue;
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->GetInlinePropertyBase(propItem->tag, &propItem->attr,
res = mHTMLEditor->GetInlinePropertyBase(*propItem->tag, &propItem->attr,
nullptr, &bFirst, &bAny, &bAll,
&curValue, false);
NS_ENSURE_SUCCESS(res, res);
@ -7559,7 +7564,8 @@ nsHTMLEditRules::ReapplyCachedStyles()
if (!bAny) {
// then check typeinstate and html style
NS_ENSURE_STATE(mHTMLEditor);
nsresult res = mHTMLEditor->GetInlinePropertyBase(mCachedStyles[i].tag,
nsresult res = mHTMLEditor->GetInlinePropertyBase(
*mCachedStyles[i].tag,
&(mCachedStyles[i].attr),
&(mCachedStyles[i].value),
&bFirst, &bAny, &bAll,
@ -8969,7 +8975,8 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_
GetAsDOMNode(element));
nsAutoString value;
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(aNode, marginProperty, value);
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*element, *marginProperty,
value);
float f;
nsCOMPtr<nsIAtom> unit;
NS_ENSURE_STATE(mHTMLEditor);

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

@ -739,7 +739,7 @@ AssertParserServiceIsCorrect(nsIAtom* aTag, bool aIsBlock)
* Can be used to determine if a new paragraph should be started.
*/
bool
nsHTMLEditor::NodeIsBlockStatic(const dom::Element* aElement)
nsHTMLEditor::NodeIsBlockStatic(const nsINode* aElement)
{
MOZ_ASSERT(aElement);
@ -795,7 +795,7 @@ nsHTMLEditor::NodeIsBlock(nsIDOMNode *aNode, bool *aIsBlock)
bool
nsHTMLEditor::IsBlockNode(nsINode *aNode)
{
return aNode && aNode->IsElement() && NodeIsBlockStatic(aNode->AsElement());
return aNode && NodeIsBlockStatic(aNode);
}
// Non-static version for the nsIEditor interface and JavaScript
@ -825,7 +825,7 @@ nsHTMLEditor::GetBlockNodeParent(nsINode* aNode)
nsCOMPtr<nsINode> p = aNode->GetParentNode();
while (p) {
if (p->IsElement() && NodeIsBlockStatic(p->AsElement())) {
if (NodeIsBlockStatic(p)) {
return p.forget().downcast<Element>();
}
p = p->GetParentNode();
@ -1731,59 +1731,48 @@ nsHTMLEditor::GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor, boo
// get selection
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
NS_ENSURE_STATE(selection && selection->GetRangeAt(0));
// get selection location
nsCOMPtr<nsIDOMNode> parent;
int32_t offset;
nsresult res = GetStartNodeAndOffset(selection, getter_AddRefs(parent),
&offset);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsINode> parent = selection->GetRangeAt(0)->GetStartParent();
int32_t offset = selection->GetRangeAt(0)->StartOffset();
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
// is the selection collapsed?
nsCOMPtr<nsIDOMNode> nodeToExamine;
nsCOMPtr<nsINode> nodeToExamine;
if (selection->Collapsed() || IsTextNode(parent)) {
// we want to look at the parent and ancestors
nodeToExamine = parent;
} else {
// otherwise we want to look at the first editable node after
// {parent,offset} and its ancestors for divs with alignment on them
nodeToExamine = GetChildAt(parent, offset);
nodeToExamine = parent->GetChildAt(offset);
//GetNextNode(parent, offset, true, address_of(nodeToExamine));
}
NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
// is the node to examine a block ?
bool isBlock;
res = NodeIsBlockStatic(nodeToExamine, &isBlock);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> tmp;
if (aBlockLevel) {
// we are querying the block background (and not the text background), let's
// climb to the block container
nsCOMPtr<nsIDOMNode> blockParent = nodeToExamine;
if (!isBlock) {
nsCOMPtr<Element> blockParent;
if (NodeIsBlockStatic(nodeToExamine)) {
blockParent = nodeToExamine->AsElement();
} else {
blockParent = GetBlockNodeParent(nodeToExamine);
NS_ENSURE_TRUE(blockParent, NS_OK);
}
NS_ENSURE_TRUE(blockParent, NS_OK);
// Make sure to not walk off onto the Document node
nsCOMPtr<nsIDOMElement> element;
do {
// retrieve the computed style of background-color for blockParent
mHTMLCSSUtils->GetComputedProperty(blockParent,
nsGkAtoms::backgroundColor,
mHTMLCSSUtils->GetComputedProperty(*blockParent,
*nsGkAtoms::backgroundColor,
aOutColor);
tmp.swap(blockParent);
res = tmp->GetParentNode(getter_AddRefs(blockParent));
element = do_QueryInterface(blockParent);
blockParent = blockParent->GetParentElement();
// look at parent if the queried color is transparent and if the node to
// examine is not the root of the document
} while (aOutColor.EqualsLiteral("transparent") && element);
} while (aOutColor.EqualsLiteral("transparent") && blockParent);
if (aOutColor.EqualsLiteral("transparent")) {
// we have hit the root of the document and the color is still transparent !
// Grumble... Let's look at the default background color because that's the
@ -1795,15 +1784,11 @@ nsHTMLEditor::GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor, boo
// no, we are querying the text background for the Text Highlight button
if (IsTextNode(nodeToExamine)) {
// if the node of interest is a text node, let's climb a level
res = nodeToExamine->GetParentNode(getter_AddRefs(parent));
NS_ENSURE_SUCCESS(res, res);
nodeToExamine = parent;
nodeToExamine = nodeToExamine->GetParentNode();
}
do {
// is the node to examine a block ?
res = NodeIsBlockStatic(nodeToExamine, &isBlock);
NS_ENSURE_SUCCESS(res, res);
if (isBlock) {
if (NodeIsBlockStatic(nodeToExamine)) {
// yes it is a block; in that case, the text background color is transparent
aOutColor.AssignLiteral("transparent");
break;
@ -1811,16 +1796,14 @@ nsHTMLEditor::GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor, boo
else {
// no, it's not; let's retrieve the computed style of background-color for the
// node to examine
mHTMLCSSUtils->GetComputedProperty(nodeToExamine,
nsGkAtoms::backgroundColor,
mHTMLCSSUtils->GetComputedProperty(*nodeToExamine,
*nsGkAtoms::backgroundColor,
aOutColor);
if (!aOutColor.EqualsLiteral("transparent")) {
break;
}
}
tmp.swap(nodeToExamine);
res = tmp->GetParentNode(getter_AddRefs(nodeToExamine));
NS_ENSURE_SUCCESS(res, res);
nodeToExamine = nodeToExamine->GetParentNode();
} while ( aOutColor.EqualsLiteral("transparent") && nodeToExamine );
}
return NS_OK;
@ -3551,17 +3534,16 @@ nsHTMLEditor::SelectAll()
// this will NOT find aAttribute unless aAttribute has a non-null value
// so singleton attributes like <Table border> will not be matched!
bool nsHTMLEditor::IsTextPropertySetByContent(nsIContent* aContent,
bool nsHTMLEditor::IsTextPropertySetByContent(nsINode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute,
const nsAString* aValue,
nsAString* outValue)
{
MOZ_ASSERT(aContent && aProperty);
MOZ_ASSERT_IF(aAttribute, aValue);
MOZ_ASSERT(aNode && aProperty);
bool isSet;
IsTextPropertySetByContent(aContent->AsDOMNode(), aProperty, aAttribute,
aValue, isSet, outValue);
IsTextPropertySetByContent(aNode->AsDOMNode(), aProperty, aAttribute, aValue,
isSet, outValue);
return isSet;
}

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

@ -257,7 +257,7 @@ public:
/** Internal, static version */
// aElement must not be null.
static bool NodeIsBlockStatic(const mozilla::dom::Element* aElement);
static bool NodeIsBlockStatic(const nsINode* aElement);
static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock);
protected:
virtual ~nsHTMLEditor();
@ -513,7 +513,7 @@ protected:
*
* The nsIContent variant returns aIsSet instead of using an out parameter.
*/
bool IsTextPropertySetByContent(nsIContent* aContent,
bool IsTextPropertySetByContent(nsINode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute,
const nsAString* aValue,
@ -646,12 +646,12 @@ protected:
nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
/* helper routines for inline style */
nsresult SetInlinePropertyOnTextNode( nsIDOMCharacterData *aTextNode,
int32_t aStartOffset,
int32_t aEndOffset,
nsIAtom *aProperty,
const nsAString *aAttribute,
const nsAString *aValue);
nsresult SetInlinePropertyOnTextNode(mozilla::dom::Text& aData,
int32_t aStartOffset,
int32_t aEndOffset,
nsIAtom& aProperty,
const nsAString* aAttribute,
const nsAString& aValue);
nsresult SetInlinePropertyOnNode( nsIDOMNode *aNode,
nsIAtom *aProperty,
const nsAString *aAttribute,
@ -677,7 +677,8 @@ protected:
nsIAtom *aProperty,
const nsAString *aAttribute,
const bool aChildrenOnly = false);
nsresult RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAString *aAttribute);
nsresult RemoveInlinePropertyImpl(nsIAtom* aProperty,
const nsAString* aAttribute);
bool NodeIsProperty(nsIDOMNode *aNode);
bool HasAttr(nsIDOMNode *aNode, const nsAString *aAttribute);
@ -718,14 +719,14 @@ protected:
nsIContent* GetFirstEditableLeaf(nsINode& aNode);
nsIContent* GetLastEditableLeaf(nsINode& aNode);
nsresult GetInlinePropertyBase(nsIAtom *aProperty,
const nsAString *aAttribute,
const nsAString *aValue,
bool *aFirst,
bool *aAny,
bool *aAll,
nsAString *outValue,
bool aCheckDefaults = true);
nsresult GetInlinePropertyBase(nsIAtom& aProperty,
const nsAString* aAttribute,
const nsAString* aValue,
bool* aFirst,
bool* aAny,
bool* aAll,
nsAString* outValue,
bool aCheckDefaults = true);
bool HasStyleOrIdOrClass(mozilla::dom::Element* aElement);
nsresult RemoveElementIfNoStyleOrIdOrClass(nsIDOMNode* aElement);
@ -787,7 +788,7 @@ protected:
void RemoveListenerAndDeleteRef(const nsAString& aEvent,
nsIDOMEventListener* aListener,
bool aUseCapture,
nsIDOMElement* aElement,
mozilla::dom::Element* aElement,
nsIContent* aParentContent,
nsIPresShell* aShell);
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
@ -829,21 +830,21 @@ protected:
/* RESIZING */
nsCOMPtr<nsIDOMElement> mTopLeftHandle;
nsCOMPtr<nsIDOMElement> mTopHandle;
nsCOMPtr<nsIDOMElement> mTopRightHandle;
nsCOMPtr<nsIDOMElement> mLeftHandle;
nsCOMPtr<nsIDOMElement> mRightHandle;
nsCOMPtr<nsIDOMElement> mBottomLeftHandle;
nsCOMPtr<nsIDOMElement> mBottomHandle;
nsCOMPtr<nsIDOMElement> mBottomRightHandle;
nsCOMPtr<mozilla::dom::Element> mTopLeftHandle;
nsCOMPtr<mozilla::dom::Element> mTopHandle;
nsCOMPtr<mozilla::dom::Element> mTopRightHandle;
nsCOMPtr<mozilla::dom::Element> mLeftHandle;
nsCOMPtr<mozilla::dom::Element> mRightHandle;
nsCOMPtr<mozilla::dom::Element> mBottomLeftHandle;
nsCOMPtr<mozilla::dom::Element> mBottomHandle;
nsCOMPtr<mozilla::dom::Element> mBottomRightHandle;
nsCOMPtr<nsIDOMElement> mActivatedHandle;
nsCOMPtr<mozilla::dom::Element> mActivatedHandle;
nsCOMPtr<nsIDOMElement> mResizingShadow;
nsCOMPtr<nsIDOMElement> mResizingInfo;
nsCOMPtr<mozilla::dom::Element> mResizingShadow;
nsCOMPtr<mozilla::dom::Element> mResizingInfo;
nsCOMPtr<nsIDOMElement> mResizedObject;
nsCOMPtr<mozilla::dom::Element> mResizedObject;
nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
nsCOMPtr<nsISelectionListener> mSelectionListenerP;
@ -874,17 +875,18 @@ protected:
nsresult SetAllResizersPosition();
nsresult CreateResizer(nsIDOMElement ** aReturn, int16_t aLocation, nsIDOMNode * aParentNode);
already_AddRefed<mozilla::dom::Element>
CreateResizer(int16_t aLocation, nsIDOMNode* aParentNode);
void SetAnonymousElementPosition(int32_t aX, int32_t aY, nsIDOMElement *aResizer);
nsresult CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
nsIDOMElement * aOriginalObject);
nsresult SetShadowPosition(nsIDOMElement * aShadow,
nsIDOMElement * aOriginalObject,
already_AddRefed<mozilla::dom::Element>
CreateShadow(nsIDOMNode* aParentNode, nsIDOMElement* aOriginalObject);
nsresult SetShadowPosition(mozilla::dom::Element* aShadow,
mozilla::dom::Element* aOriginalObject,
int32_t aOriginalObjectX,
int32_t aOriginalObjectY);
nsresult CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode);
already_AddRefed<mozilla::dom::Element> CreateResizingInfo(nsIDOMNode* aParentNode);
nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
int32_t aW, int32_t aH);
@ -912,13 +914,13 @@ protected:
int32_t mPositionedObjectBorderLeft;
int32_t mPositionedObjectBorderTop;
nsCOMPtr<nsIDOMElement> mAbsolutelyPositionedObject;
nsCOMPtr<nsIDOMElement> mGrabber;
nsCOMPtr<nsIDOMElement> mPositioningShadow;
nsCOMPtr<mozilla::dom::Element> mAbsolutelyPositionedObject;
nsCOMPtr<mozilla::dom::Element> mGrabber;
nsCOMPtr<mozilla::dom::Element> mPositioningShadow;
int32_t mGridSize;
nsresult CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn);
already_AddRefed<mozilla::dom::Element> CreateGrabber(nsINode* aParentNode);
nsresult StartMoving(nsIDOMElement * aHandle);
nsresult SetFinalPosition(int32_t aX, int32_t aY);
void AddPositioningOffset(int32_t & aX, int32_t & aY);

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

@ -154,18 +154,13 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
NS_ENSURE_SUCCESS(res, res);
// check for easy case: both range endpoints in same text node
nsCOMPtr<nsIDOMNode> startNode, endNode;
res = range->GetStartContainer(getter_AddRefs(startNode));
NS_ENSURE_SUCCESS(res, res);
res = range->GetEndContainer(getter_AddRefs(endNode));
NS_ENSURE_SUCCESS(res, res);
if (startNode == endNode && IsTextNode(startNode)) {
int32_t startOffset, endOffset;
range->GetStartOffset(&startOffset);
range->GetEndOffset(&endOffset);
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
res = SetInlinePropertyOnTextNode(nodeAsText, startOffset, endOffset,
aProperty, &aAttribute, &aValue);
nsCOMPtr<nsINode> startNode = range->GetStartParent();
nsCOMPtr<nsINode> endNode = range->GetEndParent();
if (startNode && startNode == endNode && startNode->GetAsText()) {
res = SetInlinePropertyOnTextNode(*startNode->GetAsText(),
range->StartOffset(),
range->EndOffset(),
*aProperty, &aAttribute, aValue);
NS_ENSURE_SUCCESS(res, res);
continue;
}
@ -207,14 +202,11 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
// first check the start parent of the range to see if it needs to
// be separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it).
if (IsTextNode(startNode) && IsEditable(startNode)) {
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
int32_t startOffset;
uint32_t textLen;
range->GetStartOffset(&startOffset);
nodeAsText->GetLength(&textLen);
res = SetInlinePropertyOnTextNode(nodeAsText, startOffset, textLen,
aProperty, &aAttribute, &aValue);
if (startNode && startNode->GetAsText() && IsEditable(startNode)) {
res = SetInlinePropertyOnTextNode(*startNode->GetAsText(),
range->StartOffset(),
startNode->Length(), *aProperty,
&aAttribute, aValue);
NS_ENSURE_SUCCESS(res, res);
}
@ -230,12 +222,10 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
// last check the end parent of the range to see if it needs to
// be separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it).
if (IsTextNode(endNode) && IsEditable(endNode)) {
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
int32_t endOffset;
range->GetEndOffset(&endOffset);
res = SetInlinePropertyOnTextNode(nodeAsText, 0, endOffset,
aProperty, &aAttribute, &aValue);
if (endNode && endNode->GetAsText() && IsEditable(endNode)) {
res = SetInlinePropertyOnTextNode(*endNode->GetAsText(), 0,
range->EndOffset(), *aProperty,
&aAttribute, aValue);
NS_ENSURE_SUCCESS(res, res);
}
}
@ -326,81 +316,67 @@ nsHTMLEditor::IsSimpleModifiableNode(nsIContent* aContent,
nsresult
nsHTMLEditor::SetInlinePropertyOnTextNode( nsIDOMCharacterData *aTextNode,
int32_t aStartOffset,
int32_t aEndOffset,
nsIAtom *aProperty,
const nsAString *aAttribute,
const nsAString *aValue)
nsHTMLEditor::SetInlinePropertyOnTextNode(Text& aText,
int32_t aStartOffset,
int32_t aEndOffset,
nsIAtom& aProperty,
const nsAString* aAttribute,
const nsAString& aValue)
{
MOZ_ASSERT(aValue);
nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
NS_ENSURE_TRUE(textNode, NS_ERROR_NULL_POINTER);
if (!textNode->GetParentNode() ||
!CanContainTag(*textNode->GetParentNode(), *aProperty)) {
if (!aText.GetParentNode() ||
!CanContainTag(*aText.GetParentNode(), aProperty)) {
return NS_OK;
}
// don't need to do anything if no characters actually selected
if (aStartOffset == aEndOffset) return NS_OK;
nsCOMPtr<nsIDOMNode> node = aTextNode;
// don't need to do anything if property already set on node
bool bHasProp;
if (mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
// the HTML styles defined by aProperty/aAttribute has a CSS equivalence
// in this implementation for node; let's check if it carries those css styles
nsAutoString value(*aValue);
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, aAttribute,
bHasProp, value,
nsHTMLCSSUtils::eComputed);
} else {
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, bHasProp);
// Don't need to do anything if no characters actually selected
if (aStartOffset == aEndOffset) {
return NS_OK;
}
if (bHasProp) return NS_OK;
// do we need to split the text node?
uint32_t textLen;
aTextNode->GetLength(&textLen);
// Don't need to do anything if property already set on node
if (mHTMLCSSUtils->IsCSSEditableProperty(&aText, &aProperty, aAttribute)) {
// The HTML styles defined by aProperty/aAttribute have a CSS equivalence
// for node; let's check if it carries those CSS styles
if (mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(&aText, &aProperty,
aAttribute, aValue, nsHTMLCSSUtils::eComputed)) {
return NS_OK;
}
} else if (IsTextPropertySetByContent(&aText, &aProperty, aAttribute,
&aValue)) {
return NS_OK;
}
nsresult res;
if (uint32_t(aEndOffset) != textLen) {
// we need to split off back of text node
nsCOMPtr<nsIDOMNode> tmp;
res = SplitNode(node, aEndOffset, getter_AddRefs(tmp));
NS_ENSURE_SUCCESS(res, res);
node = tmp; // remember left node
// Do we need to split the text node?
ErrorResult rv;
nsRefPtr<Text> text = &aText;
if (uint32_t(aEndOffset) != aText.Length()) {
// We need to split off back of text node
text = SplitNode(aText, aEndOffset, rv)->GetAsText();
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
}
if (aStartOffset) {
// we need to split off front of text node
nsCOMPtr<nsIDOMNode> tmp;
res = SplitNode(node, aStartOffset, getter_AddRefs(tmp));
NS_ENSURE_SUCCESS(res, res);
// We need to split off front of text node
SplitNode(*text, aStartOffset, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
}
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
NS_ENSURE_STATE(content);
if (aAttribute) {
// look for siblings that are correct type of node
nsIContent* sibling = GetPriorHTMLSibling(content);
if (IsSimpleModifiableNode(sibling, aProperty, aAttribute, aValue)) {
// previous sib is already right kind of inline node; slide this over into it
return MoveNode(content, sibling, -1);
// Look for siblings that are correct type of node
nsIContent* sibling = GetPriorHTMLSibling(text);
if (IsSimpleModifiableNode(sibling, &aProperty, aAttribute, &aValue)) {
// Previous sib is already right kind of inline node; slide this over
return MoveNode(text, sibling, -1);
}
sibling = GetNextHTMLSibling(content);
if (IsSimpleModifiableNode(sibling, aProperty, aAttribute, aValue)) {
// following sib is already right kind of inline node; slide this over into it
return MoveNode(content, sibling, 0);
sibling = GetNextHTMLSibling(text);
if (IsSimpleModifiableNode(sibling, &aProperty, aAttribute, &aValue)) {
// Following sib is already right kind of inline node; slide this over
return MoveNode(text, sibling, 0);
}
}
// reparent the node inside inline node with appropriate {attribute,value}
return SetInlinePropertyOnNode(node, aProperty, aAttribute, aValue);
// Reparent the node inside inline node with appropriate {attribute,value}
return SetInlinePropertyOnNode(text, &aProperty, aAttribute, &aValue);
}
@ -859,7 +835,7 @@ nsresult nsHTMLEditor::RemoveStyleInside(nsIDOMNode *aNode,
}
if (!aChildrenOnly &&
mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) {
mHTMLCSSUtils->IsCSSEditableProperty(content, aProperty, aAttribute)) {
// the HTML style defined by aProperty/aAttribute has a CSS equivalence in
// this implementation for the node aNode; let's check if it carries those
// css styles
@ -1097,18 +1073,15 @@ bool nsHTMLEditor::IsAtEndOfNode(nsIDOMNode *aNode, int32_t aOffset)
nsresult
nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
const nsAString *aAttribute,
const nsAString *aValue,
bool *aFirst,
bool *aAny,
bool *aAll,
nsAString *outValue,
nsHTMLEditor::GetInlinePropertyBase(nsIAtom& aProperty,
const nsAString* aAttribute,
const nsAString* aValue,
bool* aFirst,
bool* aAny,
bool* aAll,
nsAString* outValue,
bool aCheckDefaults)
{
NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
nsresult result = NS_OK;
*aAny = false;
*aAll = true;
*aFirst = false;
@ -1118,54 +1091,54 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
bool isCollapsed = selection->Collapsed();
nsCOMPtr<nsIDOMNode> collapsedNode;
nsRefPtr<nsRange> range = selection->GetRangeAt(0);
// XXX: should be a while loop, to get each separate range
// XXX: Should be a while loop, to get each separate range
// XXX: ERROR_HANDLING can currentItem be null?
if (range) {
bool firstNodeInRange = true; // for each range, set a flag
// For each range, set a flag
bool firstNodeInRange = true;
if (isCollapsed) {
range->GetStartContainer(getter_AddRefs(collapsedNode));
nsCOMPtr<nsINode> collapsedNode = range->GetStartParent();
NS_ENSURE_TRUE(collapsedNode, NS_ERROR_FAILURE);
bool isSet, theSetting;
nsString tOutString;
if (aAttribute) {
nsString tString(*aAttribute);
mTypeInState->GetTypingState(isSet, theSetting, aProperty, tString,
mTypeInState->GetTypingState(isSet, theSetting, &aProperty, tString,
&tOutString);
if (outValue) {
outValue->Assign(tOutString);
}
} else {
mTypeInState->GetTypingState(isSet, theSetting, aProperty);
mTypeInState->GetTypingState(isSet, theSetting, &aProperty);
}
if (isSet) {
*aFirst = *aAny = *aAll = theSetting;
return NS_OK;
}
if (mHTMLCSSUtils->IsCSSEditableProperty(collapsedNode, aProperty, aAttribute)) {
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(
collapsedNode, aProperty, aAttribute, isSet, tOutString,
nsHTMLCSSUtils::eComputed);
if (mHTMLCSSUtils->IsCSSEditableProperty(collapsedNode, &aProperty,
aAttribute)) {
*aFirst = *aAny = *aAll =
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(collapsedNode,
&aProperty, aAttribute, tOutString, nsHTMLCSSUtils::eComputed);
if (outValue) {
outValue->Assign(tOutString);
}
*aFirst = *aAny = *aAll = isSet;
return NS_OK;
}
IsTextPropertySetByContent(collapsedNode, aProperty, aAttribute, aValue,
isSet, outValue);
isSet = IsTextPropertySetByContent(collapsedNode, &aProperty,
aAttribute, aValue, outValue);
*aFirst = *aAny = *aAll = isSet;
if (!isSet && aCheckDefaults) {
// style not set, but if it is a default then it will appear if
// content is inserted, so we should report it as set (analogous to
// Style not set, but if it is a default then it will appear if content
// is inserted, so we should report it as set (analogous to
// TypeInState).
int32_t index;
if (aAttribute && TypeInState::FindPropInList(aProperty, *aAttribute,
if (aAttribute && TypeInState::FindPropInList(&aProperty, *aAttribute,
outValue, mDefaultStyles,
index)) {
*aFirst = *aAny = *aAll = true;
@ -1177,49 +1150,36 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
return NS_OK;
}
// non-collapsed selection
nsCOMPtr<nsIContentIterator> iter =
do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
// Non-collapsed selection
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
nsAutoString firstValue, theValue;
nsCOMPtr<nsIDOMNode> endNode;
int32_t endOffset;
result = range->GetEndContainer(getter_AddRefs(endNode));
NS_ENSURE_SUCCESS(result, result);
result = range->GetEndOffset(&endOffset);
NS_ENSURE_SUCCESS(result, result);
nsCOMPtr<nsINode> endNode = range->GetEndParent();
int32_t endOffset = range->EndOffset();
for (iter->Init(range); !iter->IsDone(); iter->Next()) {
if (!iter->GetCurrentNode()->IsContent()) {
continue;
}
nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->AsContent();
nsCOMPtr<nsIDOMNode> node = content->AsDOMNode();
if (nsTextEditUtils::IsBody(node)) {
if (content->IsHTMLElement(nsGkAtoms::body)) {
break;
}
nsCOMPtr<nsIDOMCharacterData> text;
text = do_QueryInterface(content);
// just ignore any non-editable nodes
if (text && (!IsEditable(text) || IsEmptyTextNode(this, content))) {
if (content->GetAsText() && (!IsEditable(content) ||
IsEmptyTextNode(this, content))) {
continue;
}
if (text) {
if (content->GetAsText()) {
if (!isCollapsed && first && firstNodeInRange) {
firstNodeInRange = false;
int32_t startOffset;
range->GetStartOffset(&startOffset);
uint32_t count;
text->GetLength(&count);
if (startOffset == (int32_t)count) {
if (range->StartOffset() == (int32_t)content->Length()) {
continue;
}
} else if (node == endNode && !endOffset) {
} else if (content == endNode && !endOffset) {
continue;
}
} else if (content->IsElement()) {
@ -1229,18 +1189,19 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
bool isSet = false;
if (first) {
if (mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)){
// the HTML styles defined by aProperty/aAttribute has a CSS
if (mHTMLCSSUtils->IsCSSEditableProperty(content, &aProperty,
aAttribute)) {
// The HTML styles defined by aProperty/aAttribute have a CSS
// equivalence in this implementation for node; let's check if it
// carries those css styles
// carries those CSS styles
if (aValue) {
firstValue.Assign(*aValue);
}
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty,
aAttribute, isSet, firstValue, nsHTMLCSSUtils::eComputed);
isSet = mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(content,
&aProperty, aAttribute, firstValue, nsHTMLCSSUtils::eComputed);
} else {
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet,
&firstValue);
isSet = IsTextPropertySetByContent(content, &aProperty, aAttribute,
aValue, &firstValue);
}
*aFirst = isSet;
first = false;
@ -1248,17 +1209,19 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
*outValue = firstValue;
}
} else {
if (mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)){
// the HTML styles defined by aProperty/aAttribute has a CSS equivalence
// in this implementation for node; let's check if it carries those css styles
if (mHTMLCSSUtils->IsCSSEditableProperty(content, &aProperty,
aAttribute)) {
// The HTML styles defined by aProperty/aAttribute have a CSS
// equivalence in this implementation for node; let's check if it
// carries those CSS styles
if (aValue) {
theValue.Assign(*aValue);
}
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty,
aAttribute, isSet, theValue, nsHTMLCSSUtils::eComputed);
isSet = mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(content,
&aProperty, aAttribute, theValue, nsHTMLCSSUtils::eComputed);
} else {
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet,
&theValue);
isSet = IsTextPropertySetByContent(content, &aProperty, aAttribute,
aValue, &theValue);
}
if (firstValue != theValue) {
*aAll = false;
@ -1277,7 +1240,7 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
// set
*aAll = false;
}
return result;
return NS_OK;
}
@ -1295,7 +1258,7 @@ NS_IMETHODIMP nsHTMLEditor::GetInlineProperty(nsIAtom *aProperty,
const nsAString *val = nullptr;
if (!aValue.IsEmpty())
val = &aValue;
return GetInlinePropertyBase( aProperty, att, val, aFirst, aAny, aAll, nullptr);
return GetInlinePropertyBase(*aProperty, att, val, aFirst, aAny, aAll, nullptr);
}
@ -1314,7 +1277,7 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
const nsAString *val = nullptr;
if (!aValue.IsEmpty())
val = &aValue;
return GetInlinePropertyBase( aProperty, att, val, aFirst, aAny, aAll, &outValue);
return GetInlinePropertyBase(*aProperty, att, val, aFirst, aAny, aAll, &outValue);
}
@ -1333,19 +1296,20 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsASt
return RemoveInlinePropertyImpl(aProperty, &aAttribute);
}
nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAString *aAttribute)
nsresult
nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
const nsAString* aAttribute)
{
MOZ_ASSERT_IF(aProperty, aAttribute);
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
ForceCompositionEnd();
nsresult res;
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
bool useCSS = IsCSSEnabled();
if (selection->Collapsed()) {
// manipulating text attributes on a collapsed selection only sets state for the next text insertion
// Manipulating text attributes on a collapsed selection only sets state
// for the next text insertion
// For links, aProperty uses "href", use "a" instead
if (aProperty == nsGkAtoms::href || aProperty == nsGkAtoms::name) {
@ -1361,134 +1325,110 @@ nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAStr
}
nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, EditAction::removeTextProperty, nsIEditor::eNext);
nsAutoRules beginRulesSniffing(this, EditAction::removeTextProperty,
nsIEditor::eNext);
nsAutoSelectionReset selectionResetter(selection, this);
nsAutoTxnsConserveSelection dontSpazMySelection(this);
bool cancel, handled;
nsTextRulesInfo ruleInfo(EditAction::removeTextProperty);
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(res, res);
if (!cancel && !handled)
{
// loop thru the ranges in the selection
if (!cancel && !handled) {
// Loop through the ranges in the selection
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
if (aProperty == nsGkAtoms::name) {
// promote range if it starts or end in a named anchor and we
// want to remove named anchors
// Promote range if it starts or end in a named anchor and we want to
// remove named anchors
res = PromoteRangeIfStartsOrEndsInNamedAnchor(range);
}
else {
// adjust range to include any ancestors who's children are entirely selected
} else {
// Adjust range to include any ancestors whose children are entirely
// selected
res = PromoteInlineRange(range);
}
NS_ENSURE_SUCCESS(res, res);
// remove this style from ancestors of our range endpoints,
// splitting them as appropriate
// Remove this style from ancestors of our range endpoints, splitting
// them as appropriate
res = SplitStyleAboveRange(range, aProperty, aAttribute);
NS_ENSURE_SUCCESS(res, res);
// check for easy case: both range endpoints in same text node
nsCOMPtr<nsIDOMNode> startNode, endNode;
res = range->GetStartContainer(getter_AddRefs(startNode));
NS_ENSURE_SUCCESS(res, res);
res = range->GetEndContainer(getter_AddRefs(endNode));
NS_ENSURE_SUCCESS(res, res);
if ((startNode == endNode) && IsTextNode(startNode))
{
// we're done with this range!
if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(startNode, aProperty, aAttribute)) {
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
// in this implementation for startNode
nsAutoString cssValue;
bool isSet = false;
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(startNode,
aProperty, aAttribute, isSet , cssValue,
nsHTMLCSSUtils::eComputed);
if (isSet) {
// startNode's computed style indicates the CSS equivalence to the HTML style to
// remove is applied; but we found no element in the ancestors of startNode
// carrying specified styles; assume it comes from a rule and let's try to
// insert a span "inverting" the style
nsAutoString value; value.AssignLiteral("-moz-editor-invert-value");
int32_t startOffset, endOffset;
range->GetStartOffset(&startOffset);
range->GetEndOffset(&endOffset);
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
if (mHTMLCSSUtils->IsCSSInvertable(aProperty, aAttribute)) {
SetInlinePropertyOnTextNode(nodeAsText, startOffset, endOffset, aProperty, aAttribute, &value);
// Check for easy case: both range endpoints in same text node
nsCOMPtr<nsINode> startNode = range->GetStartParent();
nsCOMPtr<nsINode> endNode = range->GetEndParent();
if (startNode && startNode == endNode && startNode->GetAsText()) {
// We're done with this range!
if (IsCSSEnabled() &&
mHTMLCSSUtils->IsCSSEditableProperty(startNode, aProperty,
aAttribute)) {
// The HTML style defined by aProperty/aAttribute has a CSS
// equivalence in this implementation for startNode
if (mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(startNode,
aProperty, aAttribute, EmptyString(),
nsHTMLCSSUtils::eComputed)) {
// startNode's computed style indicates the CSS equivalence to the
// HTML style to remove is applied; but we found no element in the
// ancestors of startNode carrying specified styles; assume it
// comes from a rule and try to insert a span "inverting" the style
if (mHTMLCSSUtils->IsCSSInvertible(*aProperty, aAttribute)) {
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
SetInlinePropertyOnTextNode(*startNode->GetAsText(),
range->StartOffset(),
range->EndOffset(), *aProperty,
aAttribute, value);
}
}
}
}
else
{
// not the easy case. range not contained in single text node.
nsCOMPtr<nsIContentIterator> iter =
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE);
} else {
// Not the easy case. Range not contained in single text node.
nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
nsCOMArray<nsIDOMNode> arrayOfNodes;
nsCOMPtr<nsIDOMNode> node;
// iterate range and build up array
iter->Init(range);
while (!iter->IsDone())
{
node = do_QueryInterface(iter->GetCurrentNode());
nsTArray<nsCOMPtr<nsINode>> arrayOfNodes;
// Iterate range and build up array
for (iter->Init(range); !iter->IsDone(); iter->Next()) {
nsCOMPtr<nsINode> node = iter->GetCurrentNode();
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (IsEditable(node))
{
arrayOfNodes.AppendObject(node);
if (IsEditable(node)) {
arrayOfNodes.AppendElement(node);
}
}
iter->Next();
}
// loop through the list, remove the property on each node
int32_t listCount = arrayOfNodes.Count();
int32_t j;
for (j = 0; j < listCount; j++)
{
node = arrayOfNodes[j];
res = RemoveStyleInside(node, aProperty, aAttribute);
// Loop through the list, remove the property on each node
for (auto& node : arrayOfNodes) {
res = RemoveStyleInside(GetAsDOMNode(node), aProperty, aAttribute);
NS_ENSURE_SUCCESS(res, res);
if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
// in this implementation for node
nsAutoString cssValue;
bool isSet = false;
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty,
aAttribute, isSet , cssValue, nsHTMLCSSUtils::eComputed);
if (isSet) {
// startNode's computed style indicates the CSS equivalence to the HTML style to
// remove is applied; but we found no element in the ancestors of startNode
// carrying specified styles; assume it comes from a rule and let's try to
// insert a span "inverting" the style
if (mHTMLCSSUtils->IsCSSInvertable(aProperty, aAttribute)) {
nsAutoString value; value.AssignLiteral("-moz-editor-invert-value");
SetInlinePropertyOnNode(node, aProperty, aAttribute, &value);
}
}
if (IsCSSEnabled() &&
mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty,
aAttribute) &&
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node,
aProperty, aAttribute, EmptyString(),
nsHTMLCSSUtils::eComputed) &&
// startNode's computed style indicates the CSS equivalence to
// the HTML style to remove is applied; but we found no element
// in the ancestors of startNode carrying specified styles;
// assume it comes from a rule and let's try to insert a span
// "inverting" the style
mHTMLCSSUtils->IsCSSInvertible(*aProperty, aAttribute)) {
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
SetInlinePropertyOnNode(node->AsContent(), aProperty,
aAttribute, &value);
}
}
arrayOfNodes.Clear();
}
}
}
if (!cancel)
{
// post-process
if (!cancel) {
// Post-process
res = mRules->DidDoAction(selection, &ruleInfo, res);
NS_ENSURE_SUCCESS(res, res);
}
return res;
return NS_OK;
}
NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize()
@ -1826,7 +1766,7 @@ nsHTMLEditor::GetFontFaceState(bool *aMixed, nsAString &outFace)
bool first, any, all;
NS_NAMED_LITERAL_STRING(attr, "face");
res = GetInlinePropertyBase(nsGkAtoms::font, &attr, nullptr, &first, &any,
res = GetInlinePropertyBase(*nsGkAtoms::font, &attr, nullptr, &first, &any,
&all, &outFace);
NS_ENSURE_SUCCESS(res, res);
if (any && !all) return res; // mixed
@ -1837,7 +1777,7 @@ nsHTMLEditor::GetFontFaceState(bool *aMixed, nsAString &outFace)
}
// if there is no font face, check for tt
res = GetInlinePropertyBase(nsGkAtoms::tt, nullptr, nullptr, &first, &any,
res = GetInlinePropertyBase(*nsGkAtoms::tt, nullptr, nullptr, &first, &any,
&all,nullptr);
NS_ENSURE_SUCCESS(res, res);
if (any && !all) return res; // mixed
@ -1867,7 +1807,7 @@ nsHTMLEditor::GetFontColorState(bool *aMixed, nsAString &aOutColor)
NS_NAMED_LITERAL_STRING(colorStr, "color");
bool first, any, all;
res = GetInlinePropertyBase(nsGkAtoms::font, &colorStr, nullptr, &first,
res = GetInlinePropertyBase(*nsGkAtoms::font, &colorStr, nullptr, &first,
&any, &all, &aOutColor);
NS_ENSURE_SUCCESS(res, res);
if (any && !all) return res; // mixed

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

@ -149,7 +149,7 @@ nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement)
NS_ENSURE_SUCCESS(res, res);
bool hideUI = false;
bool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
bool hideResizersWithInlineTableUI = (GetAsDOMNode(mResizedObject) == tableElement);
if (anonclass.EqualsLiteral("mozTableAddColumnBefore"))
InsertTableColumn(1, false);

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

@ -5,6 +5,7 @@
#include "nsHTMLObjectResizer.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h"
@ -147,20 +148,21 @@ ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
// nsHTMLEditor
// ==================================================================
nsresult
nsHTMLEditor::CreateResizer(nsIDOMElement ** aReturn, int16_t aLocation, nsIDOMNode * aParentNode)
already_AddRefed<Element>
nsHTMLEditor::CreateResizer(int16_t aLocation, nsIDOMNode* aParentNode)
{
nsCOMPtr<nsIDOMElement> retDOM;
nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
aParentNode,
NS_LITERAL_STRING("mozResizer"),
false,
aReturn);
getter_AddRefs(retDOM));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(res, nullptr);
NS_ENSURE_TRUE(retDOM, nullptr);
// add the mouse listener so we can detect a click on a resizer
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(retDOM);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mEventListener,
true);
@ -194,14 +196,16 @@ nsHTMLEditor::CreateResizer(nsIDOMElement ** aReturn, int16_t aLocation, nsIDOMN
break;
}
res = (*aReturn)->SetAttribute(NS_LITERAL_STRING("anonlocation"),
locationStr);
return res;
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
res = ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr,
true);
NS_ENSURE_SUCCESS(res, nullptr);
return ret.forget();
}
nsresult
nsHTMLEditor::CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
nsIDOMElement * aOriginalObject)
already_AddRefed<Element>
nsHTMLEditor::CreateShadow(nsIDOMNode* aParentNode,
nsIDOMElement* aOriginalObject)
{
// let's create an image through the element factory
nsAutoString name;
@ -209,30 +213,28 @@ nsHTMLEditor::CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
name.AssignLiteral("img");
else
name.AssignLiteral("span");
nsresult res = CreateAnonymousElement(name,
aParentNode,
NS_LITERAL_STRING("mozResizingShadow"),
true,
aReturn);
nsCOMPtr<nsIDOMElement> retDOM;
CreateAnonymousElement(name, aParentNode,
NS_LITERAL_STRING("mozResizingShadow"), true,
getter_AddRefs(retDOM));
NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(retDOM, nullptr);
return res;
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
return ret.forget();
}
nsresult
nsHTMLEditor::CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode)
already_AddRefed<Element>
nsHTMLEditor::CreateResizingInfo(nsIDOMNode* aParentNode)
{
// let's create an info box through the element factory
nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
aParentNode,
NS_LITERAL_STRING("mozResizingInfo"),
true,
aReturn);
nsCOMPtr<nsIDOMElement> retDOM;
CreateAnonymousElement(NS_LITERAL_STRING("span"), aParentNode,
NS_LITERAL_STRING("mozResizingInfo"), true,
getter_AddRefs(retDOM));
NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
return res;
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
return ret.forget();
}
nsresult
@ -251,24 +253,26 @@ nsHTMLEditor::SetAllResizersPosition()
nsAutoString value;
float resizerWidth, resizerHeight;
nsCOMPtr<nsIAtom> dummyUnit;
mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsGkAtoms::width, value);
mHTMLCSSUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::width,
value);
mHTMLCSSUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsGkAtoms::height, value);
mHTMLCSSUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::height,
value);
mHTMLCSSUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
int32_t rw = (int32_t)((resizerWidth + 1) / 2);
int32_t rh = (int32_t)((resizerHeight+ 1) / 2);
SetAnonymousElementPosition(x-rw, y-rh, mTopLeftHandle);
SetAnonymousElementPosition(x+w/2-rw, y-rh, mTopHandle);
SetAnonymousElementPosition(x+w-rw-1, y-rh, mTopRightHandle);
SetAnonymousElementPosition(x-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopLeftHandle)));
SetAnonymousElementPosition(x+w/2-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopHandle)));
SetAnonymousElementPosition(x+w-rw-1, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopRightHandle)));
SetAnonymousElementPosition(x-rw, y+h/2-rh, mLeftHandle);
SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, mRightHandle);
SetAnonymousElementPosition(x-rw, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mLeftHandle)));
SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mRightHandle)));
SetAnonymousElementPosition(x-rw, y+h-rh-1, mBottomLeftHandle);
SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, mBottomHandle);
SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, mBottomRightHandle);
SetAnonymousElementPosition(x-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomLeftHandle)));
SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomHandle)));
SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomRightHandle)));
return NS_OK;
}
@ -279,7 +283,7 @@ nsHTMLEditor::RefreshResizers()
// nothing to do if resizers are not displayed...
NS_ENSURE_TRUE(mResizedObject, NS_OK);
nsresult res = GetPositionAndDimensions(mResizedObject,
nsresult res = GetPositionAndDimensions(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
mResizedObjectX,
mResizedObjectY,
mResizedObjectWidth,
@ -319,35 +323,28 @@ nsHTMLEditor::ShowResizersInner(nsIDOMElement *aResizedElement)
NS_ERROR("call HideResizers first");
return NS_ERROR_UNEXPECTED;
}
mResizedObject = aResizedElement;
mResizedObject = do_QueryInterface(aResizedElement);
NS_ENSURE_STATE(mResizedObject);
// The resizers and the shadow will be anonymous siblings of the element.
res = CreateResizer(getter_AddRefs(mTopLeftHandle),
nsIHTMLObjectResizer::eTopLeft, parentNode);
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mTopHandle),
nsIHTMLObjectResizer::eTop, parentNode);
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mTopRightHandle),
nsIHTMLObjectResizer::eTopRight, parentNode);
NS_ENSURE_SUCCESS(res, res);
mTopLeftHandle = CreateResizer(nsIHTMLObjectResizer::eTopLeft, parentNode);
NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
mTopHandle = CreateResizer(nsIHTMLObjectResizer::eTop, parentNode);
NS_ENSURE_TRUE(mTopHandle, NS_ERROR_FAILURE);
mTopRightHandle = CreateResizer(nsIHTMLObjectResizer::eTopRight, parentNode);
NS_ENSURE_TRUE(mTopRightHandle, NS_ERROR_FAILURE);
res = CreateResizer(getter_AddRefs(mLeftHandle),
nsIHTMLObjectResizer::eLeft, parentNode);
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mRightHandle),
nsIHTMLObjectResizer::eRight, parentNode);
NS_ENSURE_SUCCESS(res, res);
mLeftHandle = CreateResizer(nsIHTMLObjectResizer::eLeft, parentNode);
NS_ENSURE_TRUE(mLeftHandle, NS_ERROR_FAILURE);
mRightHandle = CreateResizer(nsIHTMLObjectResizer::eRight, parentNode);
NS_ENSURE_TRUE(mRightHandle, NS_ERROR_FAILURE);
res = CreateResizer(getter_AddRefs(mBottomLeftHandle),
nsIHTMLObjectResizer::eBottomLeft, parentNode);
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mBottomHandle),
nsIHTMLObjectResizer::eBottom, parentNode);
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mBottomRightHandle),
nsIHTMLObjectResizer::eBottomRight, parentNode);
NS_ENSURE_SUCCESS(res, res);
mBottomLeftHandle = CreateResizer(nsIHTMLObjectResizer::eBottomLeft, parentNode);
NS_ENSURE_TRUE(mBottomLeftHandle, NS_ERROR_FAILURE);
mBottomHandle = CreateResizer(nsIHTMLObjectResizer::eBottom, parentNode);
NS_ENSURE_TRUE(mBottomHandle, NS_ERROR_FAILURE);
mBottomRightHandle = CreateResizer(nsIHTMLObjectResizer::eBottomRight, parentNode);
NS_ENSURE_TRUE(mBottomRightHandle, NS_ERROR_FAILURE);
res = GetPositionAndDimensions(aResizedElement,
mResizedObjectX,
@ -365,17 +362,16 @@ nsHTMLEditor::ShowResizersInner(nsIDOMElement *aResizedElement)
NS_ENSURE_SUCCESS(res, res);
// now, let's create the resizing shadow
res = CreateShadow(getter_AddRefs(mResizingShadow), parentNode,
aResizedElement);
NS_ENSURE_SUCCESS(res, res);
mResizingShadow = CreateShadow(parentNode, aResizedElement);
NS_ENSURE_TRUE(mResizingShadow, NS_ERROR_FAILURE);
// and set its position
res = SetShadowPosition(mResizingShadow, mResizedObject,
mResizedObjectX, mResizedObjectY);
NS_ENSURE_SUCCESS(res, res);
// and then the resizing info tooltip
res = CreateResizingInfo(getter_AddRefs(mResizingInfo), parentNode);
NS_ENSURE_SUCCESS(res, res);
mResizingInfo = CreateResizingInfo(parentNode);
NS_ENSURE_TRUE(mResizingInfo, NS_ERROR_FAILURE);
// and listen to the "resize" event on the window first, get the
// window from the document...
@ -404,14 +400,10 @@ nsHTMLEditor::HideResizers(void)
// are no document observers to notify, but we still want to
// UnbindFromTree.
nsresult res;
nsCOMPtr<nsIDOMNode> parentNode;
nsCOMPtr<nsIContent> parentContent;
if (mTopLeftHandle) {
res = mTopLeftHandle->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
parentContent = do_QueryInterface(parentNode);
parentContent = mTopLeftHandle->GetParent();
}
NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
@ -457,7 +449,8 @@ nsHTMLEditor::HideResizers(void)
mResizingInfo = nullptr;
if (mActivatedHandle) {
mActivatedHandle->RemoveAttribute(NS_LITERAL_STRING("_moz_activated"));
mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
true);
mActivatedHandle = nullptr;
}
@ -465,6 +458,7 @@ nsHTMLEditor::HideResizers(void)
nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
DebugOnly<nsresult> res;
if (target && mMouseMotionListenerP)
{
res = target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
@ -484,7 +478,7 @@ nsHTMLEditor::HideResizers(void)
}
mResizeEventListenerP = nullptr;
mResizedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_resizing"));
mResizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true);
mResizedObject = nullptr;
return NS_OK;
@ -494,9 +488,11 @@ void
nsHTMLEditor::HideShadowAndInfo()
{
if (mResizingShadow)
mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
mResizingShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
NS_LITERAL_STRING("hidden"), true);
if (mResizingInfo)
mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
mResizingInfo->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
NS_LITERAL_STRING("hidden"), true);
}
nsresult
@ -509,13 +505,15 @@ nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
int32_t index;
for (index = 0; index < listenersCount; index++) {
listener = objectResizeEventListeners[index];
listener->OnStartResizing(mResizedObject);
listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)));
}
}
mIsResizing = true;
mActivatedHandle = aHandle;
mActivatedHandle->SetAttribute(NS_LITERAL_STRING("_moz_activated"), NS_LITERAL_STRING("true"));
mActivatedHandle = do_QueryInterface(aHandle);
NS_ENSURE_STATE(mActivatedHandle || !aHandle);
mActivatedHandle->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
NS_LITERAL_STRING("true"), true);
// do we want to preserve ratio or not?
bool preserveRatio = nsHTMLEditUtils::IsImage(mResizedObject) &&
@ -551,14 +549,12 @@ nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
}
// make the shadow appear
mResizingShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
mResizingShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
// position it
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
NS_LITERAL_STRING("width"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
mResizedObjectWidth);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
NS_LITERAL_STRING("height"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
mResizedObjectHeight);
// add a mouse move listener to the editor
@ -623,7 +619,8 @@ nsHTMLEditor::MouseUp(int32_t aClientX, int32_t aClientY,
}
else if (mIsMoving || mGrabberClicked) {
if (mIsMoving) {
mPositioningShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
mPositioningShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
NS_LITERAL_STRING("hidden"), true);
SetFinalPosition(aClientX, aClientY);
}
if (mGrabberClicked) {
@ -651,9 +648,6 @@ nsHTMLEditor::SetResizingInfoPosition(int32_t aX, int32_t aY, int32_t aW, int32_
{
nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
NS_NAMED_LITERAL_STRING(leftStr, "left");
NS_NAMED_LITERAL_STRING(topStr, "top");
// Determine the position of the resizing info box based upon the new
// position and size of the element (aX, aY, aW, aH), and which
// resizer is the "activated handle". For example, place the resizing
@ -688,20 +682,17 @@ nsHTMLEditor::SetResizingInfoPosition(int32_t aX, int32_t aY, int32_t aW, int32_
// Offset info box by 20 so it's not directly under the mouse cursor.
const int mouseCursorOffset = 20;
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, leftStr,
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::left,
infoXPosition + mouseCursorOffset);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, topStr,
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::top,
infoYPosition + mouseCursorOffset);
nsCOMPtr<nsIDOMNode> textInfo;
nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> junk;
nsCOMPtr<nsIContent> textInfo = mResizingInfo->GetFirstChild();
ErrorResult rv;
if (textInfo) {
res = mResizingInfo->RemoveChild(textInfo, getter_AddRefs(junk));
NS_ENSURE_SUCCESS(res, res);
mResizingInfo->RemoveChild(*textInfo, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
textInfo = nullptr;
junk = nullptr;
}
nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
@ -722,33 +713,30 @@ nsHTMLEditor::SetResizingInfoPosition(int32_t aX, int32_t aY, int32_t aW, int32_
NS_LITERAL_STRING(")"));
nsCOMPtr<nsIDOMText> nodeAsText;
res = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
nsresult res = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
NS_ENSURE_SUCCESS(res, res);
textInfo = do_QueryInterface(nodeAsText);
res = mResizingInfo->AppendChild(textInfo, getter_AddRefs(junk));
NS_ENSURE_SUCCESS(res, res);
mResizingInfo->AppendChild(*textInfo, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
bool hasClass = false;
if (NS_SUCCEEDED(mResizingInfo->HasAttribute(NS_LITERAL_STRING("class"), &hasClass )) && hasClass)
res = mResizingInfo->RemoveAttribute(NS_LITERAL_STRING("class"));
res = mResizingInfo->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
return res;
}
nsresult
nsHTMLEditor::SetShadowPosition(nsIDOMElement * aShadow,
nsIDOMElement * aOriginalObject,
nsHTMLEditor::SetShadowPosition(Element* aShadow,
Element* aOriginalObject,
int32_t aOriginalObjectX,
int32_t aOriginalObjectY)
{
SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, aShadow);
SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, static_cast<nsIDOMElement*>(GetAsDOMNode(aShadow)));
if (nsHTMLEditUtils::IsImage(aOriginalObject)) {
nsAutoString imageSource;
nsresult res = aOriginalObject->GetAttribute(NS_LITERAL_STRING("src"),
imageSource);
NS_ENSURE_SUCCESS(res, res);
res = aShadow->SetAttribute(NS_LITERAL_STRING("src"), imageSource);
aOriginalObject->GetAttr(kNameSpaceID_None, nsGkAtoms::src, imageSource);
nsresult res = aShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
imageSource, true);
NS_ENSURE_SUCCESS(res, res);
}
return NS_OK;
@ -850,17 +838,13 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
int32_t newWidth = GetNewResizingWidth(clientX, clientY);
int32_t newHeight = GetNewResizingHeight(clientX, clientY);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
leftStr,
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::left,
newX);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
topStr,
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::top,
newY);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
NS_LITERAL_STRING("width"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
newWidth);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
NS_LITERAL_STRING("height"),
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
newHeight);
return SetResizingInfoPosition(newX, newY, newWidth, newHeight);
@ -894,8 +878,10 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
SnapToGrid(newX, newY);
mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, leftStr, newX);
mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, topStr, newY);
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::left,
newX);
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::top,
newY);
}
return NS_OK;
}
@ -909,7 +895,7 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
}
if (mActivatedHandle) {
mActivatedHandle->RemoveAttribute(NS_LITERAL_STRING("_moz_activated"));
mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated, true);
mActivatedHandle = nullptr;
}
@ -933,7 +919,6 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
NS_NAMED_LITERAL_STRING(widthStr, "width");
NS_NAMED_LITERAL_STRING(heightStr, "height");
bool hasAttr = false;
nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
NS_ENSURE_TRUE(resizedObject, );
if (mResizedObjectIsAbsolutelyPositioned) {
@ -943,12 +928,14 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x);
}
if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
RemoveAttribute(mResizedObject, widthStr);
if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) {
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr);
}
hasAttr = false;
if (setHeight && NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
RemoveAttribute(mResizedObject, heightStr);
if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None,
nsGkAtoms::height)) {
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr);
}
if (setWidth)
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
@ -973,12 +960,12 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
if (setWidth) {
nsAutoString w;
w.AppendInt(width);
SetAttribute(mResizedObject, widthStr, w);
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr, w);
}
if (setHeight) {
nsAutoString h;
h.AppendInt(height);
SetAttribute(mResizedObject, heightStr, h);
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr, h);
}
if (setWidth)
@ -995,7 +982,7 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
int32_t index;
for (index = 0; index < listenersCount; index++) {
listener = objectResizeEventListeners[index];
listener->OnEndResizing(mResizedObject,
listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
mResizedObjectWidth, mResizedObjectHeight,
width, height);
}
@ -1011,8 +998,8 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
NS_IMETHODIMP
nsHTMLEditor::GetResizedObject(nsIDOMElement * *aResizedObject)
{
*aResizedObject = mResizedObject;
NS_IF_ADDREF(*aResizedObject);
nsCOMPtr<nsIDOMElement> ret = static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject));
ret.forget(aResizedObject);
return NS_OK;
}

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

@ -5,6 +5,7 @@
#include "nsWSRunObject.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/Assertions.h"
#include "mozilla/Casting.h"
#include "mozilla/mozalloc.h"
@ -605,13 +606,13 @@ already_AddRefed<nsINode>
nsWSRunObject::GetWSBoundingParent()
{
NS_ENSURE_TRUE(mNode, nullptr);
nsCOMPtr<nsINode> wsBoundingParent = mNode;
OwningNonNull<nsINode> wsBoundingParent = *mNode;
while (!IsBlockNode(wsBoundingParent)) {
nsCOMPtr<nsINode> parent = wsBoundingParent->GetParentNode();
if (!parent || !mHTMLEditor->IsEditable(parent)) {
break;
}
wsBoundingParent.swap(parent);
wsBoundingParent = parent;
}
return wsBoundingParent.forget();
}
@ -1013,7 +1014,7 @@ nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
MOZ_ASSERT(aStartNode && aBlockParent);
nsCOMPtr<nsIContent> priorNode = aStartNode->GetPreviousSibling();
nsCOMPtr<nsINode> curNode = aStartNode;
OwningNonNull<nsINode> curNode = *aStartNode;
while (!priorNode) {
// We have exhausted nodes in parent of aStartNode.
nsCOMPtr<nsINode> curParent = curNode->GetParentNode();

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

@ -1432,7 +1432,7 @@ AsyncPanZoomController::GetScrollWheelDelta(const ScrollWheelInput& aEvent) cons
MOZ_ASSERT_UNREACHABLE("unexpected scroll delta type");
}
if (gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
if (mFrameMetrics.GetIsRoot() && gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
// Only apply delta multipliers if we're increasing the delta.
double hfactor = double(gfxPrefs::MouseWheelRootHScrollDeltaFactor()) / 100;
double vfactor = double(gfxPrefs::MouseWheelRootVScrollDeltaFactor()) / 100;

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

@ -99,7 +99,6 @@ public:
bool hasBlocksInRange = false;
endBlock = aEnd >> BLOCK_INDEX_SHIFT;
blockIndex = startBlock;
for (blockIndex = startBlock; blockIndex <= endBlock; blockIndex++) {
if (blockIndex < blockLen && mBlocks[blockIndex])
hasBlocksInRange = true;

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

@ -715,6 +715,8 @@ NewImageChannel(nsIChannel** aResult,
nsIPrincipal* aLoadingPrincipal,
nsISupports* aRequestingContext)
{
MOZ_ASSERT(aResult);
nsresult rv;
nsCOMPtr<nsIHttpChannel> newHttpChannel;

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

@ -16,6 +16,7 @@ namespace JS {
_(GetProp_ArgumentsCallee) \
_(GetProp_InferredConstant) \
_(GetProp_Constant) \
_(GetProp_StaticName) \
_(GetProp_SimdGetter) \
_(GetProp_TypedObject) \
_(GetProp_DefiniteSlot) \

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

@ -0,0 +1,11 @@
var global = newGlobal();
var arrayIter = (new global.Array())[global.Symbol.iterator]();
var ArrayIteratorPrototype = Object.getPrototypeOf(arrayIter);
var arrayIterProtoBase = Object.getPrototypeOf(ArrayIteratorPrototype);
var IteratorPrototype = arrayIterProtoBase;
delete IteratorPrototype.next;
var obj = global.eval('({a: 1})')
for (var x in obj) {}
assertEq(x, "a");

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

@ -10014,6 +10014,14 @@ IonBuilder::jsop_getprop(PropertyName* name)
return resumeAfter(call) && pushTypeBarrier(call, types, BarrierKind::TypeSet);
}
// Try to optimize accesses on outer window proxies, for example window.foo.
// This needs to come before the various strategies getPropTryInnerize tries
// internally, since some of those strategies will "succeed" in silly ways
// even for an outer object.
trackOptimizationAttempt(TrackedStrategy::GetProp_Innerize);
if (!getPropTryInnerize(&emitted, obj, name, types) || emitted)
return emitted;
// Try to hardcode known constants.
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
@ -10049,11 +10057,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
if (!getPropTryInlineAccess(&emitted, obj, name, barrier, types) || emitted)
return emitted;
// Try to optimize accesses on outer window proxies, for example window.foo.
trackOptimizationAttempt(TrackedStrategy::GetProp_Innerize);
if (!getPropTryInnerize(&emitted, obj, name, types) || emitted)
return emitted;
// Try to emit a polymorphic cache.
trackOptimizationAttempt(TrackedStrategy::GetProp_InlineCache);
if (!getPropTryCache(&emitted, obj, name, barrier, types) || emitted)
@ -11051,12 +11054,20 @@ IonBuilder::getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* na
// possible the global property's HeapTypeSet has not been initialized
// yet. In this case we'll fall back to getPropTryCache for now.
// Note that it's important that we do this _before_ we'd try to
// do the optimizations below on obj normally, since some of those
// optimizations have fallback paths that are slower than the path
// we'd produce here.
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
if (!getPropTryConstant(emitted, inner, name, types) || *emitted)
return *emitted;
trackOptimizationAttempt(TrackedStrategy::GetProp_StaticName);
if (!getStaticName(&script()->global(), name, emitted) || *emitted)
return *emitted;
trackOptimizationAttempt(TrackedStrategy::GetProp_CommonGetter);
if (!getPropTryCommonGetter(emitted, inner, name, types) || *emitted)
return *emitted;
@ -11064,6 +11075,7 @@ IonBuilder::getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* na
// needsOuterizedThisObject check in IsCacheableGetPropCallNative.
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
inner, name, types);
trackOptimizationAttempt(TrackedStrategy::GetProp_InlineCache);
if (!getPropTryCache(emitted, inner, name, barrier, types) || *emitted)
return *emitted;

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

@ -1280,13 +1280,19 @@ MCallDOMNative::getAliasSet() const
// getArg(0) is "this", so skip it
MDefinition* arg = getArg(argIndex+1);
MIRType actualType = arg->type();
// The only way to reliably avoid side-effects given the informtion we
// The only way to reliably avoid side-effects given the information we
// have here is if we're passing in a known primitive value to an
// argument that expects a primitive value. XXXbz maybe we need to
// communicate better information. For example, a sequence argument
// will sort of unavoidably have side effects, while a typed array
// argument won't have any, but both are claimed to be
// JSJitInfo::Object.
// argument that expects a primitive value.
//
// XXXbz maybe we need to communicate better information. For example,
// a sequence argument will sort of unavoidably have side effects, while
// a typed array argument won't have any, but both are claimed to be
// JSJitInfo::Object. But if we do that, we need to watch out for our
// movability/DCE-ability bits: if we have an arg type that can reliably
// throw an exception on conversion, that might not affect our alias set
// per se, but it should prevent us being moved or DCE-ed, unless we
// know the incoming things match that arg type and won't throw.
//
if ((actualType == MIRType_Value || actualType == MIRType_Object) ||
(*argType & JSJitInfo::Object))
{

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

@ -3741,13 +3741,13 @@ class MCallDOMNative : public MCall
MCallDOMNative(JSFunction* target, uint32_t numActualArgs)
: MCall(target, numActualArgs, false)
{
// If our jitinfo is not marked movable, that means that our C++
// If our jitinfo is not marked eliminatable, that means that our C++
// implementation is fallible or that it never wants to be eliminated or
// coalesced or that we have no hope of ever doing the sort of argument
// analysis that would allow us to detemine that we're side-effect-free.
// In the latter case we wouldn't get DCEd no matter what, but for the
// former two cases we have to explicitly say that we can't be DCEd.
if (!getJitInfo()->isMovable)
// that we have no hope of ever doing the sort of argument analysis that
// would allow us to detemine that we're side-effect-free. In the
// latter case we wouldn't get DCEd no matter what, but for the former
// two cases we have to explicitly say that we can't be DCEd.
if (!getJitInfo()->isEliminatable)
setGuard();
}

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

@ -2346,6 +2346,7 @@ struct JSJitInfo {
#define JITINFO_OP_TYPE_BITS 4
#define JITINFO_ALIAS_SET_BITS 4
#define JITINFO_RETURN_TYPE_BITS 8
#define JITINFO_SLOT_INDEX_BITS 10
// The OpType that says what sort of function we are.
uint32_t type_ : JITINFO_OP_TYPE_BITS;
@ -2374,7 +2375,10 @@ struct JSJitInfo {
uint32_t isMovable : 1; /* Is op movable? To be movable the op must
not AliasEverything, but even that might
not be enough (e.g. in cases when it can
throw). */
throw or is explicitly not movable). */
uint32_t isEliminatable : 1; /* Can op be dead-code eliminated? Again, this
depends on whether the op can throw, in
addition to the alias set. */
// XXXbz should we have a JSValueType for the type of the member?
uint32_t isAlwaysInSlot : 1; /* True if this is a getter that can always
get the value from a slot of the "this"
@ -2385,9 +2389,15 @@ struct JSJitInfo {
slot of the "this" object. */
uint32_t isTypedMethod : 1; /* True if this is an instance of
JSTypedMethodJitInfo. */
uint32_t slotIndex : 11; /* If isAlwaysInSlot or isSometimesInSlot is
true, the index of the slot to get the value
from. Otherwise 0. */
uint32_t slotIndex : JITINFO_SLOT_INDEX_BITS; /* If isAlwaysInSlot or
isSometimesInSlot is true,
the index of the slot to
get the value from.
Otherwise 0. */
static const size_t maxSlotIndex = (1 << JITINFO_SLOT_INDEX_BITS) - 1;
#undef JITINFO_SLOT_INDEX_BITS
};
static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),

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

@ -468,6 +468,8 @@ Compare(T* a, T* b, size_t c)
return true;
}
static bool iterator_next(JSContext* cx, unsigned argc, Value* vp);
static inline PropertyIteratorObject*
NewPropertyIteratorObject(JSContext* cx, unsigned flags)
{
@ -487,13 +489,33 @@ NewPropertyIteratorObject(JSContext* cx, unsigned flags)
GetInitialHeap(GenericObject, clasp), shape, group);
if (!obj)
return nullptr;
PropertyIteratorObject* res = &obj->as<PropertyIteratorObject>();
MOZ_ASSERT(res->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
return res;
}
return NewBuiltinClassInstance<PropertyIteratorObject>(cx);
Rooted<PropertyIteratorObject*> res(cx, NewBuiltinClassInstance<PropertyIteratorObject>(cx));
if (!res)
return nullptr;
if (flags == 0) {
// Redefine next as an own property. This ensure that deleting the
// next method on the prototype doesn't break cross-global for .. in.
// We don't have to do this for JSITER_ENUMERATE because that object always
// takes an optimized path.
RootedFunction next(cx, NewNativeFunction(cx, iterator_next, 0,
HandlePropertyName(cx->names().next)));
if (!next)
return nullptr;
RootedValue value(cx, ObjectValue(*next));
if (!DefineProperty(cx, res, cx->names().next, value))
return nullptr;
}
return res;
}
NativeIterator*

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

@ -5185,6 +5185,7 @@ static const JSJitInfo dom_x_getterinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
true, /* isInfallible. False in setters. */
true, /* isMovable */
true, /* isEliminatable */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */
@ -5200,6 +5201,7 @@ static const JSJitInfo dom_x_setterinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable. */
false, /* isEliminatable. */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */
@ -5215,6 +5217,7 @@ static const JSJitInfo doFoo_methodinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable */
false, /* isEliminatable */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */

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

@ -21,6 +21,7 @@
#include "nsDebug.h"
#include "pldhash.h"
#include "mozilla/Attributes.h"
class nsIFrame;
class nsIPresShell;
@ -59,7 +60,7 @@ protected:
class UndisplayedMap;
// weak link, because the pres shell owns us
nsIPresShell* mPresShell;
nsIPresShell* MOZ_NON_OWNING_REF mPresShell;
// the pres shell owns the style set
nsStyleSet* mStyleSet;
nsIFrame* mRootFrame;

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

@ -1671,18 +1671,21 @@ protected:
// These are the same Document and PresContext owned by the DocViewer.
// we must share ownership.
nsIDocument* mDocument; // [STRONG]
nsPresContext* mPresContext; // [STRONG]
nsCOMPtr<nsIDocument> mDocument;
nsRefPtr<nsPresContext> mPresContext;
nsStyleSet* mStyleSet; // [OWNS]
nsCSSFrameConstructor* mFrameConstructor; // [OWNS]
nsViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to
nsPresArena mFrameArena;
nsFrameSelection* mSelection;
nsRefPtr<nsFrameSelection> mSelection;
// Pointer into mFrameConstructor - this is purely so that FrameManager() and
// GetRootFrame() can be inlined:
nsFrameManagerBase* mFrameManager;
mozilla::WeakPtr<nsDocShell> mForwardingContainer;
nsRefreshDriver* mHiddenInvalidationObserverRefreshDriver;
nsRefreshDriver* MOZ_UNSAFE_REF("These two objects hold weak references "
"to each other, and the validity of this "
"member is ensured by the logic in nsIPresShell.")
mHiddenInvalidationObserverRefreshDriver;
#ifdef ACCESSIBILITY
mozilla::a11y::DocAccessible* mDocAccessible;
#endif

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

@ -746,7 +746,6 @@ PresShell::BeforeAfterKeyboardEventEnabled()
PresShell::PresShell()
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
{
mSelection = nullptr;
#ifdef MOZ_REFLOW_PERF
mReflowCountMgr = new ReflowCountMgr();
mReflowCountMgr->SetPresContext(mPresContext);
@ -835,10 +834,6 @@ PresShell::~PresShell()
delete mFrameConstructor;
mCurrentEventContent = nullptr;
NS_IF_RELEASE(mPresContext);
NS_IF_RELEASE(mDocument);
NS_IF_RELEASE(mSelection);
}
/**
@ -864,7 +859,6 @@ PresShell::Init(nsIDocument* aDocument,
}
mDocument = aDocument;
NS_ADDREF(mDocument);
mViewManager = aViewManager;
// Create our frame constructor.
@ -877,7 +871,6 @@ PresShell::Init(nsIDocument* aDocument,
// Bind the context to the presentation shell.
mPresContext = aPresContext;
NS_ADDREF(mPresContext);
aPresContext->SetShell(this);
// Now we can initialize the style set.
@ -905,7 +898,7 @@ PresShell::Init(nsIDocument* aDocument,
}
NS_ADDREF(mSelection = new nsFrameSelection());
mSelection = new nsFrameSelection();
mSelection->Init(this, nullptr);

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

@ -702,14 +702,15 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT
}
}
/* static */
nscoord
nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState)
nsHTMLReflowState::GetContainingBlockContentISize(WritingMode aWritingMode) const
{
const nsHTMLReflowState* rs = aReflowState->mCBReflowState;
if (!rs)
if (!mCBReflowState) {
return 0;
return rs->ComputedWidth();
}
return mCBReflowState->GetWritingMode().IsOrthogonalTo(aWritingMode)
? mCBReflowState->ComputedBSize()
: mCBReflowState->ComputedISize();
}
void

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

@ -650,11 +650,12 @@ public:
nscoord aContainingBlockBSize = -1,
const nsMargin* aBorder = nullptr,
const nsMargin* aPadding = nullptr);
/**
* Find the content width of the containing block of aReflowState
* Find the content isize of our containing block for the given writing mode,
* which need not be the same as the reflow state's mode.
*/
static nscoord
GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
nscoord GetContainingBlockContentISize(mozilla::WritingMode aWritingMode) const;
/**
* Calculate the used line-height property. The return value will be >= 0.

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

@ -238,7 +238,7 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord,
nscoord pctBasis = 0;
if (textIndent.HasPercent()) {
pctBasis =
nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState);
mBlockReflowState->GetContainingBlockContentISize(aWritingMode);
}
nscoord indent = nsRuleNode::ComputeCoordPercentCalc(textIndent, pctBasis);

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

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font-size: 10px;
}
div {
width: 100px;
height: 200px;
margin: 5px;
border: 1px solid silver;
display: inline-block;
vertical-align: top;
}
p {
inline-size: 100%;
margin: 0;
}
span {
display: inline-block;
width: 20px;
height: 20px;
background: green;
position: relative;
}
</style>
</head>
<body>
<div> <p><span style="left: 20px;"></span></p> </div>
<div> <p><span style="left: 60px;"></span></p> </div>
<div> <p><span style="top: 40px;"></span></p> </div>
<div> <p><span style="top: 140px;"></span></p> </div>
<div> <p><span style="top: 40px; left: 80px;"></span></p> </div>
<div> <p><span style="top: 140px; left: 80px;"></span></p> </div>
<br>
<div> <p><span style="left: 20px;"></span></p> </div>
<div> <p><span style="left: 60px;"></span></p> </div>
<div> <p><span style="top: 40px;"></span></p> </div>
<div> <p><span style="top: 140px;"></span></p> </div>
<div> <p><span style="top: 40px;"></span></p> </div>
<div> <p><span style="top: 140px;"></span></p> </div>
</body>
</html>

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

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font-size: 10px;
}
div {
width: 100px;
height: 200px;
margin: 5px;
border: 1px solid silver;
display: inline-block;
vertical-align: top;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
p {
inline-size: 100%;
text-indent: 20%;
margin: 0;
}
span {
display: inline-block;
width: 20px;
height: 20px;
background: green;
}
</style>
</head>
<body>
<div> <p><span></span></p> </div>
<div dir="rtl"> <p><span></span></p> </div>
<div class="vlr"> <p><span></span></p> </div>
<div class="vlr" dir="rtl"> <p><span></span></p> </div>
<div class="vrl"> <p><span></span></p> </div>
<div class="vrl" dir="rtl"> <p><span></span></p> </div>
<br>
<div> <p><span></span></p> </div>
<div> <p dir="rtl"><span></span></p> </div>
<div> <p class="vlr"><span></span></p> </div>
<div> <p class="vlr" dir="rtl"><span></span></p> </div>
<div> <p class="vrl"><span></span></p> </div>
<div> <p class="vrl" dir="rtl"><span></span></p> </div>
</body>
</html>

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

@ -128,3 +128,4 @@ test-pref(dom.meta-viewport.enabled,true) test-pref(font.size.inflation.emPerLin
== 1144501-1a-block-end-margin-orthogonal-size.html 1144501-1-block-end-margin-orthogonal-size-ref.html
== 1144501-1b-block-end-margin-orthogonal-size.html 1144501-1-block-end-margin-orthogonal-size-ref.html
== 1151993-1-orthogonal-block-size.html 1151993-1-orthogonal-block-size-ref.html
== 1156021-text-indent-percent.html 1156021-text-indent-percent-ref.html

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

@ -116,10 +116,11 @@ private:
float mFloat;
int32_t mInt32;
uint32_t mUint32;
nsDOMCSSRGBColor* mColor;
nsDOMCSSRect* mRect;
// These can't be nsCOMPtr/nsRefPtr's because they are used inside a union.
nsDOMCSSRGBColor* MOZ_OWNING_REF mColor;
nsDOMCSSRect* MOZ_OWNING_REF mRect;
char16_t* mString;
nsIURI* mURI;
nsIURI* MOZ_OWNING_REF mURI;
nsCSSKeyword mKeyword;
} mValue;
};

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

@ -523,7 +523,7 @@ BasicTableLayoutStrategy::MarkIntrinsicISizesDirty()
}
/* virtual */ void
BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowState)
BasicTableLayoutStrategy::ComputeColumnISizes(const nsHTMLReflowState& aReflowState)
{
nscoord width = aReflowState.ComputedWidth();
@ -549,7 +549,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
DistributeWidthToColumns(width, 0, colCount, BTLS_FINAL_WIDTH, false);
#ifdef DEBUG_TABLE_STRATEGY
printf("ComputeColumnWidths final\n");
printf("ComputeColumnISizes final\n");
mTableFrame->Dump(false, true, false);
#endif
}
@ -850,7 +850,7 @@ BasicTableLayoutStrategy::DistributeWidthToColumns(nscoord aWidth,
}
#ifdef DEBUG_dbaron_off
printf("ComputeColumnWidths: %d columns in width %d,\n"
printf("ComputeColumnISizes: %d columns in width %d,\n"
" guesses=[%d,%d,%d,%d], totals=[%d,%d,%f],\n"
" l2t=%d, space=%d, basis.c=%d\n",
aColCount, aWidth,
@ -1045,8 +1045,8 @@ BasicTableLayoutStrategy::DistributeWidthToColumns(nscoord aWidth,
break;
case BTLS_FINAL_WIDTH:
{
nscoord old_final = colFrame->GetFinalWidth();
colFrame->SetFinalWidth(col_width);
nscoord old_final = colFrame->GetFinalISize();
colFrame->SetFinalISize(col_width);
if (old_final != col_width)
mTableFrame->DidResizeColumns();

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

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Web-compatible algorithms that determine column and table widths,
* Web-compatible algorithms that determine column and table isizes,
* used for CSS2's 'table-layout: auto'.
*/
@ -28,7 +28,7 @@ public:
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext,
bool aComputingSize) override;
virtual void MarkIntrinsicISizesDirty() override;
virtual void ComputeColumnWidths(const nsHTMLReflowState& aReflowState) override;
virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) override;
private:
// NOTE: Using prefix "BTLS" to avoid overlapping names with

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

@ -151,7 +151,7 @@ AllocateUnassigned(nscoord aUnassignedSpace, float aShare)
}
/* virtual */ void
FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowState)
FixedTableLayoutStrategy::ComputeColumnISizes(const nsHTMLReflowState& aReflowState)
{
nscoord tableWidth = aReflowState.ComputedWidth();
@ -170,12 +170,12 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
// border-spacing isn't part of the basis for percentages.
tableWidth -= mTableFrame->GetColSpacing(-1, colCount);
// store the old column widths. We might call multiple times SetFinalWidth
// store the old column widths. We might call multiple times SetFinalISize
// on the columns, due to this we can't compare at the last call that the
// width has changed with the respect to the last call to
// ComputeColumnWidths. In order to overcome this we store the old values
// in this array. A single call to SetFinalWidth would make it possible to
// call GetFinalWidth before and to compare when setting the final width.
// ComputeColumnISizes. In order to overcome this we store the old values
// in this array. A single call to SetFinalISize would make it possible to
// call GetFinalISize before and to compare when setting the final width.
nsTArray<nscoord> oldColWidths;
// XXX This ignores the 'min-width' and 'max-width' properties
@ -203,7 +203,7 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
NS_ERROR("column frames out of sync with cell map");
continue;
}
oldColWidths.AppendElement(colFrame->GetFinalWidth());
oldColWidths.AppendElement(colFrame->GetFinalISize());
colFrame->ResetPrefPercent();
const nsStyleCoord *styleWidth =
&colFrame->StylePosition()->mWidth;
@ -294,7 +294,7 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
}
}
colFrame->SetFinalWidth(colWidth);
colFrame->SetFinalISize(colWidth);
if (colWidth == unassignedMarker) {
++unassignedCount;
@ -317,12 +317,12 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
NS_ERROR("column frames out of sync with cell map");
continue;
}
nscoord colWidth = colFrame->GetFinalWidth();
nscoord colWidth = colFrame->GetFinalISize();
colWidth -= NSToCoordFloor(colFrame->GetPrefPercent() *
reduceRatio);
if (colWidth < 0)
colWidth = 0;
colFrame->SetFinalWidth(colWidth);
colFrame->SetFinalISize(colWidth);
}
}
unassignedSpace = 0;
@ -338,8 +338,8 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
NS_ERROR("column frames out of sync with cell map");
continue;
}
if (colFrame->GetFinalWidth() == unassignedMarker)
colFrame->SetFinalWidth(toAssign);
if (colFrame->GetFinalISize() == unassignedMarker)
colFrame->SetFinalISize(toAssign);
}
} else if (unassignedSpace > 0) {
// The spec doesn't say how to distribute the unassigned space.
@ -353,12 +353,12 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
continue;
}
if (colFrame->GetPrefPercent() == 0.0f) {
NS_ASSERTION(colFrame->GetFinalWidth() <= specUndist,
NS_ASSERTION(colFrame->GetFinalISize() <= specUndist,
"widths don't add up");
nscoord toAdd = AllocateUnassigned(unassignedSpace,
float(colFrame->GetFinalWidth()) / float(specUndist));
specUndist -= colFrame->GetFinalWidth();
colFrame->SetFinalWidth(colFrame->GetFinalWidth() + toAdd);
float(colFrame->GetFinalISize()) / float(specUndist));
specUndist -= colFrame->GetFinalISize();
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
unassignedSpace -= toAdd;
if (specUndist <= 0) {
NS_ASSERTION(specUndist == 0,
@ -386,7 +386,7 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
}
nscoord toAdd = AllocateUnassigned(unassignedSpace,
colFrame->GetPrefPercent() / pctUndist);
colFrame->SetFinalWidth(colFrame->GetFinalWidth() + toAdd);
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
unassignedSpace -= toAdd;
pctUndist -= colFrame->GetPrefPercent();
if (pctUndist <= 0.0f) {
@ -403,10 +403,10 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
NS_ERROR("column frames out of sync with cell map");
continue;
}
NS_ASSERTION(colFrame->GetFinalWidth() == 0, "yikes");
NS_ASSERTION(colFrame->GetFinalISize() == 0, "yikes");
nscoord toAdd = AllocateUnassigned(unassignedSpace,
1.0f / float(colsLeft));
colFrame->SetFinalWidth(toAdd);
colFrame->SetFinalISize(toAdd);
unassignedSpace -= toAdd;
--colsLeft;
}
@ -419,7 +419,7 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
NS_ERROR("column frames out of sync with cell map");
continue;
}
if (oldColWidths.ElementAt(col) != colFrame->GetFinalWidth()) {
if (oldColWidths.ElementAt(col) != colFrame->GetFinalISize()) {
mTableFrame->DidResizeColumns();
break;
}

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

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Algorithms that determine column and table widths used for CSS2's
* Algorithms that determine column and table isizes used for CSS2's
* 'table-layout: fixed'.
*/
@ -28,7 +28,7 @@ public:
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext,
bool aComputingSize) override;
virtual void MarkIntrinsicISizesDirty() override;
virtual void ComputeColumnWidths(const nsHTMLReflowState& aReflowState) override;
virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) override;
private:
nsTableFrame *mTableFrame;

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

@ -6,7 +6,7 @@
/*
* interface for the set of algorithms that determine column and table
* widths
* isizes
*/
#ifndef nsITableLayoutStrategy_h_
@ -34,10 +34,10 @@ public:
virtual void MarkIntrinsicISizesDirty() = 0;
/**
* Compute final column widths based on the intrinsic width data and
* the available width.
* Compute final column isizes based on the intrinsic isize data and
* the available isize.
*/
virtual void ComputeColumnWidths(const nsHTMLReflowState& aReflowState) = 0;
virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) = 0;
/**
* Return the type of table layout strategy, without the cost of

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

@ -25,7 +25,7 @@ nsTableColFrame::nsTableColFrame(nsStyleContext* aContext) :
SetColType(eColContent);
ResetIntrinsics();
ResetSpanIntrinsics();
ResetFinalWidth();
ResetFinalISize();
}
nsTableColFrame::~nsTableColFrame()
@ -142,7 +142,7 @@ void nsTableColFrame::Dump(int32_t aIndent)
mHasSpecifiedCoord ? 's' : 'u', mPrefPercent,
int32_t(mSpanMinCoord), int32_t(mSpanPrefCoord),
mSpanPrefPercent,
int32_t(GetFinalWidth()));
int32_t(GetFinalISize()));
printf("\n%s**END COL DUMP** ", indent);
delete [] indent;
}

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

@ -254,14 +254,14 @@ public:
}
// The final width of the column.
void ResetFinalWidth() {
mFinalWidth = nscoord_MIN; // so we detect that it changed
void ResetFinalISize() {
mFinalISize = nscoord_MIN; // so we detect that it changed
}
void SetFinalWidth(nscoord aFinalWidth) {
mFinalWidth = aFinalWidth;
void SetFinalISize(nscoord aFinalISize) {
mFinalISize = aFinalISize;
}
nscoord GetFinalWidth() {
return mFinalWidth;
nscoord GetFinalISize() {
return mFinalISize;
}
virtual bool IsFrameOfType(uint32_t aFlags) const override
@ -288,7 +288,7 @@ protected:
// a separate array allocated only during
// BasicTableLayoutStrategy::ComputeColumnIntrinsicISizes (and only
// when colspans were present).
nscoord mFinalWidth;
nscoord mFinalISize;
// the index of the column with respect to the whole table (starting at 0)
// it should never be smaller then the start column index of the parent

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

@ -1444,7 +1444,7 @@ nsTableFrame::SetColumnDimensions(nscoord aHeight,
if (NS_STYLE_DISPLAY_TABLE_COLUMN ==
colFrame->StyleDisplay()->mDisplay) {
NS_ASSERTION(colX < GetColCount(), "invalid number of columns");
nscoord colWidth = GetColumnWidth(colX);
nscoord colWidth = GetColumnISize(colX);
nsRect colRect(colOrigin.x, colOrigin.y, colWidth, colHeight);
colFrame->SetRect(colRect);
cellSpacingX = GetColSpacing(colX);
@ -2028,7 +2028,7 @@ nsTableFrame::ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
aLastChildReflowed = nullptr;
if (!GetPrevInFlow()) {
mTableLayoutStrategy->ComputeColumnWidths(aReflowState);
mTableLayoutStrategy->ComputeColumnISizes(aReflowState);
}
// Constrain our reflow width to the computed table width (of the 1st in flow).
// and our reflow height to our avail height minus border, padding, cellspacing
@ -2179,7 +2179,7 @@ nsTableFrame::GetCollapsedWidth(nsMargin aBorderPadding)
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
const nsStyleVisibility* colVis = colFrame->StyleVisibility();
bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
int32_t colWidth = GetColumnWidth(colX);
int32_t colWidth = GetColumnISize(colX);
if (!collapseGroup && !collapseCol) {
width += colWidth;
if (ColumnHasCellSpacingBefore(colX))
@ -3540,14 +3540,14 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
ResizeCells(*this);
}
int32_t nsTableFrame::GetColumnWidth(int32_t aColIndex)
int32_t nsTableFrame::GetColumnISize(int32_t aColIndex)
{
nsTableFrame* firstInFlow = static_cast<nsTableFrame*>(FirstInFlow());
if (this == firstInFlow) {
nsTableColFrame* colFrame = GetColFrame(aColIndex);
return colFrame ? colFrame->GetFinalWidth() : 0;
return colFrame ? colFrame->GetFinalISize() : 0;
}
return firstInFlow->GetColumnWidth(aColIndex);
return firstInFlow->GetColumnISize(aColIndex);
}
nscoord nsTableFrame::GetColSpacing()
@ -3812,7 +3812,7 @@ nsTableFrame::Dump(bool aDumpRows,
int32_t numCols = GetColCount();
int32_t colX;
for (colX = 0; colX < numCols; colX++) {
printf("%d ", GetColumnWidth(colX));
printf("%d ", GetColumnISize(colX));
}
printf("\n");

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

@ -383,8 +383,8 @@ public:
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
/** return the width of the column at aColIndex */
int32_t GetColumnWidth(int32_t aColIndex);
/** return the isize of the column at aColIndex */
int32_t GetColumnISize(int32_t aColIndex);
/** Helper to get the column spacing style value.
* The argument refers to the space between column aColIndex and column

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

@ -682,7 +682,7 @@ CalcAvailWidth(nsTableFrame& aTableFrame,
NS_ASSERTION(colspan > 0, "effective colspan should be positive");
for (int32_t spanX = 0; spanX < colspan; spanX++) {
cellAvailWidth += aTableFrame.GetColumnWidth(colIndex + spanX);
cellAvailWidth += aTableFrame.GetColumnISize(colIndex + spanX);
if (spanX > 0 &&
aTableFrame.ColumnHasCellSpacingBefore(colIndex + spanX)) {
cellAvailWidth += aTableFrame.GetColSpacing(colIndex + spanX - 1);
@ -705,7 +705,7 @@ GetSpaceBetween(int32_t aPrevColIndex,
for (colX = aPrevColIndex + 1; aColIndex > colX; colX++) {
bool isCollapsed = false;
if (!aCheckVisibility) {
space += aTableFrame.GetColumnWidth(colX);
space += aTableFrame.GetColumnISize(colX);
}
else {
nsTableColFrame* colFrame = aTableFrame.GetColFrame(colX);
@ -717,7 +717,7 @@ GetSpaceBetween(int32_t aPrevColIndex,
groupVis->mVisible);
isCollapsed = collapseCol || collapseGroup;
if (!isCollapsed)
space += aTableFrame.GetColumnWidth(colX);
space += aTableFrame.GetColumnISize(colX);
}
if (!isCollapsed && aTableFrame.ColumnHasCellSpacingBefore(colX)) {
space += aTableFrame.GetColSpacing(colX - 1);
@ -729,7 +729,7 @@ GetSpaceBetween(int32_t aPrevColIndex,
for (colX = aPrevColIndex - 1; colX > lastCol; colX--) {
bool isCollapsed = false;
if (!aCheckVisibility) {
space += aTableFrame.GetColumnWidth(colX);
space += aTableFrame.GetColumnISize(colX);
}
else {
nsTableColFrame* colFrame = aTableFrame.GetColFrame(colX);
@ -741,7 +741,7 @@ GetSpaceBetween(int32_t aPrevColIndex,
groupVis->mVisible);
isCollapsed = collapseCol || collapseGroup;
if (!isCollapsed)
space += aTableFrame.GetColumnWidth(colX);
space += aTableFrame.GetColumnISize(colX);
}
if (!isCollapsed && aTableFrame.ColumnHasCellSpacingBefore(colX)) {
space += aTableFrame.GetColSpacing(colX - 1);
@ -1241,7 +1241,7 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
groupVis->mVisible);
bool isCollapsed = collapseCol || collapseGroup;
if (!isCollapsed) {
cRect.width += tableFrame->GetColumnWidth(colX);
cRect.width += tableFrame->GetColumnISize(colX);
isVisible = true;
if ((actualColSpan > 1)) {
nsTableColFrame* nextColFrame =

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

@ -26,7 +26,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=8675309
/** Test for Bug 8675309 **/
is_loosely(1, "1", "sanity check");
ok(true, "sanity check");

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

@ -22,15 +22,11 @@
/** Test for sanity **/
ok(true, "true must be ok");
is_loosely(1, true, "1 must loosely be true");
isnot(1, true, "1 must not be true");
isnot(1, false, "1 must not be false");
is_loosely(0, false, "0 must loosely be false");
isnot(0, false, "0 must not be false");
isnot(0, true, "0 must not be true");
is_loosely("", 0, "Empty string must loosely be 0");
isnot("", 0, "Empty string must not be 0");
is_loosely("1", 1, "Numeric string must loosely equal the number");
isnot("1", 1, "Numeric string must not equal the number");
isnot("", null, "Empty string must not be null");
isnot(undefined, null, "Undefined must not be null");

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

@ -291,15 +291,6 @@ SimpleTest.isnot = function (a, b, name) {
SimpleTest.ok(pass, name, diag);
};
/**
* Roughly equivalent to ok(a==b, name)
**/
SimpleTest.is_loosely = function (a, b, name) {
var pass = (a == b);
var diag = pass ? "" : "got " + repr(a) + ", expected " + repr(b)
SimpleTest.ok(pass, name, diag);
};
/**
* Check that the function call throws an exception.
*/
@ -1454,7 +1445,6 @@ var is = SimpleTest.is;
var isfuzzy = SimpleTest.isfuzzy;
var isnot = SimpleTest.isnot;
var ise = SimpleTest.ise;
var is_loosely = SimpleTest.is_loosely;
var todo = SimpleTest.todo;
var todo_is = SimpleTest.todo_is;
var todo_isnot = SimpleTest.todo_isnot;

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

@ -99,21 +99,22 @@ function objAddr(obj)
return String(obj);
}
function log(...args)
function log(/*...args*/)
{
return;
/*
for (let arg of args) {
dump(arg);
dump(" ");
}
dump("\n");
*/
}
function logPrefetch(kind, value1, component, value2)
function logPrefetch(/*kind, value1, component, value2*/)
{
return;
/*
log("prefetching", kind, objAddr(value1) + "." + component, "=", objAddr(value2));
*/
}
/*

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

@ -633,8 +633,6 @@
return false;
}, this);
return false;
]]>
</body>
</method>

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

@ -360,7 +360,7 @@ enum {
bottomMargin
};
static int EnumSizeForCocoaSize(NSControlSize cocoaControlSize) {
static size_t EnumSizeForCocoaSize(NSControlSize cocoaControlSize) {
if (cocoaControlSize == NSMiniControlSize)
return miniControlSize;
else if (cocoaControlSize == NSSmallControlSize)
@ -394,7 +394,7 @@ static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, con
return;
static int osIndex = leopardOS;
int controlSize = EnumSizeForCocoaSize(cocoaControlSize);
size_t controlSize = EnumSizeForCocoaSize(cocoaControlSize);
const float* buttonMargins = marginSet[osIndex][controlSize];
rect->origin.x -= buttonMargins[leftMargin];
rect->origin.y -= buttonMargins[bottomMargin];
@ -820,13 +820,13 @@ static void DrawCellWithSnapping(NSCell *cell,
NSControlSize controlSizeY = FindControlSize(rectHeight, controlHeights, snapTolerance);
NSControlSize controlSize = NSRegularControlSize;
int sizeIndex = 0;
size_t sizeIndex = 0;
// At some sizes, don't scale but snap.
const NSControlSize smallerControlSize =
EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ?
controlSizeX : controlSizeY;
const int smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize);
const size_t smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize);
const NSSize size = sizes[smallerControlSizeIndex];
float diffWidth = size.width ? rectWidth - size.width : 0.0f;
float diffHeight = size.height ? rectHeight - size.height : 0.0f;

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

@ -18,6 +18,12 @@
class nsCOMPtr_helper;
namespace mozilla {
namespace dom {
template<class T> class OwningNonNull;
} // namespace dom
} // namespace mozilla
template <class T>
class nsRefPtr
{
@ -117,6 +123,10 @@ public:
MOZ_IMPLICIT nsRefPtr(const nsCOMPtr_helper& aHelper);
// Defined in OwningNonNull.h
template<class U>
MOZ_IMPLICIT nsRefPtr(const mozilla::dom::OwningNonNull<U>& aOther);
// Assignment operators
nsRefPtr<T>&
@ -163,6 +173,11 @@ public:
return *this;
}
// Defined in OwningNonNull.h
template<class U>
nsRefPtr<T>&
operator=(const mozilla::dom::OwningNonNull<U>& aOther);
// Other pointer operators
void

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

@ -112,6 +112,9 @@ namespace mozilla {
struct unused_t;
namespace dom {
template<class T> class OwningNonNull;
} // namespace dom
} // namespace mozilla
template<class T>
@ -532,6 +535,10 @@ public:
NSCAP_ASSERT_NO_QUERY_NEEDED();
}
// Defined in OwningNonNull.h
template<class U>
MOZ_IMPLICIT nsCOMPtr(const mozilla::dom::OwningNonNull<U>& aOther);
// Assignment operators
@ -623,6 +630,10 @@ public:
return *this;
}
// Defined in OwningNonNull.h
template<class U>
nsCOMPtr<T>& operator=(const mozilla::dom::OwningNonNull<U>& aOther);
// Exchange ownership with |aRhs|; can save a pair of refcount operations.
void swap(nsCOMPtr<T>& aRhs)
{

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

@ -306,6 +306,35 @@ struct nsTArray_SafeElementAtHelper<nsRefPtr<E>, Derived>
{
};
namespace mozilla {
namespace dom {
template<class T> class OwningNonNull;
}
}
template<class E, class Derived>
struct nsTArray_SafeElementAtHelper<mozilla::dom::OwningNonNull<E>, Derived>
{
typedef E* elem_type;
typedef size_t index_type;
elem_type SafeElementAt(index_type aIndex)
{
if (aIndex < static_cast<Derived*>(this)->Length()) {
return static_cast<Derived*>(this)->ElementAt(aIndex);
}
return nullptr;
}
const elem_type SafeElementAt(index_type aIndex) const
{
if (aIndex < static_cast<const Derived*>(this)->Length()) {
return static_cast<const Derived*>(this)->ElementAt(aIndex);
}
return nullptr;
}
};
//
// This class serves as a base class for nsTArray. It shouldn't be used
// directly. It holds common implementation code that does not depend on the

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

@ -44,6 +44,7 @@ TEST(Strings, test1)
nsAutoString buf(aStr);
int32_t n = buf.FindChar(',');
EXPECT_EQ(n, kNotFound);
n = buf.Length();