зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to f-t
This commit is contained in:
Коммит
3addbd04c3
|
@ -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();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче