mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge mozilla-central into mozilla-inbound
This commit is contained in:
commit
166aca09f9
1
.hgtags
1
.hgtags
@ -79,3 +79,4 @@ bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
|
||||
0000000000000000000000000000000000000000 AURORA_BASE_20120131
|
||||
bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
|
||||
b6627f28b7ec17e1b46a594df0f780d3a40847e4 FIREFOX_AURORA_13_BASE
|
||||
357da346ceb705d196a46574804c7c4ec44ac186 FIREFOX_AURORA_14_BASE
|
||||
|
2
b2g/confvars.sh
Normal file → Executable file
2
b2g/confvars.sh
Normal file → Executable file
@ -38,7 +38,7 @@
|
||||
MOZ_APP_BASENAME=B2G
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=14.0a1
|
||||
MOZ_APP_VERSION=15.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
|
||||
|
@ -55,7 +55,7 @@
|
||||
<Description>
|
||||
<em:id>{3c2e2abc-06d4-11e1-ac3b-374f68613e61}</em:id>
|
||||
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
|
||||
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
|
@ -7,7 +7,7 @@ export MOZILLA_OFFICIAL=1
|
||||
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
@ -3,4 +3,4 @@ ac_add_options --enable-update-packaging
|
||||
ac_add_options --enable-official-branding
|
||||
ac_add_options --with-l10n-base=../../l10n-central
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
|
@ -16,7 +16,7 @@ export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
@ -12,7 +12,7 @@ export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
@ -13,4 +13,4 @@ mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
|
||||
. $topsrcdir/build/win64/mozconfig.vs2010
|
||||
|
@ -22,4 +22,4 @@ mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
|
||||
. $topsrcdir/build/win64/mozconfig.vs2010
|
||||
|
@ -1 +1 @@
|
||||
14.0a1
|
||||
15.0a1
|
||||
|
@ -55,7 +55,7 @@
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
|
||||
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
|
@ -198,6 +198,9 @@ build_all_dep: alldep
|
||||
build_all_depend: alldep
|
||||
clobber clobber_all: clean
|
||||
|
||||
# helper target for mobile
|
||||
build_and_deploy: build package install
|
||||
|
||||
# Do everything from scratch
|
||||
everything: clean build
|
||||
|
||||
|
@ -59,6 +59,7 @@ MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
|
||||
MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
|
||||
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
|
||||
MOZ_APP_VERSION = @MOZ_APP_VERSION@
|
||||
MOZ_APP_MAXVERSION = @MOZ_APP_MAXVERSION@
|
||||
MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
|
||||
MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
|
||||
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
14.0a1
|
||||
15.0a1
|
||||
|
15
configure.in
15
configure.in
@ -8564,6 +8564,20 @@ if test -z "$MOZ_APP_NAME"; then
|
||||
MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
|
||||
fi
|
||||
|
||||
# For extensions and langpacks, we require a max version that is compatible
|
||||
# across security releases. MOZ_APP_MAXVERSION is our method for doing that.
|
||||
# 10.0a1 and 10.0a2 aren't affected
|
||||
# 10.0 becomes 10.0.*
|
||||
# 10.0.1 becomes 10.0.*
|
||||
IS_ALPHA=`echo $MOZ_APP_VERSION | grep a`
|
||||
if test -z "$IS_ALPHA"; then
|
||||
changequote(,)
|
||||
MOZ_APP_MAXVERSION=`echo $MOZ_APP_VERSION | sed "s|\(^[0-9]*.[0-9]*\).*|\1|"`.*
|
||||
changequote([,])
|
||||
else
|
||||
MOZ_APP_MAXVERSION=$MOZ_APP_VERSION
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_APP_NAME)
|
||||
AC_SUBST(MOZ_APP_DISPLAYNAME)
|
||||
AC_SUBST(MOZ_APP_BASENAME)
|
||||
@ -8578,6 +8592,7 @@ AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
|
||||
AC_SUBST(MOZ_APP_UA_NAME)
|
||||
AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
|
||||
AC_SUBST(MOZ_APP_VERSION)
|
||||
AC_SUBST(MOZ_APP_MAXVERSION)
|
||||
AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
|
||||
AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
|
||||
AC_SUBST(FIREFOX_VERSION)
|
||||
|
@ -444,6 +444,15 @@ public:
|
||||
*/
|
||||
static bool ParseIntMarginValue(const nsAString& aString, nsIntMargin& aResult);
|
||||
|
||||
/**
|
||||
* Parse the value of the <font size=""> attribute according to the HTML5
|
||||
* spec as of April 16, 2012.
|
||||
*
|
||||
* @param aValue the value to parse
|
||||
* @return 1 to 7, or 0 if the value couldn't be parsed
|
||||
*/
|
||||
static PRInt32 ParseLegacyFontSize(const nsAString& aValue);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
|
@ -243,6 +243,12 @@ interface nsIDocumentEncoder : nsISupports
|
||||
*/
|
||||
const unsigned long OutputDropInvisibleBreak = (1 << 21);
|
||||
|
||||
/**
|
||||
* Don't check for _moz_dirty attributes when deciding whether to
|
||||
* pretty-print if this flag is set (bug 599983).
|
||||
*/
|
||||
const unsigned long OutputIgnoreMozDirty = (1 << 22);
|
||||
|
||||
/**
|
||||
* Initialize with a pointer to the document and the mime type.
|
||||
* @param aDocument Document to encode.
|
||||
|
@ -55,10 +55,10 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
Link::Link(Element *aElement)
|
||||
: mLinkState(defaultState)
|
||||
, mRegistered(false)
|
||||
, mElement(aElement)
|
||||
: mElement(aElement)
|
||||
, mHistory(services::GetHistoryService())
|
||||
, mLinkState(defaultState)
|
||||
, mRegistered(false)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mElement, "Must have an element");
|
||||
}
|
||||
@ -75,7 +75,7 @@ Link::GetLinkState() const
|
||||
"Getting the link state of an unregistered Link!");
|
||||
NS_ASSERTION(mLinkState != eLinkState_Unknown,
|
||||
"Getting the link state with an unknown value!");
|
||||
return mLinkState;
|
||||
return nsLinkState(mLinkState);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -149,17 +149,17 @@ private:
|
||||
already_AddRefed<nsIURI> GetURIToMutate();
|
||||
void SetHrefAttribute(nsIURI *aURI);
|
||||
|
||||
nsLinkState mLinkState;
|
||||
|
||||
mutable nsCOMPtr<nsIURI> mCachedURI;
|
||||
|
||||
bool mRegistered;
|
||||
|
||||
Element * const mElement;
|
||||
|
||||
// Strong reference to History. The link has to unregister before History
|
||||
// can disappear.
|
||||
nsCOMPtr<IHistory> mHistory;
|
||||
|
||||
PRUint16 mLinkState;
|
||||
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Link, MOZILLA_DOM_LINK_IMPLEMENTATION_IID)
|
||||
|
@ -1306,6 +1306,59 @@ nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& resul
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
PRInt32
|
||||
nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
|
||||
{
|
||||
nsAString::const_iterator iter, end;
|
||||
aValue.BeginReading(iter);
|
||||
aValue.EndReading(end);
|
||||
|
||||
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter == end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool relative = false;
|
||||
bool negate = false;
|
||||
if (*iter == PRUnichar('-')) {
|
||||
relative = true;
|
||||
negate = true;
|
||||
++iter;
|
||||
} else if (*iter == PRUnichar('+')) {
|
||||
relative = true;
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (*iter < PRUnichar('0') || *iter > PRUnichar('9')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We don't have to worry about overflow, since we can bail out as soon as
|
||||
// we're bigger than 7.
|
||||
PRInt32 value = 0;
|
||||
while (iter != end && *iter >= PRUnichar('0') && *iter <= PRUnichar('9')) {
|
||||
value = 10*value + (*iter - PRUnichar('0'));
|
||||
if (value >= 7) {
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (relative) {
|
||||
if (negate) {
|
||||
value = 3 - value;
|
||||
} else {
|
||||
value = 3 + value;
|
||||
}
|
||||
}
|
||||
|
||||
return clamped(value, 1, 7);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
|
||||
|
@ -347,8 +347,8 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
--mDisableEntityEncoding;
|
||||
}
|
||||
|
||||
bool forceFormat = content->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozdirty);
|
||||
bool forceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
|
||||
content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
|
||||
|
||||
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
|
||||
DecrIndentation(name);
|
||||
|
@ -565,8 +565,8 @@ nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
|
||||
// The _moz_dirty attribute is emitted by the editor to
|
||||
// indicate that this element should be pretty printed
|
||||
// even if we're not in pretty printing mode
|
||||
aForceFormat = aContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozdirty);
|
||||
aForceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
|
||||
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
|
||||
|
||||
nsIAtom *name = aContent->Tag();
|
||||
PRInt32 namespaceID = aContent->GetNameSpaceID();
|
||||
@ -592,8 +592,8 @@ nsXHTMLContentSerializer::CheckElementEnd(nsIContent * aContent,
|
||||
{
|
||||
NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
|
||||
|
||||
aForceFormat = aContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozdirty);
|
||||
aForceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
|
||||
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
|
||||
|
||||
nsIAtom *name = aContent->Tag();
|
||||
PRInt32 namespaceID = aContent->GetNameSpaceID();
|
||||
|
@ -357,8 +357,8 @@ static nsresult GenerateFlatTextContent(nsRange* aRange,
|
||||
|
||||
nsresult
|
||||
nsContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
|
||||
bool aForward,
|
||||
PRUint32* aXPOffset)
|
||||
bool aForward,
|
||||
PRUint32* aXPOffset)
|
||||
{
|
||||
// XXX This method assumes that the frame boundaries must be cluster
|
||||
// boundaries. It's false, but no problem now, maybe.
|
||||
@ -366,7 +366,7 @@ nsContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
|
||||
*aXPOffset == 0 || *aXPOffset == aContent->TextLength())
|
||||
return NS_OK;
|
||||
|
||||
NS_ASSERTION(*aXPOffset >= 0 && *aXPOffset <= aContent->TextLength(),
|
||||
NS_ASSERTION(*aXPOffset <= aContent->TextLength(),
|
||||
"offset is out of range.");
|
||||
|
||||
nsRefPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
|
||||
|
@ -697,13 +697,24 @@ nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
|
||||
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = docEncoder->NativeInit(doc, contentType,
|
||||
nsIDocumentEncoder::OutputEncodeBasicEntities |
|
||||
// Output DOM-standard newlines
|
||||
nsIDocumentEncoder::OutputLFLineBreak |
|
||||
// Don't do linebreaking that's not present in
|
||||
// the source
|
||||
nsIDocumentEncoder::OutputRaw);
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputEncodeBasicEntities |
|
||||
// Output DOM-standard newlines
|
||||
nsIDocumentEncoder::OutputLFLineBreak |
|
||||
// Don't do linebreaking that's not present in
|
||||
// the source
|
||||
nsIDocumentEncoder::OutputRaw |
|
||||
// Only check for mozdirty when necessary (bug 599983)
|
||||
nsIDocumentEncoder::OutputIgnoreMozDirty;
|
||||
|
||||
if (IsEditable()) {
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
GetEditorInternal(getter_AddRefs(editor));
|
||||
if (editor && editor->OutputsMozDirty()) {
|
||||
flags &= ~nsIDocumentEncoder::OutputIgnoreMozDirty;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = docEncoder->NativeInit(doc, contentType, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aIncludeSelf) {
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsRuleData.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -116,32 +117,6 @@ NS_IMPL_STRING_ATTR(nsHTMLFontElement, Color, color)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLFontElement, Face, face)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLFontElement, Size, size)
|
||||
|
||||
static const nsAttrValue::EnumTable kRelFontSizeTable[] = {
|
||||
{ "-10", -10 },
|
||||
{ "-9", -9 },
|
||||
{ "-8", -8 },
|
||||
{ "-7", -7 },
|
||||
{ "-6", -6 },
|
||||
{ "-5", -5 },
|
||||
{ "-4", -4 },
|
||||
{ "-3", -3 },
|
||||
{ "-2", -2 },
|
||||
{ "-1", -1 },
|
||||
{ "-0", 0 },
|
||||
{ "+0", 0 },
|
||||
{ "+1", 1 },
|
||||
{ "+2", 2 },
|
||||
{ "+3", 3 },
|
||||
{ "+4", 4 },
|
||||
{ "+5", 5 },
|
||||
{ "+6", 6 },
|
||||
{ "+7", 7 },
|
||||
{ "+8", 8 },
|
||||
{ "+9", 9 },
|
||||
{ "+10", 10 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
nsHTMLFontElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
@ -151,26 +126,12 @@ nsHTMLFontElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (aAttribute == nsGkAtoms::size) {
|
||||
nsAutoString tmp(aValue);
|
||||
tmp.CompressWhitespace(true, true);
|
||||
PRUnichar ch = tmp.IsEmpty() ? 0 : tmp.First();
|
||||
if ((ch == '+' || ch == '-')) {
|
||||
if (aResult.ParseEnumValue(aValue, kRelFontSizeTable, false))
|
||||
return true;
|
||||
|
||||
// truncate after digit, then parse it again.
|
||||
PRUint32 i;
|
||||
for (i = 1; i < tmp.Length(); i++) {
|
||||
ch = tmp.CharAt(i);
|
||||
if (!nsCRT::IsAsciiDigit(ch)) {
|
||||
tmp.Truncate(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return aResult.ParseEnumValue(tmp, kRelFontSizeTable, false);
|
||||
PRInt32 size = nsContentUtils::ParseLegacyFontSize(aValue);
|
||||
if (size) {
|
||||
aResult.SetTo(size, &aValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return aResult.ParseIntValue(aValue);
|
||||
return false;
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::pointSize ||
|
||||
aAttribute == nsGkAtoms::fontWeight) {
|
||||
@ -207,20 +168,10 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
if (value && value->Type() == nsAttrValue::eInteger)
|
||||
fontSize->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Point);
|
||||
else {
|
||||
// size: int, enum ,
|
||||
// size: int
|
||||
value = aAttributes->GetAttr(nsGkAtoms::size);
|
||||
if (value) {
|
||||
nsAttrValue::ValueType unit = value->Type();
|
||||
if (unit == nsAttrValue::eInteger || unit == nsAttrValue::eEnum) {
|
||||
PRInt32 size;
|
||||
if (unit == nsAttrValue::eEnum) // int (+/-)
|
||||
size = value->GetEnumValue() + 3;
|
||||
else
|
||||
size = value->GetIntegerValue();
|
||||
|
||||
size = clamped(size, 1, 7);
|
||||
fontSize->SetIntValue(size, eCSSUnit_Enumerated);
|
||||
}
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
fontSize->SetIntValue(value->GetIntegerValue(), eCSSUnit_Enumerated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@ _TEST_FILES = \
|
||||
test_object_plugin_nav.html \
|
||||
test_bug742030.html \
|
||||
test_bug742549.html \
|
||||
test_bug745685.html \
|
||||
$(NULL)
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
|
105
content/html/content/test/test_bug745685.html
Normal file
105
content/html/content/test/test_bug745685.html
Normal file
@ -0,0 +1,105 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=745685
|
||||
-->
|
||||
<title>Test for Bug 745685</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=745685">Mozilla Bug 745685</a>
|
||||
<font>Test text</font>
|
||||
<font size=1>1</font>
|
||||
<font size=2>2</font>
|
||||
<font size=3>3</font>
|
||||
<font size=4>4</font>
|
||||
<font size=5>5</font>
|
||||
<font size=6>6</font>
|
||||
<font size=7>7</font>
|
||||
<script>
|
||||
/** Test for Bug 745685 **/
|
||||
|
||||
var referenceSizes = {};
|
||||
for (var i = 1; i <= 7; i++) {
|
||||
referenceSizes[i] =
|
||||
getComputedStyle(document.querySelector('[size="' + i + '"]'))
|
||||
.fontSize;
|
||||
if (i > 1) {
|
||||
isnot(referenceSizes[i], referenceSizes[i - 1],
|
||||
"Sanity check: different <font size>s give different .fontSize");
|
||||
}
|
||||
}
|
||||
|
||||
function testFontSize(input, expected) {
|
||||
var font = document.querySelector("font");
|
||||
font.setAttribute("size", input);
|
||||
is(font.getAttribute("size"), input,
|
||||
"Setting doesn't round-trip (.getAttribute)");
|
||||
is(font.size, input,
|
||||
"Setting doesn't round-trip (.size)");
|
||||
is(getComputedStyle(font).fontSize, referenceSizes[expected],
|
||||
'Incorrect size for "' + input + '" : expected the same as ' + expected);
|
||||
}
|
||||
|
||||
function testFontSizes(input, expected) {
|
||||
testFontSize(input, expected);
|
||||
// Leading whitespace
|
||||
testFontSize(" " + input, expected);
|
||||
testFontSize("\t" + input, expected);
|
||||
testFontSize("\n" + input, expected);
|
||||
testFontSize("\f" + input, expected);
|
||||
testFontSize("\r" + input, expected);
|
||||
// Trailing garbage
|
||||
testFontSize(input + "abcd", expected);
|
||||
testFontSize(input + ".5", expected);
|
||||
testFontSize(input + "e2", expected);
|
||||
}
|
||||
|
||||
// Parse error
|
||||
testFontSizes("", 3);
|
||||
|
||||
// No sign
|
||||
testFontSizes("0", 1);
|
||||
testFontSizes("1", 1);
|
||||
testFontSizes("2", 2);
|
||||
testFontSizes("3", 3);
|
||||
testFontSizes("4", 4);
|
||||
testFontSizes("5", 5);
|
||||
testFontSizes("6", 6);
|
||||
testFontSizes("7", 7);
|
||||
testFontSizes("8", 7);
|
||||
testFontSizes("9", 7);
|
||||
testFontSizes("10", 7);
|
||||
testFontSizes("10000000000000000000000", 7);
|
||||
|
||||
// Minus sign
|
||||
testFontSizes("-0", 3);
|
||||
testFontSizes("-1", 2);
|
||||
testFontSizes("-2", 1);
|
||||
testFontSizes("-3", 1);
|
||||
testFontSizes("-4", 1);
|
||||
testFontSizes("-5", 1);
|
||||
testFontSizes("-6", 1);
|
||||
testFontSizes("-7", 1);
|
||||
testFontSizes("-8", 1);
|
||||
testFontSizes("-9", 1);
|
||||
testFontSizes("-10", 1);
|
||||
testFontSizes("-10000000000000000000000", 1);
|
||||
|
||||
// Plus sign
|
||||
testFontSizes("+0", 3);
|
||||
testFontSizes("+1", 4);
|
||||
testFontSizes("+2", 5);
|
||||
testFontSizes("+3", 6);
|
||||
testFontSizes("+4", 7);
|
||||
testFontSizes("+5", 7);
|
||||
testFontSizes("+6", 7);
|
||||
testFontSizes("+7", 7);
|
||||
testFontSizes("+8", 7);
|
||||
testFontSizes("+9", 7);
|
||||
testFontSizes("+10", 7);
|
||||
testFontSizes("+10000000000000000000000", 7);
|
||||
|
||||
// Non-HTML5 whitespace
|
||||
testFontSize("\b1", 3);
|
||||
testFontSize("\v1", 3);
|
||||
testFontSize("\0u00a01", 3);
|
||||
</script>
|
@ -2305,7 +2305,7 @@ nsresult
|
||||
nsHTMLDocument::ChangeContentEditableCount(nsIContent *aElement,
|
||||
PRInt32 aChange)
|
||||
{
|
||||
NS_ASSERTION(mContentEditableCount + aChange >= 0,
|
||||
NS_ASSERTION(PRInt32(mContentEditableCount) + aChange >= 0,
|
||||
"Trying to decrement too much.");
|
||||
|
||||
mContentEditableCount += aChange;
|
||||
@ -2877,8 +2877,8 @@ static const char* const gBlocks[] = {
|
||||
};
|
||||
|
||||
static bool
|
||||
ConvertToMidasInternalCommandInner(const nsAString & inCommandID,
|
||||
const nsAString & inParam,
|
||||
ConvertToMidasInternalCommandInner(const nsAString& inCommandID,
|
||||
const nsAString& inParam,
|
||||
nsACString& outCommandID,
|
||||
nsACString& outParam,
|
||||
bool& outIsBoolean,
|
||||
@ -2892,8 +2892,7 @@ ConvertToMidasInternalCommandInner(const nsAString & inCommandID,
|
||||
if (convertedCommandID.LowerCaseEqualsLiteral("usecss")) {
|
||||
convertedCommandID.Assign("styleWithCSS");
|
||||
invertBool = true;
|
||||
}
|
||||
else if (convertedCommandID.LowerCaseEqualsLiteral("readonly")) {
|
||||
} else if (convertedCommandID.LowerCaseEqualsLiteral("readonly")) {
|
||||
convertedCommandID.Assign("contentReadOnly");
|
||||
invertBool = true;
|
||||
}
|
||||
@ -2908,70 +2907,84 @@ ConvertToMidasInternalCommandInner(const nsAString & inCommandID,
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
// set outCommandID (what we use internally)
|
||||
outCommandID.Assign(gMidasCommandTable[i].internalCommandString);
|
||||
|
||||
// set outParam & outIsBoolean based on flags from the table
|
||||
outIsBoolean = gMidasCommandTable[i].convertToBoolean;
|
||||
|
||||
if (!aIgnoreParams) {
|
||||
if (gMidasCommandTable[i].useNewParam) {
|
||||
outParam.Assign(gMidasCommandTable[i].internalParamString);
|
||||
}
|
||||
else {
|
||||
// handle checking of param passed in
|
||||
if (outIsBoolean) {
|
||||
// if this is a boolean value and it's not explicitly false
|
||||
// (e.g. no value) we default to "true". For old backwards commands
|
||||
// we invert the check (see bug 301490).
|
||||
if (invertBool) {
|
||||
outBooleanValue = inParam.LowerCaseEqualsLiteral("false");
|
||||
}
|
||||
else {
|
||||
outBooleanValue = !inParam.LowerCaseEqualsLiteral("false");
|
||||
}
|
||||
outParam.Truncate();
|
||||
}
|
||||
else {
|
||||
// check to see if we need to convert the parameter
|
||||
if (outCommandID.EqualsLiteral("cmd_paragraphState")) {
|
||||
const PRUnichar *start = inParam.BeginReading();
|
||||
const PRUnichar *end = inParam.EndReading();
|
||||
if (start != end && *start == '<' && *(end - 1) == '>') {
|
||||
++start;
|
||||
--end;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 convertedParam(Substring(start, end));
|
||||
PRUint32 j;
|
||||
for (j = 0; j < ArrayLength(gBlocks); ++j) {
|
||||
if (convertedParam.Equals(gBlocks[j],
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
outParam.Assign(gBlocks[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == ArrayLength(gBlocks)) {
|
||||
outParam.Truncate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
CopyUTF16toUTF8(inParam, outParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end else for useNewParam (do convert existing param)
|
||||
else {
|
||||
if (!found) {
|
||||
// reset results if the command is not found in our table
|
||||
outCommandID.SetLength(0);
|
||||
outParam.SetLength(0);
|
||||
outIsBoolean = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return found;
|
||||
// set outCommandID (what we use internally)
|
||||
outCommandID.Assign(gMidasCommandTable[i].internalCommandString);
|
||||
|
||||
// set outParam & outIsBoolean based on flags from the table
|
||||
outIsBoolean = gMidasCommandTable[i].convertToBoolean;
|
||||
|
||||
if (aIgnoreParams) {
|
||||
// No further work to do
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gMidasCommandTable[i].useNewParam) {
|
||||
// Just have to copy it, no checking
|
||||
outParam.Assign(gMidasCommandTable[i].internalParamString);
|
||||
return true;
|
||||
}
|
||||
|
||||
// handle checking of param passed in
|
||||
if (outIsBoolean) {
|
||||
// If this is a boolean value and it's not explicitly false (e.g. no value)
|
||||
// we default to "true". For old backwards commands we invert the check (see
|
||||
// bug 301490).
|
||||
if (invertBool) {
|
||||
outBooleanValue = inParam.LowerCaseEqualsLiteral("false");
|
||||
} else {
|
||||
outBooleanValue = !inParam.LowerCaseEqualsLiteral("false");
|
||||
}
|
||||
outParam.Truncate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// String parameter -- see if we need to convert it (necessary for
|
||||
// cmd_paragraphState and cmd_fontSize)
|
||||
if (outCommandID.EqualsLiteral("cmd_paragraphState")) {
|
||||
const PRUnichar* start = inParam.BeginReading();
|
||||
const PRUnichar* end = inParam.EndReading();
|
||||
if (start != end && *start == '<' && *(end - 1) == '>') {
|
||||
++start;
|
||||
--end;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 convertedParam(Substring(start, end));
|
||||
PRUint32 j;
|
||||
for (j = 0; j < ArrayLength(gBlocks); ++j) {
|
||||
if (convertedParam.Equals(gBlocks[j],
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
outParam.Assign(gBlocks[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == ArrayLength(gBlocks)) {
|
||||
outParam.Truncate();
|
||||
}
|
||||
} else if (outCommandID.EqualsLiteral("cmd_fontSize")) {
|
||||
// Per editing spec as of April 23, 2012, we need to reject the value if
|
||||
// it's not a valid floating-point number surrounded by optional whitespace.
|
||||
// Otherwise, we parse it as a legacy font size. For now, we just parse as
|
||||
// a legacy font size regardless (matching WebKit) -- bug 747879.
|
||||
outParam.Truncate();
|
||||
PRInt32 size = nsContentUtils::ParseLegacyFontSize(inParam);
|
||||
if (size) {
|
||||
outParam.AppendInt(size);
|
||||
}
|
||||
} else {
|
||||
CopyUTF16toUTF8(inParam, outParam);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -3103,7 +3116,8 @@ nsHTMLDocument::ExecCommand(const nsAString & commandID,
|
||||
cmdToDispatch, paramStr, isBool, boolVal))
|
||||
return NS_OK;
|
||||
|
||||
if (cmdToDispatch.EqualsLiteral("cmd_paragraphState") && paramStr.IsEmpty()) {
|
||||
if ((cmdToDispatch.EqualsLiteral("cmd_paragraphState") ||
|
||||
cmdToDispatch.EqualsLiteral("cmd_fontSize")) && paramStr.IsEmpty()) {
|
||||
// Invalid value
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include "MediaResource.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "prlog.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "FileBlockCache.h"
|
||||
|
||||
@ -123,7 +122,7 @@ void nsMediaCacheFlusher::Init()
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->AddObserver(gMediaCacheFlusher, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
|
||||
observerService->AddObserver(gMediaCacheFlusher, "last-pb-context-exited", true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,8 +373,7 @@ protected:
|
||||
NS_IMETHODIMP
|
||||
nsMediaCacheFlusher::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
|
||||
{
|
||||
if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0 &&
|
||||
NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
|
||||
if (strcmp(aTopic, "last-pb-context-exited") == 0) {
|
||||
nsMediaCache::Flush();
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -255,10 +255,10 @@ nsXBLJSClass::Destroy()
|
||||
|
||||
// Constructors/Destructors
|
||||
nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
|
||||
: mPrototypeBinding(aBinding),
|
||||
mInsertionPointTable(nsnull),
|
||||
mIsStyleBinding(true),
|
||||
mMarkedForDeath(false)
|
||||
: mIsStyleBinding(true),
|
||||
mMarkedForDeath(false),
|
||||
mPrototypeBinding(aBinding),
|
||||
mInsertionPointTable(nsnull)
|
||||
{
|
||||
NS_ASSERTION(mPrototypeBinding, "Must have a prototype binding!");
|
||||
// Grab a ref to the document info so the prototype binding won't die
|
||||
|
@ -156,6 +156,9 @@ public:
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
|
||||
bool mIsStyleBinding;
|
||||
bool mMarkedForDeath;
|
||||
|
||||
nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo
|
||||
nsCOMPtr<nsIContent> mContent; // Strong. Our anonymous content stays around with us.
|
||||
nsRefPtr<nsXBLBinding> mNextBinding; // Strong. The derived binding owns the base class bindings.
|
||||
@ -164,9 +167,6 @@ protected:
|
||||
|
||||
// A hash from nsIContent* -> (a sorted array of nsXBLInsertionPoint)
|
||||
nsClassHashtable<nsISupportsHashKey, nsInsertionPointList>* mInsertionPointTable;
|
||||
|
||||
bool mIsStyleBinding;
|
||||
bool mMarkedForDeath;
|
||||
};
|
||||
|
||||
#endif // nsXBLBinding_h_
|
||||
|
@ -83,6 +83,7 @@ XPIDLSRCS = \
|
||||
nsIRefreshURI.idl \
|
||||
nsIContentViewerContainer.idl \
|
||||
nsIDocumentLoaderFactory.idl \
|
||||
nsIPrivacyTransitionObserver.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
@ -114,6 +115,8 @@ CPPSRCS = \
|
||||
# static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
|
@ -68,7 +68,8 @@ nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell)
|
||||
if (NS_UNLIKELY(!initializedPrefCache)) {
|
||||
// Lock the pref so that the user's changes to it, if any, are ignored.
|
||||
nsIPrefBranch *root = Preferences::GetRootBranch();
|
||||
root->LockPref("b2g.ignoreXFrameOptions");
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Content)
|
||||
root->LockPref("b2g.ignoreXFrameOptions");
|
||||
|
||||
Preferences::AddBoolVarCache(&sIgnoreXFrameOptions, "b2g.ignoreXFrameOptions");
|
||||
initializedPrefCache = true;
|
||||
|
@ -41,6 +41,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
@ -106,6 +107,7 @@
|
||||
#include "nsIScriptChannel.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIPrivacyTransitionObserver.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsJSON.h"
|
||||
#include "IHistory.h"
|
||||
@ -714,6 +716,19 @@ ConvertLoadTypeToNavigationType(PRUint32 aLoadType)
|
||||
|
||||
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
|
||||
|
||||
static void
|
||||
IncreasePrivateDocShellCount()
|
||||
{
|
||||
gNumberOfPrivateDocShells++;
|
||||
if (gNumberOfPrivateDocShells > 1 ||
|
||||
XRE_GetProcessType() != GeckoProcessType_Content) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
|
||||
cc->SendPrivateDocShellsExist(true);
|
||||
}
|
||||
|
||||
static void
|
||||
DecreasePrivateDocShellCount()
|
||||
{
|
||||
@ -721,9 +736,16 @@ DecreasePrivateDocShellCount()
|
||||
gNumberOfPrivateDocShells--;
|
||||
if (!gNumberOfPrivateDocShells)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
|
||||
cc->SendPrivateDocShellsExist(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsvc = mozilla::services::GetObserverService();
|
||||
if (obsvc)
|
||||
if (obsvc) {
|
||||
obsvc->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2020,10 +2042,11 @@ nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing)
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
|
||||
{
|
||||
if (aUsePrivateBrowsing != mInPrivateBrowsing) {
|
||||
bool changed = aUsePrivateBrowsing != mInPrivateBrowsing;
|
||||
if (changed) {
|
||||
mInPrivateBrowsing = aUsePrivateBrowsing;
|
||||
if (aUsePrivateBrowsing) {
|
||||
gNumberOfPrivateDocShells++;
|
||||
IncreasePrivateDocShellCount();
|
||||
} else {
|
||||
DecreasePrivateDocShellCount();
|
||||
}
|
||||
@ -2036,9 +2059,32 @@ nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
|
||||
shell->SetUsePrivateBrowsing(aUsePrivateBrowsing);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
|
||||
while (iter.HasMore()) {
|
||||
nsWeakPtr ref = iter.GetNext();
|
||||
nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
|
||||
if (!obs) {
|
||||
mPrivacyObservers.RemoveElement(ref);
|
||||
} else {
|
||||
obs->PrivateModeChanged(aUsePrivateBrowsing);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddWeakPrivacyTransitionObserver(nsIPrivacyTransitionObserver* aObserver)
|
||||
{
|
||||
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
|
||||
if (!weakObs) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::GetAllowMetaRedirects(bool * aReturn)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aReturn);
|
||||
|
@ -847,6 +847,7 @@ protected:
|
||||
private:
|
||||
nsCOMPtr<nsIAtom> mForcedCharset;
|
||||
nsCOMPtr<nsIAtom> mParentCharset;
|
||||
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
||||
PRInt32 mParentCharsetSource;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -71,8 +71,9 @@ interface nsIDOMStorage;
|
||||
interface nsIPrincipal;
|
||||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
interface nsIPrivacyTransitionObserver;
|
||||
|
||||
[scriptable, uuid(c7325422-817e-4321-957a-c0bdd764941d)]
|
||||
[scriptable, uuid(6f60ac96-fa2c-41a5-92b4-29aaadbd7a7b)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -603,6 +604,12 @@ interface nsIDocShell : nsISupports
|
||||
*/
|
||||
attribute PRInt32 parentCharsetSource;
|
||||
|
||||
/**
|
||||
* Add an observer to the list of parties to be notified when this docshell's
|
||||
* private browsing status is changed. |obs| must support weak references.
|
||||
*/
|
||||
void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
|
||||
|
||||
/*
|
||||
* Is this docshell a browser frame (i.e., does it correspond to an <iframe
|
||||
* mozbrowser>)? The frameloader is responsible for setting this property
|
||||
|
11
docshell/base/nsIPrivacyTransitionObserver.idl
Normal file
11
docshell/base/nsIPrivacyTransitionObserver.idl
Normal file
@ -0,0 +1,11 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, function, uuid(b4b1449d-0ef0-47f5-b62e-adc57fd49702)]
|
||||
interface nsIPrivacyTransitionObserver : nsISupports
|
||||
{
|
||||
void privateModeChanged(in bool enabled);
|
||||
};
|
@ -47,10 +47,14 @@ DIRS += chrome \
|
||||
navigation \
|
||||
$(NULL)
|
||||
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPCSHELL_TESTS = unit
|
||||
# FIXME/bug 575918: out-of-process xpcshell is broken on OS X
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
XPCSHELL_TESTS += unit_ipc
|
||||
endif
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
DIRS += browser
|
||||
endif
|
||||
|
23
docshell/test/unit/test_pb_notification.js
Normal file
23
docshell/test/unit/test_pb_notification.js
Normal file
@ -0,0 +1,23 @@
|
||||
if (typeof Cc === "undefined")
|
||||
Cc = Components.classes;
|
||||
if (typeof Ci === "undefined")
|
||||
Ci = Components.interfaces;
|
||||
|
||||
function destroy_transient_docshell() {
|
||||
var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
|
||||
docshell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
|
||||
do_test_pending();
|
||||
do_timeout(0, Components.utils.forceGC);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
var obs = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
do_check_eq(aTopic, "last-pb-context-exited");
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(obs, "last-pb-context-exited", false);
|
||||
destroy_transient_docshell();
|
||||
}
|
23
docshell/test/unit/test_privacy_transition.js
Normal file
23
docshell/test/unit/test_privacy_transition.js
Normal file
@ -0,0 +1,23 @@
|
||||
var gNotifications = 0;
|
||||
|
||||
var observer = {
|
||||
QueryInterface: function(iid) {
|
||||
if (Ci.nsIPrivacyTransitionObserver.equals(iid) ||
|
||||
Ci.nsISupportsWeakReference.equals(iid) ||
|
||||
Ci.nsISupports.equals(iid))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
privateModeChanged: function(enabled) {
|
||||
gNotifications++;
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
|
||||
docshell.addWeakPrivacyTransitionObserver(observer);
|
||||
docshell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
|
||||
docshell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = false;
|
||||
do_check_eq(gNotifications, 2);
|
||||
}
|
@ -5,3 +5,5 @@ tail =
|
||||
[test_bug414201_jfif.js]
|
||||
[test_bug442584.js]
|
||||
[test_nsIDownloadHistory.js]
|
||||
[test_pb_notification.js]
|
||||
[test_privacy_transition.js]
|
20
docshell/test/unit_ipc/test_pb_notification_ipc.js
Normal file
20
docshell/test/unit_ipc/test_pb_notification_ipc.js
Normal file
@ -0,0 +1,20 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function run_test() {
|
||||
var notifications = 0;
|
||||
var obs = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
do_check_eq(aTopic, "last-pb-context-exited");
|
||||
notifications++;
|
||||
}
|
||||
};
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(obs, "last-pb-context-exited", false);
|
||||
|
||||
run_test_in_child("../unit/test_pb_notification.js",
|
||||
function() {
|
||||
do_check_eq(notifications, 1);
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
5
docshell/test/unit_ipc/xpcshell.ini
Normal file
5
docshell/test/unit_ipc/xpcshell.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_pb_notification_ipc.js]
|
@ -98,6 +98,7 @@
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
#include "nsIInlineEventHandlers.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
||||
// JS includes
|
||||
#include "jsapi.h"
|
||||
|
@ -188,9 +188,11 @@ class CGList(CGThing):
|
||||
def prepend(self, child):
|
||||
self.children.insert(0, child)
|
||||
def declare(self):
|
||||
return self.joiner.join([child.declare() for child in self.children])
|
||||
return self.joiner.join([child.declare() for child in self.children
|
||||
if child is not None])
|
||||
def define(self):
|
||||
return self.joiner.join([child.define() for child in self.children])
|
||||
return self.joiner.join([child.define() for child in self.children
|
||||
if child is not None])
|
||||
|
||||
class CGGeneric(CGThing):
|
||||
"""
|
||||
@ -237,7 +239,7 @@ class CGWrapper(CGThing):
|
||||
"""
|
||||
def __init__(self, child, pre="", post="", declarePre=None,
|
||||
declarePost=None, definePre=None, definePost=None,
|
||||
declareOnly=False):
|
||||
declareOnly=False, reindent=False):
|
||||
CGThing.__init__(self)
|
||||
self.child = child
|
||||
self.declarePre = declarePre or pre
|
||||
@ -245,12 +247,25 @@ class CGWrapper(CGThing):
|
||||
self.definePre = definePre or pre
|
||||
self.definePost = definePost or post
|
||||
self.declareOnly = declareOnly
|
||||
self.reindent = reindent
|
||||
def declare(self):
|
||||
return self.declarePre + self.child.declare() + self.declarePost
|
||||
decl = self.child.declare()
|
||||
if self.reindent:
|
||||
# We don't use lineStartDetector because we don't want to
|
||||
# insert whitespace at the beginning of our _first_ line.
|
||||
decl = stripTrailingWhitespace(
|
||||
decl.replace("\n", "\n" + (" " * len(self.declarePre))))
|
||||
return self.declarePre + decl + self.declarePost
|
||||
def define(self):
|
||||
if self.declareOnly:
|
||||
return ''
|
||||
return self.definePre + self.child.define() + self.definePost
|
||||
defn = self.child.define()
|
||||
if self.reindent:
|
||||
# We don't use lineStartDetector because we don't want to
|
||||
# insert whitespace at the beginning of our _first_ line.
|
||||
defn = stripTrailingWhitespace(
|
||||
defn.replace("\n", "\n" + (" " * len(self.definePre))))
|
||||
return self.definePre + defn + self.definePost
|
||||
|
||||
class CGNamespace(CGWrapper):
|
||||
def __init__(self, namespace, child, declareOnly=False):
|
||||
@ -810,45 +825,54 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
idsToInit.append(props.variableName(False))
|
||||
if props.hasChromeOnly() and not self.descriptor.workers:
|
||||
idsToInit.append(props.variableName(True))
|
||||
initIds = ""
|
||||
if len(idsToInit) > 0:
|
||||
init = ' ||\n '.join(["!InitIds(aCx, %s, %s_ids)" % (varname, varname)
|
||||
for varname in idsToInit])
|
||||
initIds = CGList(
|
||||
[CGGeneric("!InitIds(aCx, %s, %s_ids)" % (varname, varname)) for
|
||||
varname in idsToInit], ' ||\n')
|
||||
if len(idsToInit) > 1:
|
||||
init = '(' + init + ')'
|
||||
initIds = (" if (%s_ids[0] == JSID_VOID &&\n" +
|
||||
" %s) {\n" +
|
||||
" %s_ids[0] = JSID_VOID;\n"
|
||||
" return NULL;\n"
|
||||
" }\n\n") % (idsToInit[0], init, idsToInit[0])
|
||||
initIds = CGWrapper(initIds, pre="(", post=")", reindent=True)
|
||||
initIds = CGList(
|
||||
[CGGeneric("%s_ids[0] == JSID_VOID &&" % idsToInit[0]), initIds],
|
||||
"\n")
|
||||
initIds = CGWrapper(initIds, pre="if (", post=") {", reindent=True)
|
||||
initIds = CGList(
|
||||
[initIds,
|
||||
CGGeneric((" %s_ids[0] = JSID_VOID;\n"
|
||||
" return NULL;") % idsToInit[0]),
|
||||
CGGeneric("}")],
|
||||
"\n")
|
||||
else:
|
||||
initIds = None
|
||||
|
||||
getParentProto = (" JSObject* parentProto = %s;\n" +
|
||||
" if (!parentProto) {\n" +
|
||||
" return NULL;\n" +
|
||||
" }") % getParentProto
|
||||
getParentProto = ("JSObject* parentProto = %s;\n"
|
||||
"if (!parentProto) {\n"
|
||||
" return NULL;\n"
|
||||
"}") % getParentProto
|
||||
|
||||
call = """return bindings::CreateInterfaceObjects(aCx, aGlobal, parentProto,
|
||||
%s, %s,
|
||||
%%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,
|
||||
%s);""" % (
|
||||
call = CGGeneric(("return bindings::CreateInterfaceObjects(aCx, aGlobal, parentProto,\n"
|
||||
" %s, %s,\n"
|
||||
" %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n"
|
||||
" %s);") % (
|
||||
"&PrototypeClass" if needInterfacePrototypeObject else "NULL",
|
||||
"&InterfaceObjectClass" if needInterfaceObject else "NULL",
|
||||
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL")
|
||||
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
|
||||
|
||||
if self.properties.hasChromeOnly():
|
||||
if self.descriptor.workers:
|
||||
accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
|
||||
else:
|
||||
accessCheck = "xpc::AccessCheck::isChrome(js::GetObjectCompartment(aGlobal))"
|
||||
chrome = """
|
||||
|
||||
if (%s) {
|
||||
%s
|
||||
}
|
||||
""" % (accessCheck, call.replace("\n ", "\n ") % self.properties.variableNames(True))
|
||||
accessCheck = "if (" + accessCheck + ") {\n"
|
||||
chrome = CGWrapper(CGGeneric((CGIndenter(call).define() % self.properties.variableNames(True))),
|
||||
pre=accessCheck, post="\n}")
|
||||
else:
|
||||
chrome = ""
|
||||
return initIds + getParentProto + chrome + "\n " + call % self.properties.variableNames(False)
|
||||
chrome = None
|
||||
|
||||
functionBody = CGList(
|
||||
[CGGeneric(getParentProto), initIds, chrome,
|
||||
CGGeneric(call.define() % self.properties.variableNames(False))],
|
||||
"\n\n")
|
||||
return CGIndenter(functionBody).define()
|
||||
|
||||
class CGGetPerInterfaceObject(CGAbstractMethod):
|
||||
"""
|
||||
@ -912,7 +936,7 @@ def CheckPref(descriptor, scopeName, varName, retval, wrapperCache = None):
|
||||
else:
|
||||
wrapperCache = ""
|
||||
return """
|
||||
if (!%s->ParisBindingsEnabled()) {
|
||||
if (!%s->ExperimentalBindingsEnabled()) {
|
||||
%s %s = false;
|
||||
return %s;
|
||||
}
|
||||
@ -1219,8 +1243,8 @@ def getArgumentConversionTemplate(type, descriptor):
|
||||
nullBehavior = "eNull"
|
||||
undefinedBehavior = "eNull"
|
||||
else:
|
||||
nullBehavior = "eDefaultNullBehavior"
|
||||
undefinedBehavior = "eDefaultUndefinedBehavior"
|
||||
nullBehavior = "eStringify"
|
||||
undefinedBehavior = "eStringify"
|
||||
|
||||
return (
|
||||
" xpc_qsDOMString ${name}(cx, ${argVal}, ${argPtr},\n"
|
||||
@ -1488,11 +1512,15 @@ def getWrapTemplateForTypeImpl(type, result, descriptorProvider,
|
||||
if type.isCallback() and not type.isInterface():
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable and always have [TreatNonCallableAsNull] for now.
|
||||
# See comments in WrapNewBindingObject explaining why we need
|
||||
# to wrap here.
|
||||
return """
|
||||
${jsvalRef} = JS::ObjectOrNullValue(%s);
|
||||
return JS_WrapValue(cx, ${jsvalPtr});""" % result
|
||||
|
||||
if type.tag() == IDLType.Tags.any:
|
||||
# See comments in WrapNewBindingObject explaining why we need
|
||||
# to wrap here.
|
||||
return """
|
||||
${jsvalRef} = %s;\n
|
||||
return JS_WrapValue(cx, ${jsvalPtr});""" % result
|
||||
@ -1736,12 +1764,12 @@ class CGCase(CGList):
|
||||
def __init__(self, expression, body, fallThrough=False):
|
||||
CGList.__init__(self, [], "\n")
|
||||
self.append(CGWrapper(CGGeneric(expression), pre="case ", post=": {"))
|
||||
if body is not None:
|
||||
self.append(CGIndenter(body))
|
||||
bodyList = CGList([body], "\n")
|
||||
if fallThrough:
|
||||
self.append(CGIndenter(CGGeneric("/* Fall through */")))
|
||||
bodyList.append(CGGeneric("/* Fall through */"))
|
||||
else:
|
||||
self.append(CGIndenter(CGGeneric("break;")))
|
||||
bodyList.append(CGGeneric("break;"))
|
||||
self.append(CGIndenter(bodyList));
|
||||
self.append(CGGeneric("}"))
|
||||
|
||||
class CGMethodCall(CGThing):
|
||||
|
@ -36,6 +36,14 @@ public:
|
||||
mIsNull = false;
|
||||
}
|
||||
|
||||
// For cases when |T| is some type with nontrivial copy behavior, we may want
|
||||
// to get a reference to our internal copy of T and work with it directly
|
||||
// instead of relying on the copying version of SetValue().
|
||||
T& SetValue() {
|
||||
mIsNull = false;
|
||||
return mValue;
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
mIsNull = true;
|
||||
}
|
||||
|
@ -69,7 +69,8 @@ CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
|
||||
JSPropertySpec* properties,
|
||||
ConstantSpec* constants)
|
||||
{
|
||||
JSObject* ourProto = JS_NewObject(cx, protoClass, parentProto, global);
|
||||
JSObject* ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto,
|
||||
global);
|
||||
if (!ourProto) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -270,12 +270,12 @@ WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
|
||||
}
|
||||
}
|
||||
|
||||
// Now make sure that |obj| is wrapped for the compartment of |scope|
|
||||
// correctly. That means entering the compartment of |scope|.
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(cx, scope)) {
|
||||
return false;
|
||||
}
|
||||
// When called via XrayWrapper, we end up here while running in the
|
||||
// chrome compartment. But the obj we have would be created in
|
||||
// whatever the content compartment is. So at this point we need to
|
||||
// make sure it's correctly wrapped for the compartment of |scope|.
|
||||
// cx should already be in the compartment of |scope| here.
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
|
||||
*vp = JS::ObjectValue(*obj);
|
||||
return JS_WrapValue(cx, vp);
|
||||
}
|
||||
|
@ -819,5 +819,13 @@ ContentChild::RecvSetID(const PRUint64 &id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvLastPrivateDocShellDestroyed()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -170,6 +170,8 @@ public:
|
||||
virtual bool RecvAppInfo(const nsCString& version, const nsCString& buildID);
|
||||
virtual bool RecvSetID(const PRUint64 &id);
|
||||
|
||||
virtual bool RecvLastPrivateDocShellDestroyed();
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
|
@ -163,6 +163,7 @@ MemoryReportRequestParent::~MemoryReportRequestParent()
|
||||
}
|
||||
|
||||
nsTArray<ContentParent*>* ContentParent::gContentParents;
|
||||
nsTArray<ContentParent*>* ContentParent::gPrivateContent;
|
||||
|
||||
// The first content child has ID 1, so the chrome process can have ID 0.
|
||||
static PRUint64 gContentChildID = 1;
|
||||
@ -211,6 +212,7 @@ ContentParent::Init()
|
||||
obs->AddObserver(this, "memory-pressure", false);
|
||||
obs->AddObserver(this, "child-gc-request", false);
|
||||
obs->AddObserver(this, "child-cc-request", false);
|
||||
obs->AddObserver(this, "last-pb-context-exited", false);
|
||||
#ifdef ACCESSIBILITY
|
||||
obs->AddObserver(this, "a11y-init-or-shutdown", false);
|
||||
#endif
|
||||
@ -308,6 +310,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC);
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-gc-request");
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-cc-request");
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "last-pb-context-exited");
|
||||
#ifdef ACCESSIBILITY
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
|
||||
#endif
|
||||
@ -339,6 +342,14 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
}
|
||||
}
|
||||
|
||||
if (gPrivateContent) {
|
||||
gPrivateContent->RemoveElement(this);
|
||||
if (!gPrivateContent->Length()) {
|
||||
delete gPrivateContent;
|
||||
gPrivateContent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mIsAlive = false;
|
||||
|
||||
if (obs) {
|
||||
@ -723,6 +734,9 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
else if (!strcmp(aTopic, "child-cc-request")){
|
||||
SendCycleCollect();
|
||||
}
|
||||
else if (!strcmp(aTopic, "last-pb-context-exited")) {
|
||||
unused << SendLastPrivateDocShellDestroyed();
|
||||
}
|
||||
#ifdef ACCESSIBILITY
|
||||
// Make sure accessibility is running in content process when accessibility
|
||||
// gets initiated in chrome process.
|
||||
@ -1234,5 +1248,24 @@ ContentParent::RecvScriptError(const nsString& aMessage,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
|
||||
{
|
||||
if (!gPrivateContent)
|
||||
gPrivateContent = new nsTArray<ContentParent*>;
|
||||
if (aExist) {
|
||||
gPrivateContent->AppendElement(this);
|
||||
} else {
|
||||
gPrivateContent->RemoveElement(this);
|
||||
if (!gPrivateContent->Length()) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
|
||||
delete gPrivateContent;
|
||||
gPrivateContent = NULL;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -110,6 +110,7 @@ protected:
|
||||
|
||||
private:
|
||||
static nsTArray<ContentParent*>* gContentParents;
|
||||
static nsTArray<ContentParent*>* gPrivateContent;
|
||||
|
||||
// Hide the raw constructor methods since we don't want client code
|
||||
// using them.
|
||||
@ -222,6 +223,8 @@ private:
|
||||
const PRUint32& aFlags,
|
||||
const nsCString& aCategory);
|
||||
|
||||
virtual bool RecvPrivateDocShellsExist(const bool& aExist);
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
||||
PRInt32 mGeolocationWatchID;
|
||||
|
@ -149,6 +149,9 @@ child:
|
||||
|
||||
SetID(PRUint64 id);
|
||||
|
||||
// Notify child that last-pb-context-exited notification was observed
|
||||
LastPrivateDocShellDestroyed();
|
||||
|
||||
parent:
|
||||
PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
|
||||
|
||||
@ -226,6 +229,9 @@ parent:
|
||||
sync GetShowPasswordSetting()
|
||||
returns (bool showPassword);
|
||||
|
||||
// Notify the parent of the presence or absence of private docshells
|
||||
PrivateDocShellsExist(bool aExist);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, nsString aJSON);
|
||||
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include "nsNPAPIPluginStreamListener.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "nsIPluginStreamListener.h"
|
||||
@ -105,6 +104,8 @@
|
||||
#include "nsJSNPRuntime.h"
|
||||
#include "nsIHttpAuthManager.h"
|
||||
#include "nsICookieService.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
@ -2135,11 +2136,12 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
|
||||
}
|
||||
|
||||
case NPNVprivateModeBool: {
|
||||
nsCOMPtr<nsIPrivateBrowsingService> pbs = do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
|
||||
if (pbs) {
|
||||
bool enabled;
|
||||
pbs->GetPrivateBrowsingEnabled(&enabled);
|
||||
*(NPBool*)result = (NPBool)enabled;
|
||||
nsCOMPtr<nsIDocument> doc = GetDocumentFromNPP(npp);
|
||||
nsCOMPtr<nsPIDOMWindow> domwindow = do_QueryInterface(doc);
|
||||
if (domwindow) {
|
||||
nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
|
||||
*(NPBool*)result = (NPBool)(loadContext && loadContext->UsePrivateBrowsing());
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginSafety.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
@ -152,7 +151,7 @@ nsresult nsNPAPIPluginInstance::Initialize(nsNPAPIPlugin *aPlugin, nsIPluginInst
|
||||
PL_strcpy(mMIMEType, aMIMEType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Start();
|
||||
}
|
||||
|
||||
@ -1143,7 +1142,7 @@ nsNPAPIPluginInstance::GetPluginAPIVersion(PRUint16* version)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNPAPIPluginInstance::PrivateModeStateChanged()
|
||||
nsNPAPIPluginInstance::PrivateModeStateChanged(bool enabled)
|
||||
{
|
||||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
@ -1155,23 +1154,15 @@ nsNPAPIPluginInstance::PrivateModeStateChanged()
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
if (pluginFunctions->setvalue) {
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
nsCOMPtr<nsIPrivateBrowsingService> pbs = do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
|
||||
if (pbs) {
|
||||
bool pme = false;
|
||||
nsresult rv = pbs->GetPrivateBrowsingEnabled(&pme);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!pluginFunctions->setvalue)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NPError error;
|
||||
NPBool value = static_cast<NPBool>(pme);
|
||||
NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value), this);
|
||||
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
NPError error;
|
||||
NPBool value = static_cast<NPBool>(enabled);
|
||||
NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value), this);
|
||||
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
class DelayUnscheduleEvent : public nsRunnable {
|
||||
|
@ -204,7 +204,7 @@ public:
|
||||
|
||||
already_AddRefed<nsPIDOMWindow> GetDOMWindow();
|
||||
|
||||
nsresult PrivateModeStateChanged();
|
||||
nsresult PrivateModeStateChanged(bool aEnabled);
|
||||
|
||||
nsresult GetDOMElement(nsIDOMElement* *result);
|
||||
|
||||
|
@ -86,7 +86,6 @@
|
||||
#include "nsIScriptChannel.h"
|
||||
#include "nsIBlocklistService.h"
|
||||
#include "nsVersionComparator.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
@ -359,7 +358,6 @@ nsPluginHost::nsPluginHost()
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsService) {
|
||||
obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
obsService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, false);
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
obsService->AddObserver(this, "application-foreground", false);
|
||||
obsService->AddObserver(this, "application-background", false);
|
||||
@ -2697,19 +2695,20 @@ nsPluginHost::ReadPluginInfo()
|
||||
return rv;
|
||||
|
||||
// kPluginRegistryVersion
|
||||
PRInt32 vdiff = NS_CompareVersions(values[1], kPluginRegistryVersion);
|
||||
PRInt32 vdiff = mozilla::CompareVersions(values[1], kPluginRegistryVersion);
|
||||
mozilla::Version version(values[1]);
|
||||
// If this is a registry from some future version then don't attempt to read it
|
||||
if (vdiff > 0)
|
||||
return rv;
|
||||
// If this is a registry from before the minimum then don't attempt to read it
|
||||
if (NS_CompareVersions(values[1], kMinimumRegistryVersion) < 0)
|
||||
if (version < kMinimumRegistryVersion)
|
||||
return rv;
|
||||
|
||||
// Registry v0.10 and upwards includes the plugin version field
|
||||
bool regHasVersion = NS_CompareVersions(values[1], "0.10") >= 0;
|
||||
bool regHasVersion = (version >= "0.10");
|
||||
|
||||
// Registry v0.13 and upwards includes the architecture
|
||||
if (NS_CompareVersions(values[1], "0.13") >= 0) {
|
||||
if (version >= "0.13") {
|
||||
char* archValues[6];
|
||||
|
||||
if (!reader.NextLine()) {
|
||||
@ -2743,7 +2742,7 @@ nsPluginHost::ReadPluginInfo()
|
||||
}
|
||||
|
||||
// Registry v0.13 and upwards includes the list of invalid plugins
|
||||
bool hasInvalidPlugins = (NS_CompareVersions(values[1], "0.13") >= 0);
|
||||
bool hasInvalidPlugins = (version >= "0.13");
|
||||
|
||||
if (!ReadSectionHeader(reader, "PLUGINS"))
|
||||
return rv;
|
||||
@ -2751,7 +2750,7 @@ nsPluginHost::ReadPluginInfo()
|
||||
#if defined(XP_MACOSX)
|
||||
bool hasFullPathInFileNameField = false;
|
||||
#else
|
||||
bool hasFullPathInFileNameField = (NS_CompareVersions(values[1], "0.11") < 0);
|
||||
bool hasFullPathInFileNameField = (version < "0.11");
|
||||
#endif
|
||||
|
||||
while (reader.NextLine()) {
|
||||
@ -3294,21 +3293,6 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
|
||||
UnloadPlugins();
|
||||
sInst->Release();
|
||||
}
|
||||
if (!nsCRT::strcmp(NS_PRIVATE_BROWSING_SWITCH_TOPIC, aTopic)) {
|
||||
// inform all active plugins of changed private mode state
|
||||
for (PRUint32 i = 0; i < mInstances.Length(); i++) {
|
||||
mInstances[i]->PrivateModeStateChanged();
|
||||
}
|
||||
}
|
||||
if (!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
|
||||
mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
|
||||
// Unload or load plugins as needed
|
||||
if (mPluginsDisabled) {
|
||||
UnloadPlugins();
|
||||
} else {
|
||||
LoadPlugins();
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
if (!nsCRT::strcmp("application-background", aTopic)) {
|
||||
for(PRUint32 i = 0; i < mInstances.Length(); i++) {
|
||||
|
@ -100,6 +100,7 @@ using mozilla::DefaultXDisplay;
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
@ -404,10 +405,12 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsPluginInstanceOwner,
|
||||
NS_IMPL_ISUPPORTS5(nsPluginInstanceOwner,
|
||||
nsIPluginInstanceOwner,
|
||||
nsIPluginTagInfo,
|
||||
nsIDOMEventListener)
|
||||
nsIDOMEventListener,
|
||||
nsIPrivacyTransitionObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
nsresult
|
||||
nsPluginInstanceOwner::SetInstance(nsNPAPIPluginInstance *aInstance)
|
||||
@ -427,6 +430,17 @@ nsPluginInstanceOwner::SetInstance(nsNPAPIPluginInstance *aInstance)
|
||||
|
||||
mInstance = aInstance;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
GetDocument(getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsPIDOMWindow> domWindow = doc->GetWindow();
|
||||
if (domWindow) {
|
||||
nsCOMPtr<nsIDocShell> docShell = domWindow->GetDocShell();
|
||||
if (docShell)
|
||||
docShell->AddWeakPrivacyTransitionObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3798,6 +3812,11 @@ void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::PrivateModeChanged(bool aEnabled)
|
||||
{
|
||||
return mInstance ? mInstance->PrivateModeStateChanged(aEnabled) : NS_OK;
|
||||
}
|
||||
|
||||
// nsPluginDOMContextMenuListener class implementation
|
||||
|
||||
nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener()
|
||||
|
@ -52,10 +52,12 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsIPluginTagInfo.h"
|
||||
#include "nsIPrivacyTransitionObserver.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "gfxRect.h"
|
||||
|
||||
// X.h defines KeyPress
|
||||
@ -103,7 +105,9 @@ namespace mozilla {
|
||||
class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
|
||||
public nsIPluginTagInfo,
|
||||
public nsIDOMEventListener,
|
||||
public nsIScrollPositionListener
|
||||
public nsIScrollPositionListener,
|
||||
public nsIPrivacyTransitionObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsPluginInstanceOwner();
|
||||
@ -111,6 +115,7 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGININSTANCEOWNER
|
||||
NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
|
||||
|
||||
NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
|
||||
nsIInputStream *aPostStream,
|
||||
|
@ -55,7 +55,7 @@ interface nsIEditActionListener;
|
||||
interface nsIInlineSpellChecker;
|
||||
interface nsITransferable;
|
||||
|
||||
[scriptable, uuid(2e14b183-29d4-4282-9475-589277a70654)]
|
||||
[scriptable, uuid(7861fe14-9977-413f-a893-3e1000c40817)]
|
||||
|
||||
interface nsIEditor : nsISupports
|
||||
{
|
||||
@ -497,6 +497,12 @@ interface nsIEditor : nsISupports
|
||||
*/
|
||||
void deleteNode(in nsIDOMNode child);
|
||||
|
||||
/**
|
||||
* Returns true if markNodeDirty() has any effect. Returns false if
|
||||
* markNodeDirty() is a no-op.
|
||||
*/
|
||||
[notxpcom] boolean outputsMozDirty();
|
||||
|
||||
/**
|
||||
* markNodeDirty() sets a special dirty attribute on the node.
|
||||
* Usually this will be called immediately after creating a new node.
|
||||
|
@ -147,34 +147,28 @@ extern nsIParserService *sParserService;
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
nsEditor::nsEditor()
|
||||
: mModCount(0)
|
||||
: mPlaceHolderName(nsnull)
|
||||
, mSelState(nsnull)
|
||||
, mPhonetic(nsnull)
|
||||
, mModCount(0)
|
||||
, mFlags(0)
|
||||
, mUpdateCount(0)
|
||||
, mSpellcheckCheckboxState(eTriUnset)
|
||||
, mPlaceHolderTxn(nsnull)
|
||||
, mPlaceHolderName(nsnull)
|
||||
, mPlaceHolderBatch(0)
|
||||
, mSelState(nsnull)
|
||||
, mSavedSel()
|
||||
, mRangeUpdater()
|
||||
, mAction(nsnull)
|
||||
, mDirection(eNone)
|
||||
, mIMETextNode(nsnull)
|
||||
, mHandlingActionCount(0)
|
||||
, mIMETextOffset(0)
|
||||
, mIMEBufferLength(0)
|
||||
, mDirection(eNone)
|
||||
, mDocDirtyState(-1)
|
||||
, mSpellcheckCheckboxState(eTriUnset)
|
||||
, mInIMEMode(false)
|
||||
, mIsIMEComposing(false)
|
||||
, mShouldTxnSetSelection(true)
|
||||
, mDidPreDestroy(false)
|
||||
, mDidPostCreate(false)
|
||||
, mDocDirtyState(-1)
|
||||
, mDocWeak(nsnull)
|
||||
, mPhonetic(nsnull)
|
||||
, mHandlingActionCount(0)
|
||||
, mHandlingTrustedAction(false)
|
||||
, mDispatchInputEvent(true)
|
||||
{
|
||||
//initialize member variables here
|
||||
}
|
||||
|
||||
nsEditor::~nsEditor()
|
||||
@ -1270,14 +1264,28 @@ nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsAString& aAttribute)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsEditor::OutputsMozDirty()
|
||||
{
|
||||
// Return true for Composer (!eEditorAllowInteraction) or mail
|
||||
// (eEditorMailMask), but false for webpages.
|
||||
return !(mFlags & nsIPlaintextEditor::eEditorAllowInteraction) ||
|
||||
(mFlags & nsIPlaintextEditor::eEditorMailMask);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::MarkNodeDirty(nsIDOMNode* aNode)
|
||||
{
|
||||
// mark the node dirty.
|
||||
nsCOMPtr<nsIContent> element (do_QueryInterface(aNode));
|
||||
if (element)
|
||||
// Mark the node dirty, but not for webpages (bug 599983)
|
||||
if (!OutputsMozDirty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
|
||||
if (element) {
|
||||
element->SetAttr(kNameSpaceID_None, nsEditProperty::mozdirty,
|
||||
EmptyString(), false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -218,8 +218,6 @@ public:
|
||||
void SwitchTextDirectionTo(PRUint32 aDirection);
|
||||
|
||||
protected:
|
||||
nsCString mContentMIMEType; // MIME type of the doc we are editing.
|
||||
|
||||
nsresult DetermineCurrentDirection();
|
||||
|
||||
/** create a transaction for setting aAttribute to aValue on aElement
|
||||
@ -793,59 +791,60 @@ public:
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mModCount; // number of modifications (for undo/redo stack)
|
||||
PRUint32 mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
|
||||
|
||||
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
|
||||
PRInt32 mUpdateCount;
|
||||
|
||||
// Spellchecking
|
||||
enum Tristate {
|
||||
eTriUnset,
|
||||
eTriFalse,
|
||||
eTriTrue
|
||||
} mSpellcheckCheckboxState;
|
||||
};
|
||||
// Spellchecking
|
||||
nsCString mContentMIMEType; // MIME type of the doc we are editing.
|
||||
|
||||
nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
|
||||
|
||||
nsCOMPtr<nsITransactionManager> mTxnMgr;
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
|
||||
// data necessary to build IME transactions
|
||||
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
|
||||
nsCOMPtr<nsIPrivateTextRangeList> mIMETextRangeList; // IME special selection ranges
|
||||
nsCOMPtr<nsIDOMCharacterData> mIMETextNode; // current IME text node
|
||||
PRUint32 mIMETextOffset; // offset in text node where IME comp string begins
|
||||
PRUint32 mIMEBufferLength; // current length of IME comp string
|
||||
bool mInIMEMode; // are we inside an IME composition?
|
||||
bool mIsIMEComposing; // is IME in composition state?
|
||||
// This is different from mInIMEMode. see Bug 98434.
|
||||
nsCOMPtr<nsIDOMEventTarget> mEventTarget; // The form field as an event receiver
|
||||
nsCOMPtr<nsIDOMEventListener> mEventListener;
|
||||
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsWeakPtr mDocWeak; // weak reference to the nsIDOMDocument
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsString *mPhonetic;
|
||||
|
||||
bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
bool mDidPreDestroy; // whether PreDestroy has been called
|
||||
bool mDidPostCreate; // whether PostCreate has been called
|
||||
// various listeners
|
||||
// various listeners
|
||||
nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc
|
||||
nsCOMArray<nsIEditorObserver> mEditorObservers; // just notify once per high level change
|
||||
nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)
|
||||
|
||||
PRInt8 mDocDirtyState; // -1 = not initialized
|
||||
nsWeakPtr mDocWeak; // weak reference to the nsIDOMDocument
|
||||
// The form field as an event receiver
|
||||
nsCOMPtr<nsIDOMEventTarget> mEventTarget;
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
|
||||
nsString* mPhonetic;
|
||||
PRUint32 mModCount; // number of modifications (for undo/redo stack)
|
||||
PRUint32 mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> mEventListener;
|
||||
PRInt32 mUpdateCount;
|
||||
|
||||
PRUint32 mHandlingActionCount;
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
PRInt32 mAction; // the current editor action
|
||||
PRUint32 mHandlingActionCount;
|
||||
|
||||
PRUint32 mIMETextOffset; // offset in text node where IME comp string begins
|
||||
PRUint32 mIMEBufferLength; // current length of IME comp string
|
||||
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
PRInt8 mDocDirtyState; // -1 = not initialized
|
||||
PRUint8 mSpellcheckCheckboxState; // a Tristate value
|
||||
|
||||
bool mInIMEMode; // are we inside an IME composition?
|
||||
bool mIsIMEComposing; // is IME in composition state?
|
||||
// This is different from mInIMEMode. see Bug 98434.
|
||||
|
||||
bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
bool mDidPreDestroy; // whether PreDestroy has been called
|
||||
bool mDidPostCreate; // whether PostCreate has been called
|
||||
bool mHandlingTrustedAction;
|
||||
bool mDispatchInputEvent;
|
||||
|
||||
|
@ -50,6 +50,7 @@ _TEST_FILES = \
|
||||
test_bug567213.html \
|
||||
file_bug586662.html \
|
||||
test_bug586662.html \
|
||||
test_bug599983.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_TEST_FILES = \
|
||||
@ -57,6 +58,7 @@ _CHROME_TEST_FILES = \
|
||||
test_bug46555.html \
|
||||
test_bug646194.xul \
|
||||
test_dragdrop.html \
|
||||
test_bug599983.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
16
editor/libeditor/base/tests/test_bug599983.html
Normal file
16
editor/libeditor/base/tests/test_bug599983.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=599983
|
||||
-->
|
||||
<title>Test for Bug 599983</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599983">Mozilla Bug 599983</a>
|
||||
<div contenteditable>foo</div>
|
||||
<script>
|
||||
getSelection().selectAllChildren(document.querySelector("div"));
|
||||
document.execCommand("bold");
|
||||
is(document.querySelector("[_moz_dirty]"), null,
|
||||
"No _moz_dirty allowed in webpages");
|
||||
</script>
|
70
editor/libeditor/base/tests/test_bug599983.xul
Normal file
70
editor/libeditor/base/tests/test_bug599983.xul
Normal file
@ -0,0 +1,70 @@
|
||||
<?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"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=599983
|
||||
-->
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Mozilla Bug 599983" onload="runTest()">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=599983"
|
||||
target="_blank">Mozilla Bug 599983</a>
|
||||
<editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="editor"
|
||||
editortype="html"
|
||||
src="about:blank" />
|
||||
</body>
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const kAllowInteraction = Components.interfaces.nsIPlaintextEditor
|
||||
.eEditorAllowInteraction;
|
||||
const kMailMask = Components.interfaces.nsIPlaintextEditor.eEditorMailMask;
|
||||
|
||||
function runTest() {
|
||||
testEditor(false, false);
|
||||
testEditor(false, true);
|
||||
testEditor(true, false);
|
||||
testEditor(true, true);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testEditor(setAllowInteraction, setMailMask) {
|
||||
var desc = " with " + (setAllowInteraction ? "" : "no ") +
|
||||
"eEditorAllowInteraction and " +
|
||||
(setMailMask ? "" : "no ") + "eEditorMailMask";
|
||||
|
||||
var editorElem = document.getElementById("editor");
|
||||
|
||||
var editorObj = editorElem.getEditor(editorElem.contentWindow);
|
||||
editorObj.flags = (setAllowInteraction ? kAllowInteraction : 0) |
|
||||
(setMailMask ? kMailMask : 0);
|
||||
|
||||
var editorDoc = editorElem.contentDocument;
|
||||
editorDoc.body.innerHTML = "<p>foo<p>bar";
|
||||
editorDoc.getSelection().selectAllChildren(editorDoc.body.firstChild);
|
||||
editorDoc.execCommand("bold");
|
||||
|
||||
var createsDirty = !setAllowInteraction || setMailMask;
|
||||
|
||||
(createsDirty ? isnot : is)(editorDoc.querySelector("[_moz_dirty]"), null,
|
||||
"Elements with _moz_dirty" + desc);
|
||||
|
||||
// Even if we do create _moz_dirty, we should strip it for innerHTML.
|
||||
is(editorDoc.body.innerHTML, "<p><b>foo</b></p><p>bar</p>",
|
||||
"innerHTML" + desc);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -55,6 +55,7 @@
|
||||
#include "nsAttrName.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -194,6 +195,45 @@ void ProcessMarginRightValue(const nsAString * aInputString, nsAString & aOutput
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void ProcessFontSizeValue(const nsAString* aInputString, nsAString& aOutputString,
|
||||
const char* aDefaultValueString,
|
||||
const char* aPrependString, const char* aAppendString)
|
||||
{
|
||||
aOutputString.Truncate();
|
||||
if (aInputString) {
|
||||
PRInt32 size = nsContentUtils::ParseLegacyFontSize(*aInputString);
|
||||
switch (size) {
|
||||
case 0:
|
||||
// Didn't parse
|
||||
return;
|
||||
case 1:
|
||||
aOutputString.AssignLiteral("x-small");
|
||||
return;
|
||||
case 2:
|
||||
aOutputString.AssignLiteral("small");
|
||||
return;
|
||||
case 3:
|
||||
aOutputString.AssignLiteral("medium");
|
||||
return;
|
||||
case 4:
|
||||
aOutputString.AssignLiteral("large");
|
||||
return;
|
||||
case 5:
|
||||
aOutputString.AssignLiteral("x-large");
|
||||
return;
|
||||
case 6:
|
||||
aOutputString.AssignLiteral("xx-large");
|
||||
return;
|
||||
case 7:
|
||||
// No corresponding CSS size
|
||||
return;
|
||||
default:
|
||||
NS_NOTREACHED("Unexpected return value from ParseLegacyFontSize");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nsHTMLCSSUtils::CSSEquivTable boldEquivTable[] = {
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_font_weight, ProcessBValue, nsnull, nsnull, nsnull, true, false },
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_NONE, 0 }
|
||||
@ -229,6 +269,11 @@ const nsHTMLCSSUtils::CSSEquivTable fontFaceEquivTable[] = {
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_NONE, 0 }
|
||||
};
|
||||
|
||||
const nsHTMLCSSUtils::CSSEquivTable fontSizeEquivTable[] = {
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_font_size, ProcessFontSizeValue, nsnull, nsnull, nsnull, true, false },
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_NONE, 0 }
|
||||
};
|
||||
|
||||
const nsHTMLCSSUtils::CSSEquivTable bgcolorEquivTable[] = {
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_background_color, ProcessSameValue, nsnull, nsnull, nsnull, true, false },
|
||||
{ nsHTMLCSSUtils::eCSSEditableProperty_NONE, 0 }
|
||||
@ -312,21 +357,23 @@ 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)
|
||||
nsHTMLCSSUtils::IsCSSEditableProperty(nsIDOMNode* aNode,
|
||||
nsIAtom* aProperty,
|
||||
const nsAString* aAttribute,
|
||||
const nsAString* aValue)
|
||||
{
|
||||
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);
|
||||
return IsCSSEditableProperty(content, aProperty, aAttribute, aValue);
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
|
||||
nsIAtom* aProperty,
|
||||
const nsAString* aAttribute)
|
||||
const nsAString* aAttribute,
|
||||
const nsAString* aValue)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
|
||||
@ -352,6 +399,16 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
|
||||
return true;
|
||||
}
|
||||
|
||||
// FONT SIZE doesn't work if the value is 7
|
||||
if (nsEditProperty::font == aProperty && aAttribute &&
|
||||
aAttribute->EqualsLiteral("size")) {
|
||||
if (!aValue || aValue->IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
PRInt32 size = nsContentUtils::ParseLegacyFontSize(*aValue);
|
||||
return size && size != 7;
|
||||
}
|
||||
|
||||
// ALIGN attribute on elements supporting it
|
||||
if (aAttribute && (aAttribute->EqualsLiteral("align")) &&
|
||||
(nsEditProperty::div == tagName
|
||||
@ -853,77 +910,67 @@ nsHTMLCSSUtils::GenerateCSSDeclarationsFromHTMLStyle(dom::Element* aElement,
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
nsIAtom* tagName = aElement->Tag();
|
||||
const nsHTMLCSSUtils::CSSEquivTable* equivTable = nsnull;
|
||||
|
||||
if (nsEditProperty::b == aHTMLProperty) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, boldEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::i == aHTMLProperty) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, italicEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::u == aHTMLProperty) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, underlineEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::strike == aHTMLProperty) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, strikeEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::tt == aHTMLProperty) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, ttEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute) {
|
||||
equivTable = boldEquivTable;
|
||||
} else if (nsEditProperty::i == aHTMLProperty) {
|
||||
equivTable = italicEquivTable;
|
||||
} else if (nsEditProperty::u == aHTMLProperty) {
|
||||
equivTable = underlineEquivTable;
|
||||
} else if (nsEditProperty::strike == aHTMLProperty) {
|
||||
equivTable = strikeEquivTable;
|
||||
} else if (nsEditProperty::tt == aHTMLProperty) {
|
||||
equivTable = ttEquivTable;
|
||||
} else if (aAttribute) {
|
||||
if (nsEditProperty::font == aHTMLProperty &&
|
||||
aAttribute->EqualsLiteral("color")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, fontColorEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::font == aHTMLProperty &&
|
||||
aAttribute->EqualsLiteral("face")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, fontFaceEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("bgcolor")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, bgcolorEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("background")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, backgroundImageEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("text")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, textColorEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("border")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, borderEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("align")) {
|
||||
equivTable = fontColorEquivTable;
|
||||
} else if (nsEditProperty::font == aHTMLProperty &&
|
||||
aAttribute->EqualsLiteral("face")) {
|
||||
equivTable = fontFaceEquivTable;
|
||||
} else if (nsEditProperty::font == aHTMLProperty &&
|
||||
aAttribute->EqualsLiteral("size")) {
|
||||
equivTable = fontSizeEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("bgcolor")) {
|
||||
equivTable = bgcolorEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("background")) {
|
||||
equivTable = backgroundImageEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("text")) {
|
||||
equivTable = textColorEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("border")) {
|
||||
equivTable = borderEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("align")) {
|
||||
if (nsEditProperty::table == tagName) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, tableAlignEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::hr == tagName) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, hrAlignEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (nsEditProperty::legend == tagName ||
|
||||
equivTable = tableAlignEquivTable;
|
||||
} else if (nsEditProperty::hr == tagName) {
|
||||
equivTable = hrAlignEquivTable;
|
||||
} else if (nsEditProperty::legend == tagName ||
|
||||
nsEditProperty::caption == tagName) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, captionAlignEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, textAlignEquivTable, aValue, aGetOrRemoveRequest);
|
||||
equivTable = captionAlignEquivTable;
|
||||
} else {
|
||||
equivTable = textAlignEquivTable;
|
||||
}
|
||||
} else if (aAttribute->EqualsLiteral("valign")) {
|
||||
equivTable = verticalAlignEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("nowrap")) {
|
||||
equivTable = nowrapEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("width")) {
|
||||
equivTable = widthEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("height") ||
|
||||
(nsEditProperty::hr == tagName &&
|
||||
aAttribute->EqualsLiteral("size"))) {
|
||||
equivTable = heightEquivTable;
|
||||
} else if (aAttribute->EqualsLiteral("type") &&
|
||||
(nsEditProperty::ol == tagName
|
||||
|| nsEditProperty::ul == tagName
|
||||
|| nsEditProperty::li == tagName)) {
|
||||
equivTable = listStyleTypeEquivTable;
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("valign")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, verticalAlignEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("nowrap")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, nowrapEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("width")) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, widthEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("height") ||
|
||||
(nsEditProperty::hr == tagName && aAttribute->EqualsLiteral("size"))) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, heightEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
else if (aAttribute->EqualsLiteral("type") &&
|
||||
(nsEditProperty::ol == tagName
|
||||
|| nsEditProperty::ul == tagName
|
||||
|| nsEditProperty::li == tagName)) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, listStyleTypeEquivTable, aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
}
|
||||
if (equivTable) {
|
||||
BuildCSSDeclarations(cssPropertyArray, cssValueArray, equivTable,
|
||||
aValue, aGetOrRemoveRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -939,7 +986,8 @@ nsHTMLCSSUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode * aNode,
|
||||
{
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
|
||||
*aCount = 0;
|
||||
if (!element || !IsCSSEditableProperty(element, aHTMLProperty, aAttribute)) {
|
||||
if (!element || !IsCSSEditableProperty(element, aHTMLProperty,
|
||||
aAttribute, aValue)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1015,7 +1063,8 @@ nsHTMLCSSUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
|
||||
nsCOMPtr<dom::Element> theElement = GetElementContainerOrSelf(aNode);
|
||||
NS_ENSURE_TRUE(theElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (!theElement || !IsCSSEditableProperty(theElement, aHTMLProperty, aAttribute)) {
|
||||
if (!theElement || !IsCSSEditableProperty(theElement, aHTMLProperty,
|
||||
aAttribute, &aValueString)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1048,17 +1097,16 @@ nsHTMLCSSUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Does the node aNode (or his parent if it is not an element node) carries
|
||||
// the CSS equivalent styles to the HTML style aHTMLProperty/aAttribute/
|
||||
// aValueString for this node ?
|
||||
// The value of aStyleType controls the styles we retrieve : specified or
|
||||
// computed. The return value aIsSet is true is the CSS styles are set.
|
||||
// Does the node aNode (or its parent, if it's not an element node) have a CSS
|
||||
// style equivalent to the HTML style aHTMLProperty/aHTMLAttribute/valueString?
|
||||
// The value of aStyleType controls the styles we retrieve: specified or
|
||||
// computed. The return value aIsSet is true if the CSS styles are set.
|
||||
nsresult
|
||||
nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode *aNode,
|
||||
nsIAtom *aHTMLProperty,
|
||||
const nsAString * aHTMLAttribute,
|
||||
bool & aIsSet,
|
||||
nsAString & valueString,
|
||||
const nsAString *aHTMLAttribute,
|
||||
bool& aIsSet,
|
||||
nsAString& valueString,
|
||||
PRUint8 aStyleType)
|
||||
{
|
||||
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
|
||||
@ -1066,7 +1114,6 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
nsAutoString htmlValueString(valueString);
|
||||
aIsSet = false;
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
NS_NAMED_LITERAL_STRING(boldStr, "bold");
|
||||
do {
|
||||
valueString.Assign(htmlValueString);
|
||||
// get the value of the CSS equivalent styles
|
||||
@ -1075,64 +1122,54 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// early way out if we can
|
||||
if (valueString.IsEmpty()) return NS_OK;
|
||||
if (valueString.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (nsEditProperty::b == aHTMLProperty) {
|
||||
if (valueString.Equals(boldStr)) {
|
||||
if (valueString.EqualsLiteral("bold")) {
|
||||
aIsSet = true;
|
||||
}
|
||||
else if (valueString.EqualsLiteral("normal")) {
|
||||
} else if (valueString.EqualsLiteral("normal")) {
|
||||
aIsSet = false;
|
||||
}
|
||||
else if (valueString.EqualsLiteral("bolder")) {
|
||||
} else if (valueString.EqualsLiteral("bolder")) {
|
||||
aIsSet = true;
|
||||
valueString.Assign(boldStr);
|
||||
}
|
||||
else {
|
||||
valueString.AssignLiteral("bold");
|
||||
} else {
|
||||
PRInt32 weight = 0;
|
||||
PRInt32 errorCode;
|
||||
nsAutoString value(valueString);
|
||||
weight = value.ToInteger(&errorCode, 10);
|
||||
if (400 < weight) {
|
||||
aIsSet = true;
|
||||
valueString.Assign(boldStr);
|
||||
}
|
||||
else {
|
||||
valueString.AssignLiteral("bold");
|
||||
} else {
|
||||
aIsSet = false;
|
||||
valueString.AssignLiteral("normal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nsEditProperty::i == aHTMLProperty) {
|
||||
} else if (nsEditProperty::i == aHTMLProperty) {
|
||||
if (valueString.EqualsLiteral("italic") ||
|
||||
valueString.EqualsLiteral("oblique")) {
|
||||
aIsSet= true;
|
||||
aIsSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (nsEditProperty::u == aHTMLProperty) {
|
||||
} else if (nsEditProperty::u == aHTMLProperty) {
|
||||
nsAutoString val;
|
||||
val.AssignLiteral("underline");
|
||||
aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
|
||||
}
|
||||
|
||||
else if (nsEditProperty::strike == aHTMLProperty) {
|
||||
} else if (nsEditProperty::strike == aHTMLProperty) {
|
||||
nsAutoString val;
|
||||
val.AssignLiteral("line-through");
|
||||
aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
|
||||
}
|
||||
|
||||
else if (aHTMLAttribute &&
|
||||
( (nsEditProperty::font == aHTMLProperty &&
|
||||
aHTMLAttribute->EqualsLiteral("color")) ||
|
||||
aHTMLAttribute->EqualsLiteral("bgcolor"))) {
|
||||
if (htmlValueString.IsEmpty())
|
||||
} else if (aHTMLAttribute &&
|
||||
((nsEditProperty::font == aHTMLProperty &&
|
||||
aHTMLAttribute->EqualsLiteral("color")) ||
|
||||
aHTMLAttribute->EqualsLiteral("bgcolor"))) {
|
||||
if (htmlValueString.IsEmpty()) {
|
||||
aIsSet = true;
|
||||
else {
|
||||
} else {
|
||||
nscolor rgba;
|
||||
nsAutoString subStr;
|
||||
htmlValueString.Right(subStr, htmlValueString.Length()-1);
|
||||
htmlValueString.Right(subStr, htmlValueString.Length() - 1);
|
||||
if (NS_ColorNameToRGB(htmlValueString, &rgba) ||
|
||||
NS_HexToRGB(subStr, &rgba)) {
|
||||
nsAutoString htmlColor, tmpStr;
|
||||
@ -1154,19 +1191,15 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
htmlColor.Append(PRUnichar(')'));
|
||||
aIsSet = htmlColor.Equals(valueString,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
else
|
||||
} else {
|
||||
aIsSet = htmlValueString.Equals(valueString,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nsEditProperty::tt == aHTMLProperty) {
|
||||
} else if (nsEditProperty::tt == aHTMLProperty) {
|
||||
aIsSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace"));
|
||||
}
|
||||
|
||||
else if ((nsEditProperty::font == aHTMLProperty) && aHTMLAttribute
|
||||
&& aHTMLAttribute->EqualsLiteral("face")) {
|
||||
} else if (nsEditProperty::font == aHTMLProperty && aHTMLAttribute &&
|
||||
aHTMLAttribute->EqualsLiteral("face")) {
|
||||
if (!htmlValueString.IsEmpty()) {
|
||||
const PRUnichar commaSpace[] = { PRUnichar(','), PRUnichar(' '), 0 };
|
||||
const PRUnichar comma[] = { PRUnichar(','), 0 };
|
||||
@ -1175,8 +1208,7 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
valueStringNorm.ReplaceSubstring(commaSpace, comma);
|
||||
aIsSet = htmlValueString.Equals(valueStringNorm,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// ignore this, it's TT or our default
|
||||
nsAutoString valueStringLower;
|
||||
ToLowerCase(valueString, valueStringLower);
|
||||
@ -1184,21 +1216,30 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
!valueStringLower.EqualsLiteral("serif");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
else if (aHTMLAttribute
|
||||
&& aHTMLAttribute->EqualsLiteral("align")) {
|
||||
} else if (nsEditProperty::font == aHTMLProperty && aHTMLAttribute &&
|
||||
aHTMLAttribute->EqualsLiteral("size")) {
|
||||
if (htmlValueString.IsEmpty()) {
|
||||
aIsSet = true;
|
||||
} else {
|
||||
PRInt32 size = nsContentUtils::ParseLegacyFontSize(htmlValueString);
|
||||
aIsSet = (size == 1 && valueString.EqualsLiteral("x-small")) ||
|
||||
(size == 2 && valueString.EqualsLiteral("small")) ||
|
||||
(size == 3 && valueString.EqualsLiteral("medium")) ||
|
||||
(size == 4 && valueString.EqualsLiteral("large")) ||
|
||||
(size == 5 && valueString.EqualsLiteral("x-large")) ||
|
||||
(size == 6 && valueString.EqualsLiteral("xx-large"));
|
||||
}
|
||||
} else if (aHTMLAttribute && aHTMLAttribute->EqualsLiteral("align")) {
|
||||
aIsSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
aIsSet = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!htmlValueString.IsEmpty()) {
|
||||
if (htmlValueString.Equals(valueString,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
aIsSet = true;
|
||||
}
|
||||
if (!htmlValueString.IsEmpty() &&
|
||||
htmlValueString.Equals(valueString,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
aIsSet = true;
|
||||
}
|
||||
|
||||
if (nsEditProperty::u == aHTMLProperty || nsEditProperty::strike == aHTMLProperty) {
|
||||
|
@ -106,10 +106,20 @@ public:
|
||||
* @return a boolean saying if the tag/attribute has a css equiv
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aProperty [IN] an atom containing a HTML tag name
|
||||
* @param aAttribute [IN] a string containing the name of a HTML attribute carried by the element above
|
||||
* @param aAttribute [IN] a string containing the name of a HTML
|
||||
* attribute carried by the element above
|
||||
* @param aValue [IN] an optional string containing the attribute's
|
||||
* HTML value -- this matters for <font size>,
|
||||
* since size=7 has no CSS equivalent. Make sure
|
||||
* you pass the HTML value (e.g. "4"), not the
|
||||
* CSS value (e.g. "large").
|
||||
*/
|
||||
bool IsCSSEditableProperty(nsIContent* aNode, nsIAtom* aProperty, const nsAString* aAttribute);
|
||||
bool IsCSSEditableProperty(nsIDOMNode* aNode, nsIAtom* aProperty, const nsAString* aAttribute);
|
||||
bool IsCSSEditableProperty(nsIContent* aNode, nsIAtom* aProperty,
|
||||
const nsAString* aAttribute,
|
||||
const nsAString* aValue = nsnull);
|
||||
bool IsCSSEditableProperty(nsIDOMNode* aNode, nsIAtom* aProperty,
|
||||
const nsAString* aAttribute,
|
||||
const nsAString* aValue = nsnull);
|
||||
|
||||
/** adds/remove a CSS declaration to the STYLE atrribute carried by a given element
|
||||
*
|
||||
|
@ -709,7 +709,7 @@ protected:
|
||||
nsresult RemoveStyleInside(nsIDOMNode *aNode,
|
||||
nsIAtom *aProperty,
|
||||
const nsAString *aAttribute,
|
||||
bool aChildrenOnly = false);
|
||||
const bool aChildrenOnly = false);
|
||||
nsresult RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAString *aAttribute);
|
||||
|
||||
bool NodeIsProperty(nsIDOMNode *aNode);
|
||||
@ -972,6 +972,13 @@ friend class nsTextEditRules;
|
||||
friend class nsWSRunObject;
|
||||
friend class nsHTMLEditorEventListener;
|
||||
|
||||
private:
|
||||
// Helper
|
||||
nsresult SetInlinePropertyOnNodeImpl(nsIDOMNode *aNode,
|
||||
nsIAtom *aProperty,
|
||||
const nsAString *aAttribute,
|
||||
const nsAString *aValue);
|
||||
|
||||
};
|
||||
#endif //nsHTMLEditor_h__
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,7 @@ _TEST_FILES = \
|
||||
test_bug456244.html \
|
||||
test_bug460740.html \
|
||||
test_bug478725.html \
|
||||
test_bug480647.html \
|
||||
test_bug480972.html \
|
||||
test_bug484181.html \
|
||||
test_bug487524.html \
|
||||
|
@ -19,7 +19,6 @@ var knownFailures = {
|
||||
},
|
||||
'a' : {
|
||||
'createbookmark-0' : true,
|
||||
'fontsize-1' : true,
|
||||
'subscript-1' : true,
|
||||
'superscript-1' : true,
|
||||
},
|
||||
@ -35,15 +34,6 @@ var knownFailures = {
|
||||
'fontsize-1' : true,
|
||||
'fontsize-2' : true,
|
||||
},
|
||||
'c': {
|
||||
'fontname-0' : true,
|
||||
'fontname-2' : true,
|
||||
'fontname-3' : true,
|
||||
'fontsize-1' : true,
|
||||
'fontsize-2' : true,
|
||||
'forecolor-0' : true,
|
||||
'forecolor-2' : true,
|
||||
},
|
||||
};
|
||||
|
||||
function isKnownFailure(type, test, param) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -132,10 +132,9 @@ http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/u
|
||||
// 'body' (test within a <body contenteditable="true">)
|
||||
|
||||
if (UPDATE_TEST_RESULTS) {
|
||||
var testResults = {};
|
||||
var newKnownFailures = {value: {}, select: {}};
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var category = tests[i];
|
||||
testResults[category.id] = {};
|
||||
for (var group in results[category.id]) {
|
||||
switch (group) {
|
||||
// Skip the known properties
|
||||
@ -145,7 +144,6 @@ http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/u
|
||||
case "time":
|
||||
break;
|
||||
default:
|
||||
testResults[category.id][group] = {};
|
||||
for (var test_id in results[category.id][group]) {
|
||||
switch (test_id) {
|
||||
// Skip the known properties
|
||||
@ -154,15 +152,18 @@ http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/u
|
||||
case "selscore":
|
||||
break;
|
||||
default:
|
||||
testResults[category.id][group][test_id] = {};
|
||||
for (var structure in results[category.id][group][test_id]) {
|
||||
switch (structure) {
|
||||
// Only look at each test structure
|
||||
case "dM":
|
||||
case "body":
|
||||
case "div":
|
||||
var row = results[category.id][group][test_id][structure];
|
||||
testResults[category.id][group][test_id][structure] = row;
|
||||
if (!results[category.id][group][test_id][structure].valscore) {
|
||||
newKnownFailures.value[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
|
||||
}
|
||||
if (!results[category.id][group][test_id][structure].selscore) {
|
||||
newKnownFailures.select[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,7 +173,7 @@ http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/u
|
||||
}
|
||||
var resultContainer = document.getElementById("results");
|
||||
resultContainer.style.display = "";
|
||||
resultContainer.textContent = JSON.stringify(testResults);
|
||||
resultContainer.textContent = JSON.stringify(newKnownFailures);
|
||||
} else {
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var category = tests[i];
|
||||
@ -200,57 +201,11 @@ http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/u
|
||||
case "body":
|
||||
case "div":
|
||||
var row = results[category.id][group][test_id][structure];
|
||||
var expected = TEST_RESULTS[category.id][group][test_id][structure];
|
||||
var testName = "[" + [category.id, group, test_id, structure].join(", ") + "]";
|
||||
// There are three possible cases here:
|
||||
// a) If row.valscore == 1 and expected.valscore == 1, then the test has passed successfully.
|
||||
// b) If row.valscore == 1 and expected.valscore == 0, a previously failing test has started to pass.
|
||||
// In this case, the respective currentStatus.js entry should be modified.
|
||||
// c) If row.valscore == 0 && expected.valscore == 0, then the test is known to fail.
|
||||
// d) If row.valscore == 0 && expected.valscore == 1, then we've found a regression, which should be fixed.
|
||||
// The same logic goes for selscore too.
|
||||
if (row.valscore == 1 && expected.valscore == 1) {
|
||||
// successful
|
||||
is(row.valscore, expected.valscore, testName + " passed successfully");
|
||||
} else if (row.valscore == 1 && expected.valscore == 0) {
|
||||
// unexpected pass
|
||||
todo_is(row.valscore, 1, testName + " used to fail, but it just started passing");
|
||||
// debugging information
|
||||
info("HTML test result comparison - got " +
|
||||
row.output + ", expected " + expected.output);
|
||||
} else if (row.valscore == 0 && expected.valscore == 0) {
|
||||
// known failure
|
||||
todo_is(row.valscore, 1, testName + " is known to fail");
|
||||
} else if (row.valscore == 0 && expected.valscore == 1) {
|
||||
// regression
|
||||
is(row.valscore, expected.valscore, testName + " has regressed");
|
||||
// debugging information
|
||||
is(row.output, expected.output, "HTML test result comparison");
|
||||
} else {
|
||||
// sanity check: this shouldn't happen!
|
||||
ok(false, "Unexpected result: row = " + row.toSource() + ", expected: " + expected.toSource());
|
||||
}
|
||||
if (row.selscore == 1 && expected.selscore == 1) {
|
||||
// successful
|
||||
is(row.selscore, expected.selscore, testName + " passed successfully");
|
||||
} else if (row.selscore == 1 && expected.selscore == 0) {
|
||||
// unexpected pass
|
||||
todo_is(row.selscore, 1, testName + " used to fail, but it just started passing");
|
||||
// debugging information
|
||||
info("HTML test result comparison - got " +
|
||||
row.output + ", expected " + expected.output);
|
||||
} else if (row.selscore == 0 && expected.selscore == 0) {
|
||||
// known failure
|
||||
todo_is(row.selscore, 1, testName + " is known to fail");
|
||||
} else if (row.selscore == 0 && expected.selscore == 1) {
|
||||
// regression
|
||||
is(row.selscore, expected.selscore, testName + " has regressed");
|
||||
// debugging information
|
||||
is(row.output, expected.output, "HTML test result comparison");
|
||||
} else {
|
||||
// sanity check: this shouldn't happen!
|
||||
ok(false, "Unexpected result: row = " + row.toSource() + ", expected: " + expected.toSource());
|
||||
}
|
||||
var testName = [category.id, group, test_id, structure].join("-");
|
||||
(testName in knownFailures.value ? todo_is : is)(
|
||||
row.valscore, 1, "Browserscope richtext2 value: " + testName);
|
||||
(testName in knownFailures.select ? todo_is : is)(
|
||||
row.selscore, 1, "Browserscope richtext2 selection: " + testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
141
editor/libeditor/html/tests/test_bug480647.html
Normal file
141
editor/libeditor/html/tests/test_bug480647.html
Normal file
@ -0,0 +1,141 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=480647
|
||||
-->
|
||||
<title>Test for Bug 480647</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=480647">Mozilla Bug 480647</a>
|
||||
<div contenteditable></div>
|
||||
<script>
|
||||
/** Test for Bug 480647 **/
|
||||
|
||||
var div = document.querySelector("div");
|
||||
|
||||
function parseFontSize(input, expected) {
|
||||
parseFontSizeInner(input, expected, is);
|
||||
}
|
||||
|
||||
function parseFontSizeTodo(input, expected) {
|
||||
parseFontSizeInner(input, expected, todo_is);
|
||||
}
|
||||
|
||||
function parseFontSizeInner(input, expected, fn) {
|
||||
// First test non-CSS
|
||||
document.execCommand("styleWithCSS", false, false);
|
||||
div.innerHTML = "foo";
|
||||
getSelection().selectAllChildren(div);
|
||||
document.execCommand("fontSize", false, input);
|
||||
if (expected === null) {
|
||||
fn(div.innerHTML, "foo",
|
||||
'execCommand("fontSize", false, "' + input + '") should be no-op ' +
|
||||
'(non-CSS)');
|
||||
} else {
|
||||
fn(div.innerHTML, '<font size="' + expected + '">foo</font>',
|
||||
'execCommand("fontSize", false, "' + input + '") should parse to ' +
|
||||
expected + ' (non-CSS)');
|
||||
}
|
||||
|
||||
// Now test CSS
|
||||
document.execCommand("styleWithCSS", false, true);
|
||||
div.innerHTML = "foo";
|
||||
getSelection().selectAllChildren(div);
|
||||
document.execCommand("fontSize", false, input);
|
||||
if (expected === null) {
|
||||
fn(div.innerHTML, "foo",
|
||||
'execCommand("fontSize", false, "' + input + '") should be no-op ' +
|
||||
'(CSS)');
|
||||
} else if (expected === 7) {
|
||||
// No CSS support for <font size=7>
|
||||
fn(div.innerHTML, '<font size="' + expected + '">foo</font>',
|
||||
'execCommand("fontSize", false, "' + input + '") should parse to ' +
|
||||
expected + ' (CSS)');
|
||||
} else {
|
||||
var cssVal = {
|
||||
1: "x-small",
|
||||
2: "small",
|
||||
3: "medium",
|
||||
4: "large",
|
||||
5: "x-large",
|
||||
6: "xx-large",
|
||||
}[expected];
|
||||
fn(div.innerHTML, '<span style="font-size: ' + cssVal + ';">foo</span>',
|
||||
'execCommand("fontSize", false, "' + input + '") should parse to ' +
|
||||
expected + ' (CSS)');
|
||||
}
|
||||
}
|
||||
|
||||
// Parse errors
|
||||
parseFontSize("", null);
|
||||
parseFontSize("abc", null);
|
||||
parseFontSize("larger", null);
|
||||
parseFontSize("smaller", null);
|
||||
parseFontSize("xx-small", null);
|
||||
parseFontSize("x-small", null);
|
||||
parseFontSize("small", null);
|
||||
parseFontSize("medium", null);
|
||||
parseFontSize("large", null);
|
||||
parseFontSize("x-large", null);
|
||||
parseFontSize("xx-large", null);
|
||||
parseFontSize("xxx-large", null);
|
||||
// Bug 747879
|
||||
parseFontSizeTodo("1.2em", null);
|
||||
parseFontSizeTodo("8px", null);
|
||||
parseFontSizeTodo("-1.2em", null);
|
||||
parseFontSizeTodo("-8px", null);
|
||||
parseFontSizeTodo("+1.2em", null);
|
||||
parseFontSizeTodo("+8px", null);
|
||||
|
||||
// Numbers
|
||||
parseFontSize("0", 1);
|
||||
parseFontSize("1", 1);
|
||||
parseFontSize("2", 2);
|
||||
parseFontSize("3", 3);
|
||||
parseFontSize("4", 4);
|
||||
parseFontSize("5", 5);
|
||||
parseFontSize("6", 6);
|
||||
parseFontSize("7", 7);
|
||||
parseFontSize("8", 7);
|
||||
parseFontSize("9", 7);
|
||||
parseFontSize("10", 7);
|
||||
parseFontSize("1000000000000000000000", 7);
|
||||
parseFontSize("2.72", 2);
|
||||
parseFontSize("2.72e9", 2);
|
||||
|
||||
// Minus sign
|
||||
parseFontSize("-0", 3);
|
||||
parseFontSize("-1", 2);
|
||||
parseFontSize("-2", 1);
|
||||
parseFontSize("-3", 1);
|
||||
parseFontSize("-4", 1);
|
||||
parseFontSize("-5", 1);
|
||||
parseFontSize("-6", 1);
|
||||
parseFontSize("-7", 1);
|
||||
parseFontSize("-8", 1);
|
||||
parseFontSize("-9", 1);
|
||||
parseFontSize("-10", 1);
|
||||
parseFontSize("-1000000000000000000000", 1);
|
||||
parseFontSize("-1.72", 2);
|
||||
parseFontSize("-1.72e9", 2);
|
||||
|
||||
// Plus sign
|
||||
parseFontSize("+0", 3);
|
||||
parseFontSize("+1", 4);
|
||||
parseFontSize("+2", 5);
|
||||
parseFontSize("+3", 6);
|
||||
parseFontSize("+4", 7);
|
||||
parseFontSize("+5", 7);
|
||||
parseFontSize("+6", 7);
|
||||
parseFontSize("+7", 7);
|
||||
parseFontSize("+8", 7);
|
||||
parseFontSize("+9", 7);
|
||||
parseFontSize("+10", 7);
|
||||
parseFontSize("+1000000000000000000000", 7);
|
||||
parseFontSize("+1.72", 4);
|
||||
parseFontSize("+1.72e9", 4);
|
||||
|
||||
// Whitespace
|
||||
parseFontSize(" \t\n\r\f5 \t\n\r\f", 5);
|
||||
parseFontSize("\u00a05", null);
|
||||
parseFontSize("\b5", null);
|
||||
</script>
|
@ -78,6 +78,10 @@ struct NS_GFX nsFont {
|
||||
// The variant of the font (normal, small-caps)
|
||||
PRUint8 variant;
|
||||
|
||||
// The decorations on the font (underline, overline,
|
||||
// line-through). The decorations can be binary or'd together.
|
||||
PRUint8 decorations;
|
||||
|
||||
// The weight of the font; see gfxFontConstants.h.
|
||||
PRUint16 weight;
|
||||
|
||||
@ -85,10 +89,6 @@ struct NS_GFX nsFont {
|
||||
// constants; see gfxFontConstants.h).
|
||||
PRInt16 stretch;
|
||||
|
||||
// The decorations on the font (underline, overline,
|
||||
// line-through). The decorations can be binary or'd together.
|
||||
PRUint8 decorations;
|
||||
|
||||
// The logical size of the font, in nscoord units
|
||||
nscoord size;
|
||||
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
14.0a1
|
||||
15.0a1
|
||||
|
@ -3993,11 +3993,11 @@ JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
|
||||
|
||||
struct JSPropertyDescriptor {
|
||||
JSObject *obj;
|
||||
unsigned attrs;
|
||||
unsigned attrs;
|
||||
unsigned shortid;
|
||||
JSPropertyOp getter;
|
||||
JSStrictPropertyOp setter;
|
||||
jsval value;
|
||||
unsigned shortid;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -53,6 +53,10 @@ extern JSBool
|
||||
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
|
||||
js::StringBuffer &sb);
|
||||
|
||||
// Avoid build errors on certain platforms that define these names as constants
|
||||
#undef STRICT
|
||||
#undef LEGACY
|
||||
|
||||
/*
|
||||
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
|
||||
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the
|
||||
|
@ -1915,7 +1915,7 @@ AccumulateTelemetryCallback(int id, uint32_t sample)
|
||||
}
|
||||
|
||||
bool XPCJSRuntime::gNewDOMBindingsEnabled;
|
||||
bool XPCJSRuntime::gParisBindingsEnabled;
|
||||
bool XPCJSRuntime::gExperimentalBindingsEnabled;
|
||||
|
||||
bool PreserveWrapper(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
@ -1968,7 +1968,8 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
DOM_InitInterfaces();
|
||||
Preferences::AddBoolVarCache(&gNewDOMBindingsEnabled, "dom.new_bindings",
|
||||
false);
|
||||
Preferences::AddBoolVarCache(&gParisBindingsEnabled, "dom.paris_bindings",
|
||||
Preferences::AddBoolVarCache(&gExperimentalBindingsEnabled,
|
||||
"dom.experimental_bindings",
|
||||
false);
|
||||
|
||||
|
||||
|
@ -150,7 +150,7 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx,
|
||||
mPrototypeNoHelper(nsnull),
|
||||
mScriptObjectPrincipal(nsnull),
|
||||
mNewDOMBindingsEnabled(ccx.GetRuntime()->NewDOMBindingsEnabled()),
|
||||
mParisBindingsEnabled(ccx.GetRuntime()->ParisBindingsEnabled())
|
||||
mExperimentalBindingsEnabled(ccx.GetRuntime()->ExperimentalBindingsEnabled())
|
||||
{
|
||||
// add ourselves to the scopes list
|
||||
{ // scoped lock
|
||||
|
@ -795,9 +795,9 @@ public:
|
||||
return gNewDOMBindingsEnabled;
|
||||
}
|
||||
|
||||
bool ParisBindingsEnabled()
|
||||
bool ExperimentalBindingsEnabled()
|
||||
{
|
||||
return gParisBindingsEnabled;
|
||||
return gExperimentalBindingsEnabled;
|
||||
}
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
|
||||
@ -812,7 +812,7 @@ private:
|
||||
static void WatchdogMain(void *arg);
|
||||
|
||||
static bool gNewDOMBindingsEnabled;
|
||||
static bool gParisBindingsEnabled;
|
||||
static bool gExperimentalBindingsEnabled;
|
||||
|
||||
static const char* mStrings[IDX_TOTAL_COUNT];
|
||||
jsid mStrIDs[IDX_TOTAL_COUNT];
|
||||
@ -1638,9 +1638,9 @@ public:
|
||||
return mNewDOMBindingsEnabled;
|
||||
}
|
||||
|
||||
JSBool ParisBindingsEnabled()
|
||||
JSBool ExperimentalBindingsEnabled()
|
||||
{
|
||||
return mParisBindingsEnabled;
|
||||
return mExperimentalBindingsEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -1684,7 +1684,7 @@ private:
|
||||
nsDataHashtable<nsDepCharHashKey, JSObject*> mCachedDOMPrototypes;
|
||||
|
||||
JSBool mNewDOMBindingsEnabled;
|
||||
JSBool mParisBindingsEnabled;
|
||||
JSBool mExperimentalBindingsEnabled;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1229,9 +1229,8 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
|
||||
static void
|
||||
LayoutModuleDtor()
|
||||
{
|
||||
xpcModuleDtor();
|
||||
|
||||
nsScriptSecurityManager::Shutdown();
|
||||
xpcModuleDtor();
|
||||
}
|
||||
|
||||
static const mozilla::Module kLayoutModule = {
|
||||
|
@ -4,8 +4,8 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
var text = '<html><head></head><body style="font-size:16px;">'
|
||||
+ '<p style="background-color:red;">This paragraph should be red</p>'
|
||||
+ '<p style="background-color:blue;">This paragraph should be blue</p>'
|
||||
+ '<p><span style="background-color:red;">This paragraph should be red</span></p>'
|
||||
+ '<p><span style="background-color:blue;">This paragraph should be blue</span></p>'
|
||||
+ '<p>This paragraph should not be colored</p>'
|
||||
+ '</body></html>';
|
||||
|
||||
|
@ -136,12 +136,12 @@ static const nsStyleSet::sheetType gCSSSheetTypes[] = {
|
||||
|
||||
nsStyleSet::nsStyleSet()
|
||||
: mRuleTree(nsnull),
|
||||
mUnusedRuleNodeCount(0),
|
||||
mBatching(0),
|
||||
mInShutdown(false),
|
||||
mAuthorStyleDisabled(false),
|
||||
mInReconstruct(false),
|
||||
mDirty(0)
|
||||
mDirty(0),
|
||||
mUnusedRuleNodeCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -405,6 +405,13 @@ class nsStyleSet
|
||||
// lexicographic tree of matched rules that style
|
||||
// contexts use to look up properties.
|
||||
|
||||
PRUint16 mBatching;
|
||||
|
||||
unsigned mInShutdown : 1;
|
||||
unsigned mAuthorStyleDisabled: 1;
|
||||
unsigned mInReconstruct : 1;
|
||||
unsigned mDirty : 8; // one dirty bit is used per sheet type
|
||||
|
||||
PRUint32 mUnusedRuleNodeCount; // used to batch rule node GC
|
||||
nsTArray<nsStyleContext*> mRoots; // style contexts with no parent
|
||||
|
||||
@ -416,18 +423,10 @@ class nsStyleSet
|
||||
// determining when context-sensitive values are in use.
|
||||
nsRefPtr<nsInitialStyleRule> mInitialStyleRule;
|
||||
|
||||
PRUint16 mBatching;
|
||||
|
||||
// Old rule trees, which should only be non-empty between
|
||||
// BeginReconstruct and EndReconstruct, but in case of bugs that cause
|
||||
// style contexts to exist too long, may last longer.
|
||||
nsTArray<nsRuleNode*> mOldRuleTrees;
|
||||
|
||||
unsigned mInShutdown : 1;
|
||||
unsigned mAuthorStyleDisabled: 1;
|
||||
unsigned mInReconstruct : 1;
|
||||
unsigned mDirty : 8; // one dirty bit is used per sheet type
|
||||
|
||||
};
|
||||
|
||||
#ifdef _IMPL_NS_LAYOUT
|
||||
|
@ -457,9 +457,9 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
|
||||
mBorderImageSource(aSrc.mBorderImageSource),
|
||||
mBorderRadius(aSrc.mBorderRadius),
|
||||
mBorderImageSlice(aSrc.mBorderImageSlice),
|
||||
mBorderImageFill(aSrc.mBorderImageFill),
|
||||
mBorderImageWidth(aSrc.mBorderImageWidth),
|
||||
mBorderImageOutset(aSrc.mBorderImageOutset),
|
||||
mBorderImageFill(aSrc.mBorderImageFill),
|
||||
mBorderImageRepeatH(aSrc.mBorderImageRepeatH),
|
||||
mBorderImageRepeatV(aSrc.mBorderImageRepeatV),
|
||||
mFloatEdge(aSrc.mFloatEdge),
|
||||
@ -2846,10 +2846,10 @@ nsStyleText::nsStyleText(const nsStyleText& aSource)
|
||||
mHyphens(aSource.mHyphens),
|
||||
mTextSizeAdjust(aSource.mTextSizeAdjust),
|
||||
mTabSize(aSource.mTabSize),
|
||||
mWordSpacing(aSource.mWordSpacing),
|
||||
mLetterSpacing(aSource.mLetterSpacing),
|
||||
mLineHeight(aSource.mLineHeight),
|
||||
mTextIndent(aSource.mTextIndent),
|
||||
mWordSpacing(aSource.mWordSpacing),
|
||||
mTextShadow(aSource.mTextShadow)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsStyleText);
|
||||
|
@ -939,14 +939,13 @@ protected:
|
||||
public:
|
||||
nsStyleCorners mBorderRadius; // [reset] coord, percent
|
||||
nsStyleSides mBorderImageSlice; // [reset] factor, percent
|
||||
PRUint8 mBorderImageFill; // [reset]
|
||||
nsStyleSides mBorderImageWidth; // [reset] length, factor, percent, auto
|
||||
nsStyleSides mBorderImageOutset; // [reset] length, factor
|
||||
|
||||
PRUint8 mBorderImageFill; // [reset]
|
||||
PRUint8 mBorderImageRepeatH; // [reset] see nsStyleConsts.h
|
||||
PRUint8 mBorderImageRepeatV; // [reset]
|
||||
PRUint8 mFloatEdge; // [reset]
|
||||
// 8 bits free here
|
||||
|
||||
protected:
|
||||
// mComputedBorder holds the CSS2.1 computed border-width values.
|
||||
@ -1325,10 +1324,10 @@ struct nsStyleText {
|
||||
PRUint8 mTextSizeAdjust; // [inherited] see nsStyleConsts.h
|
||||
PRInt32 mTabSize; // [inherited] see nsStyleConsts.h
|
||||
|
||||
nscoord mWordSpacing; // [inherited]
|
||||
nsStyleCoord mLetterSpacing; // [inherited] coord, normal
|
||||
nsStyleCoord mLineHeight; // [inherited] coord, factor, normal
|
||||
nsStyleCoord mTextIndent; // [inherited] coord, percent, calc
|
||||
nscoord mWordSpacing; // [inherited]
|
||||
|
||||
nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] NULL in case of a zero-length
|
||||
|
||||
@ -1601,12 +1600,12 @@ struct nsStyleDisplay {
|
||||
// specified, or null to indicate there is no transform. (inherit or
|
||||
// initial are replaced by an actual list of transform functions, or
|
||||
// null, as appropriate.) (owned by the style rule)
|
||||
PRUint8 mBackfaceVisibility;
|
||||
PRUint8 mTransformStyle;
|
||||
const nsCSSValueList *mSpecifiedTransform; // [reset]
|
||||
nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
|
||||
nsStyleCoord mChildPerspective; // [reset] coord
|
||||
nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
|
||||
PRUint8 mBackfaceVisibility;
|
||||
PRUint8 mTransformStyle;
|
||||
|
||||
nsAutoTArray<nsTransition, 1> mTransitions; // [reset]
|
||||
// The number of elements in mTransitions that are not from repeating
|
||||
|
2
mobile/android/confvars.sh
Normal file → Executable file
2
mobile/android/confvars.sh
Normal file → Executable file
@ -38,7 +38,7 @@
|
||||
MOZ_APP_BASENAME=Fennec
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=14.0a1
|
||||
MOZ_APP_VERSION=15.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
|
||||
|
@ -55,7 +55,7 @@
|
||||
<Description>
|
||||
<em:id>{a23983c0-fd0e-11dc-95ff-0800200c9a66}</em:id>
|
||||
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
|
||||
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
|
2
mobile/xul/confvars.sh
Normal file → Executable file
2
mobile/xul/confvars.sh
Normal file → Executable file
@ -38,7 +38,7 @@
|
||||
MOZ_APP_BASENAME=Fennec
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=14.0a1
|
||||
MOZ_APP_VERSION=15.0a1
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial
|
||||
MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official
|
||||
|
@ -55,7 +55,7 @@
|
||||
<Description>
|
||||
<em:id>{a23983c0-fd0e-11dc-95ff-0800200c9a66}</em:id>
|
||||
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
|
||||
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
|
@ -646,7 +646,7 @@ pref("dom.min_background_timeout_value", 1000);
|
||||
// Use the new DOM bindings (only affects any scopes created after the pref is
|
||||
// changed)
|
||||
pref("dom.new_bindings", true);
|
||||
pref("dom.paris_bindings", true);
|
||||
pref("dom.experimental_bindings", true);
|
||||
|
||||
// Parsing perf prefs. For now just mimic what the old code did.
|
||||
#ifndef XP_WIN
|
||||
|
@ -13,6 +13,7 @@
|
||||
[include:dom/indexedDB/test/unit/xpcshell.ini]
|
||||
[include:content/xtf/test/unit/xpcshell.ini]
|
||||
[include:docshell/test/unit/xpcshell.ini]
|
||||
[include:docshell/test/unit_ipc/xpcshell.ini]
|
||||
[include:embedding/tests/unit/xpcshell.ini]
|
||||
[include:toolkit/components/commandlines/test/unit/xpcshell.ini]
|
||||
[include:toolkit/components/contentprefs/tests/unit/xpcshell.ini]
|
||||
|
@ -87,7 +87,7 @@ ThreadActor.prototype = {
|
||||
_scripts: {},
|
||||
|
||||
/**
|
||||
* Add a debuggee global to the JSInspector.
|
||||
* Add a debuggee global to the Debugger object.
|
||||
*/
|
||||
addDebuggee: function TA_addDebuggee(aGlobal) {
|
||||
// Use the inspector xpcom component to turn on debugging
|
||||
|
485
toolkit/devtools/debugger/server/dbg-server.js
Normal file
485
toolkit/devtools/debugger/server/dbg-server.js
Normal file
@ -0,0 +1,485 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Camp <dcamp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
"use strict";
|
||||
/**
|
||||
* Toolkit glue for the remote debugging protocol, loaded into the
|
||||
* debugging global.
|
||||
*/
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const CC = Components.Constructor;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
|
||||
function dumpn(str) {
|
||||
if (wantLogging) {
|
||||
dump("DBG-SERVER: " + str + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
function dbg_assert(cond, e) {
|
||||
if (!cond) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
loadSubScript.call(this, "chrome://global/content/devtools/dbg-transport.js");
|
||||
|
||||
// XPCOM constructors
|
||||
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
|
||||
"nsIServerSocket",
|
||||
"init");
|
||||
|
||||
/***
|
||||
* Public API
|
||||
*/
|
||||
var DebuggerServer = {
|
||||
_listener: null,
|
||||
_transportInitialized: false,
|
||||
xpcInspector: null,
|
||||
|
||||
/**
|
||||
* Initialize the debugger server.
|
||||
*/
|
||||
init: function DH_init() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hack: Merely loading jsdebugger.jsm will not work, because it will load
|
||||
// in the chrome compartment, and then we'd get a cross-compartment wrapper
|
||||
// of that. The Debugger object must be created in the sandbox compartment,
|
||||
// that is, this file's compartment.
|
||||
const init = Cc["@mozilla.org/jsdebugger;1"].createInstance(Ci.IJSDebugger);
|
||||
init.addClass(); // adds global variable Debugger to this global.
|
||||
|
||||
this.xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
this.initTransport();
|
||||
this.addActors("chrome://global/content/devtools/dbg-script-actors.js");
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the debugger server's transport variables. This can be
|
||||
* in place of init() for cases where the jsdebugger isn't needed.
|
||||
*/
|
||||
initTransport: function DH_initTransport() {
|
||||
if (this._transportInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._connections = {};
|
||||
this._nextConnID = 0;
|
||||
this._transportInitialized = true;
|
||||
},
|
||||
|
||||
get initialized() { return !!this.xpcInspector; },
|
||||
|
||||
/**
|
||||
* Load a subscript into the debugging global.
|
||||
*
|
||||
* @param aURL string A url that will be loaded as a subscript into the
|
||||
* debugging global. The user must load at least one script
|
||||
* that implements a createRootActor() function to create the
|
||||
* server's root actor.
|
||||
*/
|
||||
addActors: function DH_addActors(aURL) {
|
||||
loadSubScript.call(this, aURL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Install Firefox-specific actors.
|
||||
*/
|
||||
addBrowserActors: function DH_addBrowserActors() {
|
||||
this.addActors("chrome://global/content/devtools/dbg-browser-actors.js");
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens on the given port for remote debugger connections.
|
||||
*
|
||||
* @param aPort int
|
||||
* The port to listen on.
|
||||
* @param aLocalOnly bool
|
||||
* If true, server will listen on the loopback device.
|
||||
*/
|
||||
openListener: function DH_openListener(aPort, aLocalOnly) {
|
||||
this._checkInit();
|
||||
|
||||
if (this._listener) {
|
||||
throw "Debugging listener already open.";
|
||||
}
|
||||
|
||||
try {
|
||||
let socket = new ServerSocket(aPort, aLocalOnly, 4);
|
||||
socket.asyncListen(this);
|
||||
this._listener = socket;
|
||||
} catch (e) {
|
||||
dumpn("Could not start debugging listener on port " + aPort + ": " + e);
|
||||
throw Cr.NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close a previously-opened TCP listener.
|
||||
*/
|
||||
closeListener: function DH_closeListener() {
|
||||
this._checkInit();
|
||||
|
||||
if (!this._listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new connection to the local debugger speaking over an
|
||||
* nsIPipe.
|
||||
*
|
||||
* @returns a client-side DebuggerTransport for communicating with
|
||||
* the newly-created connection.
|
||||
*/
|
||||
connectPipe: function DH_connectPipe() {
|
||||
this._checkInit();
|
||||
|
||||
let toServer = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
toServer.init(true, true, 0, 0, null);
|
||||
let toClient = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
toClient.init(true, true, 0, 0, null);
|
||||
|
||||
let serverTransport = new DebuggerTransport(toServer.inputStream,
|
||||
toClient.outputStream);
|
||||
this._onConnection(serverTransport);
|
||||
|
||||
return new DebuggerTransport(toClient.inputStream, toServer.outputStream);
|
||||
},
|
||||
|
||||
|
||||
// nsIServerSocketListener implementation
|
||||
|
||||
onSocketAccepted: function DH_onSocketAccepted(aSocket, aTransport) {
|
||||
dumpn("New debugging connection on " + aTransport.host + ":" + aTransport.port);
|
||||
|
||||
try {
|
||||
let input = aTransport.openInputStream(0, 0, 0);
|
||||
let output = aTransport.openOutputStream(0, 0, 0);
|
||||
let transport = new DebuggerTransport(input, output);
|
||||
DebuggerServer._onConnection(transport);
|
||||
} catch (e) {
|
||||
dumpn("Couldn't initialize connection: " + e + " - " + e.stack);
|
||||
}
|
||||
},
|
||||
|
||||
onStopListening: function DH_onStopListening() { },
|
||||
|
||||
/**
|
||||
* Raises an exception if the server has not been properly initialized.
|
||||
*/
|
||||
_checkInit: function DH_checkInit() {
|
||||
if (!this._transportInitialized) {
|
||||
throw "DebuggerServer has not been initialized.";
|
||||
}
|
||||
|
||||
if (!this.createRootActor) {
|
||||
throw "Use DebuggerServer.addActors() to add a root actor implementation.";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new debugger connection for the given transport. Called
|
||||
* after connectPipe() or after an incoming socket connection.
|
||||
*/
|
||||
_onConnection: function DH_onConnection(aTransport) {
|
||||
let connID = "conn" + this._nextConnID++ + '.';
|
||||
let conn = new DebuggerServerConnection(connID, aTransport);
|
||||
this._connections[connID] = conn;
|
||||
|
||||
// Create a root actor for the connection and send the hello packet.
|
||||
conn.rootActor = this.createRootActor(conn);
|
||||
conn.addActor(conn.rootActor);
|
||||
aTransport.send(conn.rootActor.sayHello());
|
||||
aTransport.ready();
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the connection from the debugging server.
|
||||
*/
|
||||
_connectionClosed: function DH_connectionClosed(aConnection) {
|
||||
delete this._connections[aConnection.prefix];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct an ActorPool.
|
||||
*
|
||||
* ActorPools are actorID -> actor mapping and storage. These are
|
||||
* used to accumulate and quickly dispose of groups of actors that
|
||||
* share a lifetime.
|
||||
*/
|
||||
function ActorPool(aConnection)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
this._cleanups = {};
|
||||
this._actors = {};
|
||||
}
|
||||
|
||||
ActorPool.prototype = {
|
||||
/**
|
||||
* Add an actor to the actor pool. If the actor doesn't have an ID,
|
||||
* allocate one from the connection.
|
||||
*
|
||||
* @param aActor object
|
||||
* The actor implementation. If the object has a
|
||||
* 'disconnected' property, it will be called when the actor
|
||||
* pool is cleaned up.
|
||||
*/
|
||||
addActor: function AP_addActor(aActor) {
|
||||
aActor.conn = this.conn;
|
||||
if (!aActor.actorID) {
|
||||
aActor.actorID = this.conn.allocID(aActor.actorPrefix || undefined);
|
||||
}
|
||||
|
||||
if (aActor.registeredPool) {
|
||||
aActor.registeredPool.removeActor(aActor);
|
||||
}
|
||||
aActor.registeredPool = this;
|
||||
|
||||
this._actors[aActor.actorID] = aActor;
|
||||
if (aActor.disconnect) {
|
||||
this._cleanups[aActor.actorID] = aActor;
|
||||
}
|
||||
},
|
||||
|
||||
get: function AP_get(aActorID) {
|
||||
return this._actors[aActorID];
|
||||
},
|
||||
|
||||
has: function AP_has(aActorID) {
|
||||
return aActorID in this._actors;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an actor from the actor pool.
|
||||
*/
|
||||
removeActor: function AP_remove(aActorID) {
|
||||
delete this._actors[aActorID];
|
||||
delete this._cleanups[aActorID];
|
||||
},
|
||||
|
||||
/**
|
||||
* Run all cleanups previously registered with addCleanup.
|
||||
*/
|
||||
cleanup: function AP_cleanup() {
|
||||
for each (let actor in this._cleanups) {
|
||||
actor.disconnect();
|
||||
}
|
||||
this._cleanups = {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DebuggerServerConnection.
|
||||
*
|
||||
* Represents a connection to this debugging global from a client.
|
||||
* Manages a set of actors and actor pools, allocates actor ids, and
|
||||
* handles incoming requests.
|
||||
*
|
||||
* @param aPrefix string
|
||||
* All actor IDs created by this connection should be prefixed
|
||||
* with aPrefix.
|
||||
* @param aTransport transport
|
||||
* Packet transport for the debugging protocol.
|
||||
*/
|
||||
function DebuggerServerConnection(aPrefix, aTransport)
|
||||
{
|
||||
this._prefix = aPrefix;
|
||||
this._transport = aTransport;
|
||||
this._transport.hooks = this;
|
||||
this._nextID = 1;
|
||||
|
||||
this._actorPool = new ActorPool(this);
|
||||
this._extraPools = [];
|
||||
}
|
||||
|
||||
DebuggerServerConnection.prototype = {
|
||||
_prefix: null,
|
||||
get prefix() { return this._prefix },
|
||||
|
||||
_transport: null,
|
||||
get transport() { return this._transport },
|
||||
|
||||
send: function DSC_send(aPacket) {
|
||||
this.transport.send(aPacket);
|
||||
},
|
||||
|
||||
allocID: function DSC_allocID(aPrefix) {
|
||||
return this.prefix + (aPrefix || '') + this._nextID++;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a map of actor IDs to the connection.
|
||||
*/
|
||||
addActorPool: function DSC_addActorPool(aActorPool) {
|
||||
this._extraPools.push(aActorPool);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a previously-added pool of actors to the connection.
|
||||
*/
|
||||
removeActorPool: function DSC_removeActorPool(aActorPool) {
|
||||
let index = this._extraPools.splice(this._extraPools.lastIndexOf(aActorPool), 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an actor to the default actor pool for this connection.
|
||||
*/
|
||||
addActor: function DSC_addActor(aActor) {
|
||||
this._actorPool.addActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an actor to the default actor pool for this connection.
|
||||
*/
|
||||
removeActor: function DSC_removeActor(aActor) {
|
||||
this._actorPool.removeActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a cleanup to the default actor pool for this connection.
|
||||
*/
|
||||
addCleanup: function DSC_addCleanup(aCleanup) {
|
||||
this._actorPool.addCleanup(aCleanup);
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up an actor implementation for an actorID. Will search
|
||||
* all the actor pools registered with the connection.
|
||||
*
|
||||
* @param aActorID string
|
||||
* Actor ID to look up.
|
||||
*/
|
||||
getActor: function DSC_getActor(aActorID) {
|
||||
if (this._actorPool.has(aActorID)) {
|
||||
return this._actorPool.get(aActorID);
|
||||
}
|
||||
|
||||
for each (let pool in this._extraPools) {
|
||||
if (pool.has(aActorID)) {
|
||||
return pool.get(aActorID);
|
||||
}
|
||||
}
|
||||
|
||||
if (aActorID === "root") {
|
||||
return this.rootActor;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
// Transport hooks.
|
||||
|
||||
/**
|
||||
* Called by DebuggerTransport to dispatch incoming packets as appropriate.
|
||||
*
|
||||
* @param aPacket object
|
||||
* The incoming packet.
|
||||
*/
|
||||
onPacket: function DSC_onPacket(aPacket) {
|
||||
let actor = this.getActor(aPacket.to);
|
||||
if (!actor) {
|
||||
this.transport.send({ from: aPacket.to ? aPacket.to : "root",
|
||||
error: "noSuchActor" });
|
||||
return;
|
||||
}
|
||||
|
||||
var ret = null;
|
||||
|
||||
// Dispatch the request to the actor.
|
||||
if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
|
||||
try {
|
||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
ret = { error: "unknownError",
|
||||
message: "An unknown error has occurred while processing request." };
|
||||
}
|
||||
} else {
|
||||
ret = { error: "unrecognizedPacketType",
|
||||
message: 'Actor "' + actor.actorID + '" does not recognize the packet type "' + aPacket.type + '"' };
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
// XXX: The actor wasn't ready to reply yet, don't process new
|
||||
// requests until it does.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ret.from) {
|
||||
ret.from = aPacket.to;
|
||||
}
|
||||
|
||||
this.transport.send(ret);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by DebuggerTransport when the underlying stream is closed.
|
||||
*
|
||||
* @param aStatus nsresult
|
||||
* The status code that corresponds to the reason for closing
|
||||
* the stream.
|
||||
*/
|
||||
onClosed: function DSC_onClosed(aStatus) {
|
||||
dumpn("Cleaning up connection.");
|
||||
|
||||
this._actorPool.cleanup();
|
||||
this._actorPool = null;
|
||||
this._extraPools.map(function(p) { p.cleanup(); });
|
||||
this._extraPools = null;
|
||||
|
||||
DebuggerServer._connectionClosed(this);
|
||||
}
|
||||
};
|
@ -39,456 +39,38 @@
|
||||
|
||||
"use strict";
|
||||
/**
|
||||
* Toolkit glue for the remote debugging protocol, loaded into the
|
||||
* debugging global.
|
||||
* Loads the remote debugging protocol code into a sandbox, in order to
|
||||
* shield it from the debuggee. This way, when debugging chrome globals,
|
||||
* debugger and debuggee will be in separate compartments.
|
||||
*/
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const CC = Components.Constructor;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["DebuggerServer"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
|
||||
function loadSubScript(aURL)
|
||||
{
|
||||
try {
|
||||
let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript(aURL, this);
|
||||
} catch(e) {
|
||||
dumpn("Error loading: " + aURL + ": " + e + " - " + e.stack + "\n");
|
||||
dump("Error loading: " + aURL + ": " + e + " - " + e.stack + "\n");
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function dumpn(str) {
|
||||
if (wantLogging) {
|
||||
dump("DBG-SERVER: " + str + "\n");
|
||||
}
|
||||
}
|
||||
Cu.import("resource:///modules/devtools/dbg-client.jsm");
|
||||
|
||||
function dbg_assert(cond, e) {
|
||||
if (!cond) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
// Load the debugging server in a sandbox with its own compartment.
|
||||
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
|
||||
loadSubScript.call(this, "chrome://global/content/devtools/dbg-transport.js");
|
||||
var gGlobal = Cu.Sandbox(systemPrincipal);
|
||||
gGlobal.importFunction(loadSubScript);
|
||||
gGlobal.loadSubScript("chrome://global/content/devtools/dbg-server.js");
|
||||
|
||||
// XPCOM constructors
|
||||
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
|
||||
"nsIServerSocket",
|
||||
"init");
|
||||
|
||||
/***
|
||||
* Public API
|
||||
*/
|
||||
var DebuggerServer = {
|
||||
_listener: null,
|
||||
_transportInitialized: false,
|
||||
xpcInspector: null,
|
||||
|
||||
/**
|
||||
* Initialize the debugger server.
|
||||
*/
|
||||
init: function DH_init() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
this.xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
this.initTransport();
|
||||
this.addActors("chrome://global/content/devtools/dbg-script-actors.js");
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the debugger server's transport variables. This can be
|
||||
* in place of init() for cases where the jsdebugger isn't needed.
|
||||
*/
|
||||
initTransport: function DH_initTransport() {
|
||||
if (this._transportInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._connections = {};
|
||||
this._nextConnID = 0;
|
||||
this._transportInitialized = true;
|
||||
},
|
||||
|
||||
get initialized() { return !!this.xpcInspector; },
|
||||
|
||||
/**
|
||||
* Load a subscript into the debugging global.
|
||||
*
|
||||
* @param aURL string A url that will be loaded as a subscript into the
|
||||
* debugging global. The user must load at least one script
|
||||
* that implements a createRootActor() function to create the
|
||||
* server's root actor.
|
||||
*/
|
||||
addActors: function DH_addActors(aURL) {
|
||||
loadSubScript.call(this, aURL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Install Firefox-specific actors.
|
||||
*/
|
||||
addBrowserActors: function DH_addBrowserActors() {
|
||||
this.addActors("chrome://global/content/devtools/dbg-browser-actors.js");
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens on the given port for remote debugger connections.
|
||||
*
|
||||
* @param aPort int
|
||||
* The port to listen on.
|
||||
* @param aLocalOnly bool
|
||||
* If true, server will listen on the loopback device.
|
||||
*/
|
||||
openListener: function DH_openListener(aPort, aLocalOnly) {
|
||||
this._checkInit();
|
||||
|
||||
if (this._listener) {
|
||||
throw "Debugging listener already open.";
|
||||
}
|
||||
|
||||
try {
|
||||
let socket = new ServerSocket(aPort, aLocalOnly, 4);
|
||||
socket.asyncListen(this);
|
||||
this._listener = socket;
|
||||
} catch (e) {
|
||||
dumpn("Could not start debugging listener on port " + aPort + ": " + e);
|
||||
throw Cr.NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close a previously-opened TCP listener.
|
||||
*/
|
||||
closeListener: function DH_closeListener() {
|
||||
this._checkInit();
|
||||
|
||||
if (!this._listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new connection to the local debugger speaking over an
|
||||
* nsIPipe.
|
||||
*
|
||||
* @returns a client-side DebuggerTransport for communicating with
|
||||
* the newly-created connection.
|
||||
*/
|
||||
connectPipe: function DH_connectPipe() {
|
||||
this._checkInit();
|
||||
|
||||
let toServer = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
toServer.init(true, true, 0, 0, null);
|
||||
let toClient = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
toClient.init(true, true, 0, 0, null);
|
||||
|
||||
let serverTransport = new DebuggerTransport(toServer.inputStream,
|
||||
toClient.outputStream);
|
||||
this._onConnection(serverTransport);
|
||||
|
||||
return new DebuggerTransport(toClient.inputStream, toServer.outputStream);
|
||||
},
|
||||
|
||||
|
||||
// nsIServerSocketListener implementation
|
||||
|
||||
onSocketAccepted: function DH_onSocketAccepted(aSocket, aTransport) {
|
||||
dumpn("New debugging connection on " + aTransport.host + ":" + aTransport.port);
|
||||
|
||||
try {
|
||||
let input = aTransport.openInputStream(0, 0, 0);
|
||||
let output = aTransport.openOutputStream(0, 0, 0);
|
||||
let transport = new DebuggerTransport(input, output);
|
||||
DebuggerServer._onConnection(transport);
|
||||
} catch (e) {
|
||||
dumpn("Couldn't initialize connection: " + e + " - " + e.stack);
|
||||
}
|
||||
},
|
||||
|
||||
onStopListening: function DH_onStopListening() { },
|
||||
|
||||
/**
|
||||
* Raises an exception if the server has not been properly initialized.
|
||||
*/
|
||||
_checkInit: function DH_checkInit() {
|
||||
if (!this._transportInitialized) {
|
||||
throw "DebuggerServer has not been initialized.";
|
||||
}
|
||||
|
||||
if (!this.createRootActor) {
|
||||
throw "Use DebuggerServer.addActors() to add a root actor implementation.";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new debugger connection for the given transport. Called
|
||||
* after connectPipe() or after an incoming socket connection.
|
||||
*/
|
||||
_onConnection: function DH_onConnection(aTransport) {
|
||||
let connID = "conn" + this._nextConnID++ + '.';
|
||||
let conn = new DebuggerServerConnection(connID, aTransport);
|
||||
this._connections[connID] = conn;
|
||||
|
||||
// Create a root actor for the connection and send the hello packet.
|
||||
conn.rootActor = this.createRootActor(conn);
|
||||
conn.addActor(conn.rootActor);
|
||||
aTransport.send(conn.rootActor.sayHello());
|
||||
aTransport.ready();
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the connection from the debugging server.
|
||||
*/
|
||||
_connectionClosed: function DH_connectionClosed(aConnection) {
|
||||
delete this._connections[aConnection.prefix];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct an ActorPool.
|
||||
*
|
||||
* ActorPools are actorID -> actor mapping and storage. These are
|
||||
* used to accumulate and quickly dispose of groups of actors that
|
||||
* share a lifetime.
|
||||
*/
|
||||
function ActorPool(aConnection)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
this._cleanups = {};
|
||||
this._actors = {};
|
||||
}
|
||||
|
||||
ActorPool.prototype = {
|
||||
/**
|
||||
* Add an actor to the actor pool. If the actor doesn't have an ID,
|
||||
* allocate one from the connection.
|
||||
*
|
||||
* @param aActor object
|
||||
* The actor implementation. If the object has a
|
||||
* 'disconnected' property, it will be called when the actor
|
||||
* pool is cleaned up.
|
||||
*/
|
||||
addActor: function AP_addActor(aActor) {
|
||||
aActor.conn = this.conn;
|
||||
if (!aActor.actorID) {
|
||||
aActor.actorID = this.conn.allocID(aActor.actorPrefix || undefined);
|
||||
}
|
||||
|
||||
if (aActor.registeredPool) {
|
||||
aActor.registeredPool.removeActor(aActor);
|
||||
}
|
||||
aActor.registeredPool = this;
|
||||
|
||||
this._actors[aActor.actorID] = aActor;
|
||||
if (aActor.disconnect) {
|
||||
this._cleanups[aActor.actorID] = aActor;
|
||||
}
|
||||
},
|
||||
|
||||
get: function AP_get(aActorID) {
|
||||
return this._actors[aActorID];
|
||||
},
|
||||
|
||||
has: function AP_has(aActorID) {
|
||||
return aActorID in this._actors;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an actor from the actor pool.
|
||||
*/
|
||||
removeActor: function AP_remove(aActorID) {
|
||||
delete this._actors[aActorID];
|
||||
delete this._cleanups[aActorID];
|
||||
},
|
||||
|
||||
/**
|
||||
* Run all cleanups previously registered with addCleanup.
|
||||
*/
|
||||
cleanup: function AP_cleanup() {
|
||||
for each (let actor in this._cleanups) {
|
||||
actor.disconnect();
|
||||
}
|
||||
this._cleanups = {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DebuggerServerConnection.
|
||||
*
|
||||
* Represents a connection to this debugging global from a client.
|
||||
* Manages a set of actors and actor pools, allocates actor ids, and
|
||||
* handles incoming requests.
|
||||
*
|
||||
* @param aPrefix string
|
||||
* All actor IDs created by this connection should be prefixed
|
||||
* with aPrefix.
|
||||
* @param aTransport transport
|
||||
* Packet transport for the debugging protocol.
|
||||
*/
|
||||
function DebuggerServerConnection(aPrefix, aTransport)
|
||||
{
|
||||
this._prefix = aPrefix;
|
||||
this._transport = aTransport;
|
||||
this._transport.hooks = this;
|
||||
this._nextID = 1;
|
||||
|
||||
this._actorPool = new ActorPool(this);
|
||||
this._extraPools = [];
|
||||
}
|
||||
|
||||
DebuggerServerConnection.prototype = {
|
||||
_prefix: null,
|
||||
get prefix() { return this._prefix },
|
||||
|
||||
_transport: null,
|
||||
get transport() { return this._transport },
|
||||
|
||||
send: function DSC_send(aPacket) {
|
||||
this.transport.send(aPacket);
|
||||
},
|
||||
|
||||
allocID: function DSC_allocID(aPrefix) {
|
||||
return this.prefix + (aPrefix || '') + this._nextID++;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a map of actor IDs to the connection.
|
||||
*/
|
||||
addActorPool: function DSC_addActorPool(aActorPool) {
|
||||
this._extraPools.push(aActorPool);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a previously-added pool of actors to the connection.
|
||||
*/
|
||||
removeActorPool: function DSC_removeActorPool(aActorPool) {
|
||||
let index = this._extraPools.splice(this._extraPools.lastIndexOf(aActorPool), 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an actor to the default actor pool for this connection.
|
||||
*/
|
||||
addActor: function DSC_addActor(aActor) {
|
||||
this._actorPool.addActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an actor to the default actor pool for this connection.
|
||||
*/
|
||||
removeActor: function DSC_removeActor(aActor) {
|
||||
this._actorPool.removeActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a cleanup to the default actor pool for this connection.
|
||||
*/
|
||||
addCleanup: function DSC_addCleanup(aCleanup) {
|
||||
this._actorPool.addCleanup(aCleanup);
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up an actor implementation for an actorID. Will search
|
||||
* all the actor pools registered with the connection.
|
||||
*
|
||||
* @param aActorID string
|
||||
* Actor ID to look up.
|
||||
*/
|
||||
getActor: function DSC_getActor(aActorID) {
|
||||
if (this._actorPool.has(aActorID)) {
|
||||
return this._actorPool.get(aActorID);
|
||||
}
|
||||
|
||||
for each (let pool in this._extraPools) {
|
||||
if (pool.has(aActorID)) {
|
||||
return pool.get(aActorID);
|
||||
}
|
||||
}
|
||||
|
||||
if (aActorID === "root") {
|
||||
return this.rootActor;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
// Transport hooks.
|
||||
|
||||
/**
|
||||
* Called by DebuggerTransport to dispatch incoming packets as appropriate.
|
||||
*
|
||||
* @param aPacket object
|
||||
* The incoming packet.
|
||||
*/
|
||||
onPacket: function DSC_onPacket(aPacket) {
|
||||
let actor = this.getActor(aPacket.to);
|
||||
if (!actor) {
|
||||
this.transport.send({ from: aPacket.to ? aPacket.to : "root",
|
||||
error: "noSuchActor" });
|
||||
return;
|
||||
}
|
||||
|
||||
var ret = null;
|
||||
|
||||
// Dispatch the request to the actor.
|
||||
if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
|
||||
try {
|
||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
ret = { error: "unknownError",
|
||||
message: "An unknown error has occurred while processing request." };
|
||||
}
|
||||
} else {
|
||||
ret = { error: "unrecognizedPacketType",
|
||||
message: 'Actor "' + actor.actorID + '" does not recognize the packet type "' + aPacket.type + '"' };
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
// XXX: The actor wasn't ready to reply yet, don't process new
|
||||
// requests until it does.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ret.from) {
|
||||
ret.from = aPacket.to;
|
||||
}
|
||||
|
||||
this.transport.send(ret);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by DebuggerTransport when the underlying stream is closed.
|
||||
*
|
||||
* @param aStatus nsresult
|
||||
* The status code that corresponds to the reason for closing
|
||||
* the stream.
|
||||
*/
|
||||
onClosed: function DSC_onClosed(aStatus) {
|
||||
dumpn("Cleaning up connection.");
|
||||
|
||||
this._actorPool.cleanup();
|
||||
this._actorPool = null;
|
||||
this._extraPools.map(function(p) { p.cleanup(); });
|
||||
this._extraPools = null;
|
||||
|
||||
DebuggerServer._connectionClosed(this);
|
||||
}
|
||||
};
|
||||
var DebuggerServer = gGlobal.DebuggerServer;
|
||||
|
@ -1,4 +1,5 @@
|
||||
toolkit.jar:
|
||||
content/global/devtools/dbg-transport.js (debugger/dbg-transport.js)
|
||||
content/global/devtools/dbg-server.js (debugger/server/dbg-server.js)
|
||||
content/global/devtools/dbg-script-actors.js (debugger/server/dbg-script-actors.js)
|
||||
content/global/devtools/dbg-browser-actors.js (debugger/server/dbg-browser-actors.js)
|
||||
|
@ -85,6 +85,7 @@ DEFINES += \
|
||||
-DAB_CD=$(AB_CD) \
|
||||
-DMOZ_LANGPACK_EID=$(MOZ_LANGPACK_EID) \
|
||||
-DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
|
||||
-DMOZ_APP_MAXVERSION=$(MOZ_APP_MAXVERSION) \
|
||||
-DLOCALE_SRCDIR=$(call core_abspath,$(LOCALE_SRCDIR)) \
|
||||
-DPKG_BASENAME="$(PKG_BASENAME)" \
|
||||
-DPKG_INST_BASENAME="$(PKG_INST_BASENAME)" \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user