mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
merge fx-team to m-c
This commit is contained in:
commit
57704f35e8
@ -255,6 +255,7 @@ _TEST_FILES1 = \
|
||||
test_DOMException.html \
|
||||
test_mutationobservers.html \
|
||||
mutationobserver_dialog.html \
|
||||
test_bug744830.html \
|
||||
$(NULL)
|
||||
|
||||
_TEST_FILES2 = \
|
||||
|
@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392511
|
||||
/** Test for Bug 392511 **/
|
||||
|
||||
var results = [
|
||||
"'\"&'",
|
||||
"\""&\"",
|
||||
"\""&\"",
|
||||
"\"'&\"",
|
||||
"\"'&\"",
|
||||
|
126
content/base/test/test_bug744830.html
Normal file
126
content/base/test/test_bug744830.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=744830
|
||||
-->
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
|
||||
<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
var t = document.getElementById('testnodes');
|
||||
is(t.innerHTML,
|
||||
"<span>hi</span> there <!-- mon ami -->",
|
||||
"comment nodes should be included");
|
||||
|
||||
var PI = document.createProcessingInstruction('foo', 'bar="1.0"');
|
||||
t.appendChild(PI);
|
||||
is(t.innerHTML, '<span>hi</span> there <!-- mon ami --><?foo bar="1.0">',
|
||||
"pi nodes should be included");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("textarea"));
|
||||
t.firstChild.appendChild(document.createTextNode("\nhello"));
|
||||
// This is the old behavior. Spec requires something else.
|
||||
is(t.innerHTML, "<textarea>\nhello</textarea>",
|
||||
"No extra newlines should be inserted to the textarea!");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<svg><foo></svg>");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math:math"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<math><foo></math>");
|
||||
|
||||
// Prefix is serialized if element isn't HTML/SVG/MathML
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.example.org", "ex:example"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<ex:example><foo></ex:example>");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.example.org", "example"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<example><foo></example>");
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "us-en");
|
||||
is(t.innerHTML, '<example xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo");
|
||||
is(t.innerHTML, '<example xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://foo");
|
||||
is(t.innerHTML, '<example xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:bar", "http://bar");
|
||||
is(t.innerHTML, '<example xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.helloworldns.org", "hello:world", "!");
|
||||
is(t.innerHTML, '<example hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttribute("foo", '-"&\xA0-');
|
||||
is(t.innerHTML, '<example foo="-"& -" hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("div"));
|
||||
t.firstChild.appendChild(document.implementation
|
||||
.createDocument(null, null, null)
|
||||
.createCDATASection("foo"));
|
||||
is(t.innerHTML, '<div>foo</div>');
|
||||
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<div>1&2<3>4 </div>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("script"));
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<script>1&2<3>4\xA0\u003C/script>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("style"));
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<style>1&2<3>4\xA0\u003C/style>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<svg><script>1&2<3>4 \u003C/script></svg>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "style"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<svg><style>1&2<3>4 \u003C/style></svg>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<math><script>1&2<3>4 \u003C/script></math>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "style"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<math><style>1&2<3>4 \u003C/style></math>');
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "nsDOMMutationObserver.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -632,19 +633,609 @@ nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Try to keep the size of StringBuilder close to a jemalloc bucket size.
|
||||
#define STRING_BUFFER_UNITS 1020
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
private:
|
||||
class Unit
|
||||
{
|
||||
public:
|
||||
Unit() : mType(eUnknown), mLength(0) {}
|
||||
~Unit()
|
||||
{
|
||||
if (mType == eString || mType == eStringWithEncode) {
|
||||
delete mString;
|
||||
}
|
||||
}
|
||||
|
||||
enum Type
|
||||
{
|
||||
eUnknown,
|
||||
eAtom,
|
||||
eString,
|
||||
eStringWithEncode,
|
||||
eLiteral,
|
||||
eTextFragment,
|
||||
eTextFragmentWithEncode,
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
nsIAtom* mAtom;
|
||||
const char* mLiteral;
|
||||
nsAutoString* mString;
|
||||
const nsTextFragment* mTextFragment;
|
||||
};
|
||||
Type mType;
|
||||
PRUint32 mLength;
|
||||
};
|
||||
public:
|
||||
StringBuilder() : mLast(this), mLength(0) {}
|
||||
|
||||
void Append(nsIAtom* aAtom)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mAtom = aAtom;
|
||||
u->mType = Unit::eAtom;
|
||||
PRUint32 len = aAtom->GetLength();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void Append(const char (&aLiteral)[N])
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mLiteral = aLiteral;
|
||||
u->mType = Unit::eLiteral;
|
||||
PRUint32 len = N - 1;
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void Append(char (&aLiteral)[N])
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mLiteral = aLiteral;
|
||||
u->mType = Unit::eLiteral;
|
||||
PRUint32 len = N - 1;
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void Append(const nsAString& aString)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = new nsAutoString(aString);
|
||||
u->mType = Unit::eString;
|
||||
PRUint32 len = aString.Length();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void Append(nsAutoString* aString)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = aString;
|
||||
u->mType = Unit::eString;
|
||||
PRUint32 len = aString->Length();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void AppendWithAttrEncode(nsAutoString* aString, PRUint32 aLen)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = aString;
|
||||
u->mType = Unit::eStringWithEncode;
|
||||
u->mLength = aLen;
|
||||
mLength += aLen;
|
||||
}
|
||||
|
||||
void Append(const nsTextFragment* aTextFragment)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mTextFragment = aTextFragment;
|
||||
u->mType = Unit::eTextFragment;
|
||||
PRUint32 len = aTextFragment->GetLength();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void AppendWithEncode(const nsTextFragment* aTextFragment, PRUint32 aLen)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mTextFragment = aTextFragment;
|
||||
u->mType = Unit::eTextFragmentWithEncode;
|
||||
u->mLength = aLen;
|
||||
mLength += aLen;
|
||||
}
|
||||
|
||||
bool ToString(nsAString& aOut)
|
||||
{
|
||||
if (!aOut.SetCapacity(mLength, fallible_t())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (StringBuilder* current = this; current; current = current->mNext) {
|
||||
PRUint32 len = current->mUnits.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
Unit& u = current->mUnits[i];
|
||||
switch (u.mType) {
|
||||
case Unit::eAtom:
|
||||
aOut.Append(nsDependentAtomString(u.mAtom));
|
||||
break;
|
||||
case Unit::eString:
|
||||
aOut.Append(*(u.mString));
|
||||
break;
|
||||
case Unit::eStringWithEncode:
|
||||
EncodeAttrString(*(u.mString), aOut);
|
||||
break;
|
||||
case Unit::eLiteral:
|
||||
aOut.AppendASCII(u.mLiteral, u.mLength);
|
||||
break;
|
||||
case Unit::eTextFragment:
|
||||
u.mTextFragment->AppendTo(aOut);
|
||||
break;
|
||||
case Unit::eTextFragmentWithEncode:
|
||||
EncodeTextFragment(u.mTextFragment, aOut);
|
||||
break;
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown unit type?");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
Unit* AddUnit()
|
||||
{
|
||||
if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
|
||||
new StringBuilder(this);
|
||||
}
|
||||
return mLast->mUnits.AppendElement();
|
||||
}
|
||||
|
||||
StringBuilder(StringBuilder* aFirst)
|
||||
: mLast(nsnull), mLength(0)
|
||||
{
|
||||
aFirst->mLast->mNext = this;
|
||||
aFirst->mLast = this;
|
||||
}
|
||||
|
||||
void EncodeAttrString(const nsAutoString& aValue, nsAString& aOut)
|
||||
{
|
||||
const PRUnichar* c = aValue.BeginReading();
|
||||
const PRUnichar* end = aValue.EndReading();
|
||||
while (c < end) {
|
||||
switch (*c) {
|
||||
case '"':
|
||||
aOut.AppendLiteral(""");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(*c);
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeTextFragment(const nsTextFragment* aValue, nsAString& aOut)
|
||||
{
|
||||
PRUint32 len = aValue->GetLength();
|
||||
if (aValue->Is2b()) {
|
||||
const PRUnichar* data = aValue->Get2b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const PRUnichar c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
aOut.AppendLiteral("<");
|
||||
break;
|
||||
case '>':
|
||||
aOut.AppendLiteral(">");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* data = aValue->Get1b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const unsigned char c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
aOut.AppendLiteral("<");
|
||||
break;
|
||||
case '>':
|
||||
aOut.AppendLiteral(">");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
|
||||
nsAutoPtr<StringBuilder> mNext;
|
||||
StringBuilder* mLast;
|
||||
// mLength is used only in the first StringBuilder object in the linked list.
|
||||
PRUint32 mLength;
|
||||
};
|
||||
|
||||
static void
|
||||
AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)
|
||||
{
|
||||
PRUint32 extraSpaceNeeded = 0;
|
||||
PRUint32 len = aText->GetLength();
|
||||
if (aText->Is2b()) {
|
||||
const PRUnichar* data = aText->Get2b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const PRUnichar c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
extraSpaceNeeded += ArrayLength("<") - 2;
|
||||
break;
|
||||
case '>':
|
||||
extraSpaceNeeded += ArrayLength(">") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* data = aText->Get1b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const unsigned char c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
extraSpaceNeeded += ArrayLength("<") - 2;
|
||||
break;
|
||||
case '>':
|
||||
extraSpaceNeeded += ArrayLength(">") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extraSpaceNeeded) {
|
||||
aBuilder.AppendWithEncode(aText, len + extraSpaceNeeded);
|
||||
} else {
|
||||
aBuilder.Append(aText);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AppendEncodedAttributeValue(nsAutoString* aValue, StringBuilder& aBuilder)
|
||||
{
|
||||
const PRUnichar* c = aValue->BeginReading();
|
||||
const PRUnichar* end = aValue->EndReading();
|
||||
|
||||
PRUint32 extraSpaceNeeded = 0;
|
||||
while (c < end) {
|
||||
switch (*c) {
|
||||
case '"':
|
||||
extraSpaceNeeded += ArrayLength(""") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
|
||||
if (extraSpaceNeeded) {
|
||||
aBuilder.AppendWithAttrEncode(aValue, aValue->Length() + extraSpaceNeeded);
|
||||
} else {
|
||||
aBuilder.Append(aValue);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
StartElement(Element* aContent, StringBuilder& aBuilder)
|
||||
{
|
||||
nsIAtom* localName = aContent->Tag();
|
||||
PRInt32 tagNS = aContent->GetNameSpaceID();
|
||||
|
||||
aBuilder.Append("<");
|
||||
if (aContent->IsHTML() || aContent->IsSVG() || aContent->IsMathML()) {
|
||||
aBuilder.Append(localName);
|
||||
} else {
|
||||
aBuilder.Append(aContent->NodeName());
|
||||
}
|
||||
|
||||
PRInt32 count = aContent->GetAttrCount();
|
||||
for (PRInt32 i = count; i > 0;) {
|
||||
--i;
|
||||
const nsAttrName* name = aContent->GetAttrNameAt(i);
|
||||
PRInt32 attNs = name->NamespaceID();
|
||||
nsIAtom* attName = name->LocalName();
|
||||
|
||||
// Filter out any attribute starting with [-|_]moz
|
||||
nsDependentAtomString attrNameStr(attName);
|
||||
if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
|
||||
StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString* attValue = new nsAutoString();
|
||||
aContent->GetAttr(attNs, attName, *attValue);
|
||||
|
||||
// Filter out special case of <br type="_moz*"> used by the editor.
|
||||
// Bug 16988. Yuck.
|
||||
if (localName == nsGkAtoms::br && tagNS == kNameSpaceID_XHTML &&
|
||||
attName == nsGkAtoms::type && attNs == kNameSpaceID_None &&
|
||||
StringBeginsWith(*attValue, NS_LITERAL_STRING("_moz"))) {
|
||||
delete attValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_LIKELY(attNs == kNameSpaceID_None) ||
|
||||
(attNs == kNameSpaceID_XMLNS &&
|
||||
attName == nsGkAtoms::xmlns)) {
|
||||
aBuilder.Append(" ");
|
||||
} else if (attNs == kNameSpaceID_XML) {
|
||||
aBuilder.Append(" xml:");
|
||||
} else if (attNs == kNameSpaceID_XMLNS) {
|
||||
aBuilder.Append(" xmlns:");
|
||||
} else if (attNs == kNameSpaceID_XLink) {
|
||||
aBuilder.Append(" xlink:");
|
||||
} else {
|
||||
nsIAtom* prefix = name->GetPrefix();
|
||||
if (prefix) {
|
||||
aBuilder.Append(" ");
|
||||
aBuilder.Append(prefix);
|
||||
aBuilder.Append(":");
|
||||
}
|
||||
}
|
||||
|
||||
aBuilder.Append(attName);
|
||||
aBuilder.Append("=\"");
|
||||
AppendEncodedAttributeValue(attValue, aBuilder);
|
||||
aBuilder.Append("\"");
|
||||
}
|
||||
|
||||
aBuilder.Append(">");
|
||||
|
||||
/*
|
||||
// Per HTML spec we should append one \n if the first child of
|
||||
// pre/textarea/listing is a textnode and starts with a \n.
|
||||
// But because browsers haven't traditionally had that behavior,
|
||||
// we're not changing our behavior either - yet.
|
||||
if (aContent->IsHTML()) {
|
||||
if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
|
||||
localName == nsGkAtoms::listing) {
|
||||
nsIContent* fc = aContent->GetFirstChild();
|
||||
if (fc &&
|
||||
(fc->NodeType() == nsIDOMNode::TEXT_NODE ||
|
||||
fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
|
||||
const nsTextFragment* text = fc->GetText();
|
||||
if (text && text->GetLength() && text->CharAt(0) == PRUnichar('\n')) {
|
||||
aBuilder.Append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ShouldEscape(nsIContent* aParent)
|
||||
{
|
||||
if (!aParent || !aParent->IsHTML()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const nsIAtom* nonEscapingElements[] = {
|
||||
nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
|
||||
nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
|
||||
nsGkAtoms::plaintext,
|
||||
// Per the current spec noscript should be escaped in case
|
||||
// scripts are disabled or if document doesn't have
|
||||
// browsing context. However the latter seems to be a spec bug
|
||||
// and Gecko hasn't traditionally done the former.
|
||||
nsGkAtoms::noscript
|
||||
};
|
||||
static mozilla::BloomFilter<12, nsIAtom> sFilter;
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
sInitialized = true;
|
||||
for (PRUint32 i = 0; i < ArrayLength(nonEscapingElements); ++i) {
|
||||
sFilter.add(nonEscapingElements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsIAtom* tag = aParent->Tag();
|
||||
if (sFilter.mightContain(tag)) {
|
||||
for (PRUint32 i = 0; i < ArrayLength(nonEscapingElements); ++i) {
|
||||
if (tag == nonEscapingElements[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsVoidTag(Element* aElement)
|
||||
{
|
||||
if (!aElement->IsHTML()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const nsIAtom* voidElements[] = {
|
||||
nsGkAtoms::area, nsGkAtoms::base, nsGkAtoms::basefont,
|
||||
nsGkAtoms::bgsound, nsGkAtoms::br, nsGkAtoms::col,
|
||||
nsGkAtoms::command, nsGkAtoms::embed, nsGkAtoms::frame,
|
||||
nsGkAtoms::hr, nsGkAtoms::img, nsGkAtoms::input,
|
||||
nsGkAtoms::keygen, nsGkAtoms::link, nsGkAtoms::meta,
|
||||
nsGkAtoms::param, nsGkAtoms::source, nsGkAtoms::track,
|
||||
nsGkAtoms::wbr
|
||||
};
|
||||
|
||||
static mozilla::BloomFilter<12, nsIAtom> sFilter;
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
sInitialized = true;
|
||||
for (PRUint32 i = 0; i < ArrayLength(voidElements); ++i) {
|
||||
sFilter.add(voidElements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsIAtom* tag = aElement->Tag();
|
||||
if (sFilter.mightContain(tag)) {
|
||||
for (PRUint32 i = 0; i < ArrayLength(voidElements); ++i) {
|
||||
if (tag == voidElements[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
Serialize(Element* aRoot, bool aDescendentsOnly, nsAString& aOut)
|
||||
{
|
||||
nsINode* current = aDescendentsOnly ? aRoot->GetFirstChild() : aRoot;
|
||||
if (!current) {
|
||||
return true;
|
||||
}
|
||||
|
||||
StringBuilder builder;
|
||||
nsIContent* next;
|
||||
while (true) {
|
||||
bool isVoid = false;
|
||||
switch (current->NodeType()) {
|
||||
case nsIDOMNode::ELEMENT_NODE: {
|
||||
Element* elem = current->AsElement();
|
||||
StartElement(elem, builder);
|
||||
isVoid = IsVoidTag(elem);
|
||||
if (!isVoid && (next = current->GetFirstChild())) {
|
||||
current = next;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
case nsIDOMNode::CDATA_SECTION_NODE: {
|
||||
const nsTextFragment* text = static_cast<nsIContent*>(current)->GetText();
|
||||
nsIContent* parent = current->GetParent();
|
||||
if (ShouldEscape(parent)) {
|
||||
AppendEncodedCharacters(text, builder);
|
||||
} else {
|
||||
builder.Append(text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::COMMENT_NODE: {
|
||||
builder.Append("<!--");
|
||||
builder.Append(static_cast<nsIContent*>(current)->GetText());
|
||||
builder.Append("-->");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::DOCUMENT_TYPE_NODE: {
|
||||
builder.Append("<!DOCTYPE ");
|
||||
builder.Append(current->NodeName());
|
||||
builder.Append(">");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: {
|
||||
builder.Append("<?");
|
||||
builder.Append(current->NodeName());
|
||||
builder.Append(" ");
|
||||
builder.Append(static_cast<nsIContent*>(current)->GetText());
|
||||
builder.Append(">");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (!isVoid && current->NodeType() == nsIDOMNode::ELEMENT_NODE) {
|
||||
builder.Append("</");
|
||||
nsIContent* elem = static_cast<nsIContent*>(current);
|
||||
if (elem->IsHTML() || elem->IsSVG() || elem->IsMathML()) {
|
||||
builder.Append(elem->Tag());
|
||||
} else {
|
||||
builder.Append(current->NodeName());
|
||||
}
|
||||
builder.Append(">");
|
||||
}
|
||||
isVoid = false;
|
||||
|
||||
if (current == aRoot) {
|
||||
return builder.ToString(aOut);
|
||||
}
|
||||
|
||||
if ((next = current->GetNextSibling())) {
|
||||
current = next;
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->GetNodeParent();
|
||||
if (aDescendentsOnly && current == aRoot) {
|
||||
return builder.ToString(aOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
{
|
||||
aMarkup.Truncate();
|
||||
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (IsInHTMLDocument()) {
|
||||
return Serialize(this, !aIncludeSelf, aMarkup) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoString contentType;
|
||||
if (IsInHTMLDocument()) {
|
||||
contentType.AssignLiteral("text/html");
|
||||
} else {
|
||||
doc->GetContentType(contentType);
|
||||
}
|
||||
doc->GetContentType(contentType);
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
|
||||
if (!docEncoder) {
|
||||
@ -654,7 +1245,7 @@ nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
NS_ConvertUTF16toUTF8(contentType)
|
||||
).get());
|
||||
}
|
||||
if (!(docEncoder || doc->IsHTML())) {
|
||||
if (!docEncoder) {
|
||||
// This could be some type for which we create a synthetic document. Try
|
||||
// again as XML
|
||||
contentType.AssignLiteral("application/xml");
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "nsSVGSVGElement.h"
|
||||
#include "nsSVGTextContainerFrame.h"
|
||||
#include "SVGAnimatedPreserveAspectRatio.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1669,9 +1670,9 @@ nsSVGUtils::WritePPM(const char *fname, gfxImageSurface *aSurface)
|
||||
PRInt32 stride = aSurface->Stride();
|
||||
for (int y=0; y<size.height; y++) {
|
||||
for (int x=0; x<size.width; x++) {
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_R, 1, 1, f);
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_G, 1, 1, f);
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_B, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_R, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_G, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_B, 1, 1, f);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
@ -7,41 +7,43 @@
|
||||
|
||||
#ifdef ANDROID
|
||||
#define wrap(a) __wrap_ ## a
|
||||
|
||||
/* operator new wrapper implementation */
|
||||
static void *
|
||||
new(unsigned int size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
/* operator new(unsigned int) */
|
||||
MOZ_EXPORT_API(void *)
|
||||
wrap(_Znwj)(unsigned int) __attribute__((alias("new")));
|
||||
/* operator new[](unsigned int) */
|
||||
MOZ_EXPORT_API(void *)
|
||||
wrap(_Znaj)(unsigned int) __attribute__((alias("new")));
|
||||
|
||||
/* operator delete wrapper implementation */
|
||||
static void
|
||||
delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
/* operator delete(void*) */
|
||||
MOZ_EXPORT_API(void)
|
||||
wrap(_ZdlPv)(void *ptr) __attribute__((alias("delete")));
|
||||
/* operator delete[](void*) */
|
||||
MOZ_EXPORT_API(void)
|
||||
wrap(_ZdaPv)(void *ptr) __attribute__((alias("delete")));
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
#elif defined(XP_WIN) || defined(XP_MACOSX)
|
||||
#define wrap(a) je_ ## a
|
||||
#endif
|
||||
|
||||
#ifdef wrap
|
||||
void *wrap(malloc)(size_t);
|
||||
void wrap(free)(void *);
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
/* operator new(unsigned int) */
|
||||
MOZ_EXPORT_API(void *)
|
||||
wrap(_Znwj)(unsigned int size)
|
||||
{
|
||||
return wrap(malloc)(size);
|
||||
}
|
||||
/* operator new[](unsigned int) */
|
||||
MOZ_EXPORT_API(void *)
|
||||
wrap(_Znaj)(unsigned int size)
|
||||
{
|
||||
return wrap(malloc)(size);
|
||||
}
|
||||
/* operator delete(void*) */
|
||||
MOZ_EXPORT_API(void)
|
||||
wrap(_ZdlPv)(void *ptr)
|
||||
{
|
||||
wrap(free)(ptr);
|
||||
}
|
||||
/* operator delete[](void*) */
|
||||
MOZ_EXPORT_API(void)
|
||||
wrap(_ZdaPv)(void *ptr)
|
||||
{
|
||||
wrap(free)(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef wrap
|
||||
MOZ_EXPORT_API(char *)
|
||||
wrap(strndup)(const char *src, size_t len)
|
||||
{
|
||||
|
76
netwerk/base/src/AutoClose.h
Normal file
76
netwerk/base/src/AutoClose.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_AutoClose_h
|
||||
#define mozilla_net_AutoClose_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
// Like an nsAutoPtr for XPCOM streams (e.g. nsIAsyncInputStream) and other
|
||||
// refcounted classes that need to have the Close() method called explicitly
|
||||
// before they are destroyed.
|
||||
template <typename T>
|
||||
class AutoClose
|
||||
{
|
||||
public:
|
||||
AutoClose() { }
|
||||
~AutoClose(){
|
||||
Close();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
already_AddRefed<T> forget()
|
||||
{
|
||||
return mPtr.forget();
|
||||
}
|
||||
|
||||
void takeOver(AutoClose<T> & rhs)
|
||||
{
|
||||
Close();
|
||||
mPtr = rhs.mPtr.forget();
|
||||
}
|
||||
|
||||
// assign from |do_QueryInterface(expr, &rv)|
|
||||
void operator=(const nsQueryInterfaceWithError rhs)
|
||||
{
|
||||
Close();
|
||||
mPtr = rhs;
|
||||
}
|
||||
|
||||
void CloseAndRelease()
|
||||
{
|
||||
Close();
|
||||
mPtr = nsnull;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return mPtr.operator->();
|
||||
}
|
||||
|
||||
private:
|
||||
void Close()
|
||||
{
|
||||
if (mPtr) {
|
||||
mPtr->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(const AutoClose<T> &) MOZ_DELETE;
|
||||
AutoClose(const AutoClose<T> &) MOZ_DELETE;
|
||||
|
||||
nsCOMPtr<T> mPtr;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_AutoClose_h
|
14
netwerk/cache/nsCacheEntryDescriptor.cpp
vendored
14
netwerk/cache/nsCacheEntryDescriptor.cpp
vendored
@ -540,6 +540,11 @@ nsInputStreamWrapper::LazyInit()
|
||||
rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode,
|
||||
mStartOffset,
|
||||
getter_AddRefs(mInput));
|
||||
|
||||
CACHE_LOG_DEBUG(("nsInputStreamWrapper::LazyInit "
|
||||
"[entry=%p, wrapper=%p, mInput=%p, rv=%d]",
|
||||
mDescriptor, this, mInput.get(), PRIntn(rv)));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mInitialized = true;
|
||||
@ -568,9 +573,14 @@ nsresult nsCacheEntryDescriptor::
|
||||
nsInputStreamWrapper::Read(char *buf, PRUint32 count, PRUint32 *countRead)
|
||||
{
|
||||
nsresult rv = EnsureInit();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = mInput->Read(buf, count, countRead);
|
||||
|
||||
return mInput->Read(buf, count, countRead);
|
||||
CACHE_LOG_DEBUG(("nsInputStreamWrapper::Read "
|
||||
"[entry=%p, wrapper=%p, mInput=%p, rv=%d]",
|
||||
mDescriptor, this, mInput.get(), rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsCacheEntryDescriptor::
|
||||
|
2
netwerk/cache/nsCacheService.cpp
vendored
2
netwerk/cache/nsCacheService.cpp
vendored
@ -1759,7 +1759,7 @@ nsCacheService::ProcessRequest(nsCacheRequest * request,
|
||||
|
||||
if (request->mListener) { // Asynchronous
|
||||
|
||||
if (NS_FAILED(rv) && calledFromOpenCacheEntry)
|
||||
if (NS_FAILED(rv) && calledFromOpenCacheEntry && request->IsBlocking())
|
||||
return rv; // skip notifying listener, just return rv to caller
|
||||
|
||||
// call listener to report error or descriptor
|
||||
|
19
netwerk/cache/nsDiskCacheBlockFile.cpp
vendored
19
netwerk/cache/nsDiskCacheBlockFile.cpp
vendored
@ -4,6 +4,7 @@
|
||||
* 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 "nsCache.h"
|
||||
#include "nsDiskCache.h"
|
||||
#include "nsDiskCacheBlockFile.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
@ -31,14 +32,15 @@ nsDiskCacheBlockFile::Open(nsILocalFile * blockFile,
|
||||
|
||||
// open the file - restricted to user, the data could be confidential
|
||||
nsresult rv = blockFile->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE, 00600, &mFD);
|
||||
if (NS_FAILED(rv)) return rv; // unable to open or create file
|
||||
if (NS_FAILED(rv)) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open "
|
||||
"[this=%p] unable to open or create file: %d",
|
||||
this, rv));
|
||||
return rv; // unable to open or create file
|
||||
}
|
||||
|
||||
// allocate bit map buffer
|
||||
mBitMap = new PRUint32[mBitMapWords];
|
||||
if (!mBitMap) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// check if we just creating the file
|
||||
mFileSize = PR_Available(mFD);
|
||||
@ -79,9 +81,13 @@ nsDiskCacheBlockFile::Open(nsILocalFile * blockFile,
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open [this=%p] succeeded",
|
||||
this));
|
||||
return NS_OK;
|
||||
|
||||
error_exit:
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open [this=%p] failed with "
|
||||
"error %d", this, rv));
|
||||
Close(false);
|
||||
return rv;
|
||||
}
|
||||
@ -234,6 +240,9 @@ nsDiskCacheBlockFile::ReadBlocks( void * buffer,
|
||||
}
|
||||
*bytesRead = PR_Read(mFD, buffer, bytesToRead);
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Read [this=%p] "
|
||||
"returned %d / %d bytes", this, *bytesRead, bytesToRead));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
6
netwerk/cache/nsDiskCacheMap.cpp
vendored
6
netwerk/cache/nsDiskCacheMap.cpp
vendored
@ -77,6 +77,8 @@ nsDiskCacheMap::Open(nsILocalFile * cacheDirectory)
|
||||
if (!cacheFilesExist)
|
||||
goto error_exit;
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheMap::Open [this=%p] reading map", this));
|
||||
|
||||
// read the header
|
||||
PRUint32 bytesRead = PR_Read(mMapFD, &mHeader, sizeof(nsDiskCacheHeader));
|
||||
if (sizeof(nsDiskCacheHeader) != bytesRead) goto error_exit;
|
||||
@ -686,7 +688,11 @@ nsDiskCacheMap::ReadDiskCacheEntry(nsDiskCacheRecord * record)
|
||||
getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheMap::ReadDiskCacheEntry"
|
||||
"[this=%p] reading disk cache entry", this));
|
||||
|
||||
PRFileDesc * fd = nsnull;
|
||||
|
||||
// open the file - restricted to user, the data could be confidential
|
||||
rv = file->OpenNSPRFileDesc(PR_RDONLY, 00600, &fd);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
34
netwerk/cache/nsDiskCacheStreams.cpp
vendored
34
netwerk/cache/nsDiskCacheStreams.cpp
vendored
@ -108,11 +108,25 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
{
|
||||
*bytesRead = 0;
|
||||
|
||||
if (mClosed)
|
||||
if (mClosed) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream was closed",
|
||||
this, buffer, count));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mPos == mStreamEnd) return NS_OK;
|
||||
if (mPos > mStreamEnd) return NS_ERROR_UNEXPECTED;
|
||||
if (mPos == mStreamEnd) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream at end of file",
|
||||
this, buffer, count));
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPos > mStreamEnd) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream past end of file (!)",
|
||||
this, buffer, count));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (count > mStreamEnd - mPos)
|
||||
count = mStreamEnd - mPos;
|
||||
@ -120,7 +134,14 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
if (mFD) {
|
||||
// just read from file
|
||||
PRInt32 result = PR_Read(mFD, buffer, count);
|
||||
if (result < 0) return NS_ErrorAccordingToNSPR();
|
||||
if (result < 0) {
|
||||
PRErrorCode error = PR_GetError();
|
||||
nsresult rv = NS_ErrorAccordingToNSPR();
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read PR_Read failed"
|
||||
"[stream=%p, rv=%d, NSPR error %s",
|
||||
this, PRIntn(rv), PR_ErrorToName(error)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPos += (PRUint32)result;
|
||||
*bytesRead = (PRUint32)result;
|
||||
@ -134,6 +155,9 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
// no data source for input stream
|
||||
}
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p, count=%ud, byteRead=%ud] ",
|
||||
this, PRUintn(count), PRUintn(*bytesRead)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -679,6 +703,8 @@ nsDiskCacheStreamIO::OpenCacheFile(PRIntn flags, PRFileDesc ** fd)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(fd);
|
||||
|
||||
CACHE_LOG_DEBUG(("nsDiskCacheStreamIO::OpenCacheFile"));
|
||||
|
||||
nsresult rv;
|
||||
nsDiskCacheMap * cacheMap = mDevice->CacheMap();
|
||||
|
||||
|
@ -50,7 +50,6 @@ HttpBaseChannel::HttpBaseChannel()
|
||||
, mTimingEnabled(false)
|
||||
, mAllowSpdy(true)
|
||||
, mSuspendCount(0)
|
||||
, mRedirectedCachekeys(nsnull)
|
||||
{
|
||||
LOG(("Creating HttpBaseChannel @%x\n", this));
|
||||
|
||||
@ -1626,8 +1625,7 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
if (mRedirectedCachekeys) {
|
||||
LOG(("HttpBaseChannel::SetupReplacementChannel "
|
||||
"[this=%p] transferring chain of redirect cache-keys", this));
|
||||
httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys);
|
||||
mRedirectedCachekeys = nsnull;
|
||||
httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,10 +140,7 @@ public:
|
||||
|
||||
inline void CleanRedirectCacheChainIfNecessary()
|
||||
{
|
||||
if (mRedirectedCachekeys) {
|
||||
delete mRedirectedCachekeys;
|
||||
mRedirectedCachekeys = nsnull;
|
||||
}
|
||||
mRedirectedCachekeys = nsnull;
|
||||
}
|
||||
NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName,
|
||||
nsIHttpUpgradeListener *aListener);
|
||||
@ -272,7 +269,7 @@ protected:
|
||||
// Current suspension depth for this channel object
|
||||
PRUint32 mSuspendCount;
|
||||
|
||||
nsTArray<nsCString> *mRedirectedCachekeys;
|
||||
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
||||
};
|
||||
|
||||
// Share some code while working around C++'s absurd inability to handle casting
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,15 +26,17 @@
|
||||
#include "nsIHttpAuthenticableChannel.h"
|
||||
#include "nsIHttpChannelAuthProvider.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsDNSPrefetch.h"
|
||||
#include "TimingStruct.h"
|
||||
#include "AutoClose.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
class nsAHttpConnection;
|
||||
class AutoRedirectVetoNotifier;
|
||||
|
||||
using namespace mozilla::net;
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class HttpCacheQuery;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel
|
||||
@ -156,7 +158,8 @@ private:
|
||||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||
|
||||
bool RequestIsConditional();
|
||||
nsresult Connect(bool firstTime = true);
|
||||
nsresult Connect();
|
||||
nsresult ContinueConnect();
|
||||
void SpeculativeConnect();
|
||||
nsresult SetupTransaction();
|
||||
nsresult CallOnStartRequest();
|
||||
@ -172,7 +175,6 @@ private:
|
||||
nsresult ProcessFailedSSLConnect(PRUint32 httpStatus);
|
||||
nsresult ProcessFallback(bool *waitingForRedirectCallback);
|
||||
nsresult ContinueProcessFallback(nsresult);
|
||||
bool ResponseWouldVary();
|
||||
void HandleAsyncAbort();
|
||||
nsresult EnsureAssocReq();
|
||||
|
||||
@ -200,11 +202,11 @@ private:
|
||||
nsresult ResolveProxy();
|
||||
|
||||
// cache specific methods
|
||||
nsresult OpenCacheEntry();
|
||||
nsresult OpenCacheEntry(bool usingSSL);
|
||||
nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult aResult);
|
||||
nsresult OpenNormalCacheEntry();
|
||||
nsresult OpenNormalCacheEntry(bool usingSSL);
|
||||
nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult aResult);
|
||||
@ -219,8 +221,9 @@ private:
|
||||
nsresult GenerateCacheKey(PRUint32 postID, nsACString &key);
|
||||
nsresult UpdateExpirationTime();
|
||||
nsresult CheckCache();
|
||||
nsresult ShouldUpdateOfflineCacheEntry(bool *shouldCacheForOfflineUse);
|
||||
nsresult ReadFromCache();
|
||||
bool ShouldUpdateOfflineCacheEntry();
|
||||
nsresult StartBufferingCachedEntity(bool usingSSL);
|
||||
nsresult ReadFromCache(bool alreadyMarkedValid);
|
||||
void CloseCacheEntry(bool doomOnFailure);
|
||||
void CloseOfflineCacheEntry();
|
||||
nsresult InitCacheEntry();
|
||||
@ -232,7 +235,7 @@ private:
|
||||
nsresult InstallCacheListener(PRUint32 offset = 0);
|
||||
nsresult InstallOfflineCacheListener();
|
||||
void MaybeInvalidateCacheEntryForSubsequentGet();
|
||||
nsCacheStoragePolicy DetermineStoragePolicy();
|
||||
nsCacheStoragePolicy DetermineStoragePolicy(bool isPrivate);
|
||||
nsresult DetermineCacheAccess(nsCacheAccessMode *_retval);
|
||||
void AsyncOnExamineCachedResponse();
|
||||
|
||||
@ -240,12 +243,10 @@ private:
|
||||
void ClearBogusContentEncodingIfNeeded();
|
||||
|
||||
// byte range request specific methods
|
||||
nsresult SetupByteRangeRequest(PRUint32 partialLen);
|
||||
nsresult ProcessPartialContent();
|
||||
nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
|
||||
|
||||
nsresult DoAuthRetry(nsAHttpConnection *);
|
||||
bool MustValidateBasedOnQueryUrl();
|
||||
|
||||
void HandleAsyncRedirectChannelToHttps();
|
||||
nsresult AsyncRedirectChannelToHttps();
|
||||
@ -259,16 +260,10 @@ private:
|
||||
*/
|
||||
nsresult ProcessSTSHeader();
|
||||
|
||||
/**
|
||||
* Computes and returns a 64 bit encoded string holding a hash of the
|
||||
* input buffer. Input buffer must be a null-terminated string.
|
||||
*/
|
||||
nsresult Hash(const char *buf, nsACString &hash);
|
||||
|
||||
void InvalidateCacheEntryForLocation(const char *location);
|
||||
void AssembleCacheKey(const char *spec, PRUint32 postID, nsACString &key);
|
||||
nsresult CreateNewURI(const char *loc, nsIURI **newURI);
|
||||
void DoInvalidateCacheEntry(nsACString &key);
|
||||
void DoInvalidateCacheEntry(const nsCString &key);
|
||||
|
||||
// Ref RFC2616 13.10: "invalidation... MUST only be performed if
|
||||
// the host part is the same as in the Request-URI"
|
||||
@ -289,10 +284,15 @@ private:
|
||||
PRUint64 mLogicalOffset;
|
||||
|
||||
// cache specific data
|
||||
nsRefPtr<HttpCacheQuery> mCacheQuery;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||
// We must close mCacheAsyncInputStream explicitly to avoid leaks.
|
||||
AutoClose<nsIAsyncInputStream> mCacheAsyncInputStream;
|
||||
nsRefPtr<nsInputStreamPump> mCachePump;
|
||||
nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
|
||||
nsCOMPtr<nsISupports> mCachedSecurityInfo;
|
||||
nsCacheAccessMode mCacheAccess;
|
||||
mozilla::Telemetry::ID mCacheEntryDeviceTelemetryID;
|
||||
PRUint32 mPostID;
|
||||
PRUint32 mRequestTime;
|
||||
|
||||
@ -317,6 +317,8 @@ private:
|
||||
|
||||
friend class AutoRedirectVetoNotifier;
|
||||
friend class HttpAsyncAborter<nsHttpChannel>;
|
||||
friend class HttpCacheQuery;
|
||||
|
||||
nsCOMPtr<nsIURI> mRedirectURI;
|
||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
PRUint32 mRedirectType;
|
||||
@ -344,8 +346,6 @@ private:
|
||||
|
||||
nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
|
||||
|
||||
nsCOMPtr<nsICryptoHash> mHasher;
|
||||
|
||||
PRTime mChannelCreationTime;
|
||||
mozilla::TimeStamp mChannelCreationTimestamp;
|
||||
mozilla::TimeStamp mAsyncOpenTime;
|
||||
@ -374,4 +374,6 @@ private: // cache telemetry
|
||||
bool mDidReval;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::net
|
||||
|
||||
#endif // nsHttpChannel_h__
|
||||
|
@ -406,52 +406,6 @@ nsHttpHandler::IsAcceptableEncoding(const char *enc)
|
||||
return nsHttp::FindToken(mAcceptEncodings.get(), enc, HTTP_LWS ",") != nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate,
|
||||
nsICacheSession **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Skip cache if disabled in preferences
|
||||
if (!mUseCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// We want to get the pointer to the cache service each time we're called,
|
||||
// because it's possible for some add-ons (such as Google Gears) to swap
|
||||
// in new cache services on the fly, and we want to pick them up as
|
||||
// appropriate.
|
||||
nsCOMPtr<nsICacheService> serv = do_GetService(NS_CACHESERVICE_CONTRACTID,
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
const char *sessionName = "HTTP";
|
||||
switch (storagePolicy) {
|
||||
case nsICache::STORE_IN_MEMORY:
|
||||
sessionName = isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only";
|
||||
break;
|
||||
case nsICache::STORE_OFFLINE:
|
||||
sessionName = "HTTP-offline";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheSession> cacheSession;
|
||||
rv = serv->CreateSession(sessionName,
|
||||
storagePolicy,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(cacheSession));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = cacheSession->SetDoomEntriesIfExpired(false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ADDREF(*result = cacheSession);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
nsHttpConnectionMgr *ConnMgr() { return mConnMgr; }
|
||||
|
||||
// cache support
|
||||
nsresult GetCacheSession(nsCacheStoragePolicy, bool isPrivate, nsICacheSession **);
|
||||
bool UseCache() const { return mUseCache; }
|
||||
PRUint32 GenerateUniqueID() { return ++mLastUniqueID; }
|
||||
PRUint32 SessionStartTime() { return mSessionStartTime; }
|
||||
|
||||
|
@ -380,7 +380,11 @@ nsHttpResponseHead::IsResumable() const
|
||||
{
|
||||
// even though some HTTP/1.0 servers may support byte range requests, we're not
|
||||
// going to bother with them, since those servers wouldn't understand If-Range.
|
||||
return mVersion >= NS_HTTP_VERSION_1_1 &&
|
||||
// Also, while in theory it may be possible to resume when the status code
|
||||
// is not 200, it is unlikely to be worth the trouble, especially for
|
||||
// non-2xx responses.
|
||||
return mStatus == 200 &&
|
||||
mVersion >= NS_HTTP_VERSION_1_1 &&
|
||||
PeekHeader(nsHttp::Content_Length) &&
|
||||
(PeekHeader(nsHttp::ETag) || PeekHeader(nsHttp::Last_Modified)) &&
|
||||
HasHeaderValue(nsHttp::Accept_Ranges, "bytes");
|
||||
|
@ -270,6 +270,7 @@ package-tests: \
|
||||
stage-peptest \
|
||||
stage-mozbase \
|
||||
stage-tps \
|
||||
stage-modules \
|
||||
$(NULL)
|
||||
else
|
||||
# This staging area has been built for us by universal/flight.mk
|
||||
@ -336,6 +337,10 @@ stage-tps: make-stage-dir
|
||||
@(cd $(topsrcdir)/services/sync/tps && tar $(TAR_CREATE_FLAGS) - *) | (cd $(PKG_STAGE)/tps && tar -xf -)
|
||||
(cd $(topsrcdir)/services/sync/tests/tps && tar $(TAR_CREATE_FLAGS_QUIET) - *) | (cd $(PKG_STAGE)/tps/tests && tar -xf -)
|
||||
|
||||
# This will get replaced by actual logic in a subsequent patch.
|
||||
stage-modules: make-stage-dir
|
||||
$(TOUCH) $(PKG_STAGE)/modules/.dummy
|
||||
|
||||
stage-mozbase: make-stage-dir
|
||||
$(MAKE) -C $(DEPTH)/testing/mozbase stage-package
|
||||
.PHONY: \
|
||||
@ -361,5 +366,6 @@ stage-mozbase: make-stage-dir
|
||||
stage-peptest \
|
||||
stage-mozbase \
|
||||
stage-tps \
|
||||
stage-modules \
|
||||
$(NULL)
|
||||
|
||||
|
@ -491,10 +491,7 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint32 aKey, bool *_retval)
|
||||
// The user wants explicitely to use that result, so this ensures
|
||||
// association of the result with the autocompleted text.
|
||||
nsAutoString value;
|
||||
nsAutoString inputValue;
|
||||
input->GetTextValue(inputValue);
|
||||
if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, value)) &&
|
||||
value.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
|
||||
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(value))) {
|
||||
input->SetTextValue(value);
|
||||
input->SelectTextRange(value.Length(), value.Length());
|
||||
}
|
||||
@ -1184,10 +1181,7 @@ nsAutoCompleteController::EnterMatch(bool aIsPopupSelection)
|
||||
// The user wants explicitely to use that result, so this ensures
|
||||
// association of the result with the autocompleted text.
|
||||
nsAutoString defaultIndexValue;
|
||||
nsAutoString inputValue;
|
||||
input->GetTextValue(inputValue);
|
||||
if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, defaultIndexValue)) &&
|
||||
defaultIndexValue.Equals(inputValue, nsCaseInsensitiveStringComparator()))
|
||||
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(defaultIndexValue)))
|
||||
value = defaultIndexValue;
|
||||
}
|
||||
|
||||
@ -1444,34 +1438,34 @@ nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aResultIndex)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
bool aPreserveCasing,
|
||||
nsAString &_retval)
|
||||
nsAutoCompleteController::GetDefaultCompleteResult(PRInt32 aResultIndex,
|
||||
nsIAutoCompleteResult** _result,
|
||||
PRInt32* _defaultIndex)
|
||||
{
|
||||
PRInt32 defaultIndex = -1;
|
||||
PRInt32 index = aResultIndex;
|
||||
if (index < 0) {
|
||||
PRUint32 count = mResults.Count();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsIAutoCompleteResult *result = mResults[i];
|
||||
if (result && NS_SUCCEEDED(result->GetDefaultIndex(&defaultIndex)) &&
|
||||
defaultIndex >= 0) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
*_defaultIndex = -1;
|
||||
PRInt32 resultIndex = aResultIndex;
|
||||
|
||||
// If a result index was not provided, find the first defaultIndex result.
|
||||
for (PRInt32 i = 0; resultIndex < 0 && i < mResults.Count(); ++i) {
|
||||
nsIAutoCompleteResult *result = mResults[i];
|
||||
if (result &&
|
||||
NS_SUCCEEDED(result->GetDefaultIndex(_defaultIndex)) &&
|
||||
*_defaultIndex >= 0) {
|
||||
resultIndex = i;
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(index >= 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(resultIndex >= 0, NS_ERROR_FAILURE);
|
||||
|
||||
nsIAutoCompleteResult *result = mResults.SafeObjectAt(index);
|
||||
NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE);
|
||||
*_result = mResults.SafeObjectAt(resultIndex);
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_FAILURE);
|
||||
|
||||
if (defaultIndex < 0) {
|
||||
if (*_defaultIndex < 0) {
|
||||
// The search must explicitly provide a default index in order
|
||||
// for us to be able to complete.
|
||||
result->GetDefaultIndex(&defaultIndex);
|
||||
(*_result)->GetDefaultIndex(_defaultIndex);
|
||||
}
|
||||
if (defaultIndex < 0) {
|
||||
|
||||
if (*_defaultIndex < 0) {
|
||||
// We were given a result index, but that result doesn't want to
|
||||
// be autocompleted.
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1481,10 +1475,24 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
// provides a defaultIndex greater than its matchCount, avoid trying to
|
||||
// complete to an empty value.
|
||||
PRUint32 matchCount = 0;
|
||||
result->GetMatchCount(&matchCount);
|
||||
(*_result)->GetMatchCount(&matchCount);
|
||||
// Here defaultIndex is surely non-negative, so can be cast to unsigned.
|
||||
if ((PRUint32)defaultIndex >= matchCount)
|
||||
if ((PRUint32)(*_defaultIndex) >= matchCount) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
bool aPreserveCasing,
|
||||
nsAString &_retval)
|
||||
{
|
||||
nsIAutoCompleteResult *result;
|
||||
PRInt32 defaultIndex = -1;
|
||||
nsresult rv = GetDefaultCompleteResult(aResultIndex, &result, &defaultIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString resultValue;
|
||||
result->GetValueAt(defaultIndex, resultValue);
|
||||
@ -1512,6 +1520,37 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetFinalDefaultCompleteValue(nsAString &_retval)
|
||||
{
|
||||
nsIAutoCompleteResult *result;
|
||||
PRInt32 defaultIndex = -1;
|
||||
nsresult rv = GetDefaultCompleteResult(-1, &result, &defaultIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Hack: For typeAheadResults allow the comment to be used as the final
|
||||
// defaultComplete value if provided, otherwise fall back to the usual
|
||||
// value. This allows to provide a different complete text when the user
|
||||
// confirms the match. Don't rely on this for production code, since it's a
|
||||
// temporary solution that needs a dedicated API (bug 754265).
|
||||
bool isTypeAheadResult = false;
|
||||
if (NS_SUCCEEDED(result->GetTypeAheadResult(&isTypeAheadResult)) &&
|
||||
isTypeAheadResult &&
|
||||
NS_SUCCEEDED(result->GetCommentAt(defaultIndex, _retval)) &&
|
||||
!_retval.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
result->GetValueAt(defaultIndex, _retval);
|
||||
nsAutoString inputValue;
|
||||
mInput->GetTextValue(inputValue);
|
||||
if (!_retval.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::CompleteValue(nsString &aValue)
|
||||
/* mInput contains mSearchString, which we want to autocomplete to aValue. If
|
||||
|
@ -66,8 +66,50 @@ private:
|
||||
nsresult GetResultValueLabelAt(PRInt32 aIndex, bool aValueOnly,
|
||||
bool aGetValue, nsAString & _retval);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Gets and validates the defaultComplete result and the relative
|
||||
* defaultIndex value.
|
||||
*
|
||||
* @param aResultIndex
|
||||
* Index of the defaultComplete result to be used. Pass -1 to search
|
||||
* for the first result providing a valid defaultIndex.
|
||||
* @param _result
|
||||
* The found result.
|
||||
* @param _defaultIndex
|
||||
* The defaultIndex relative to _result.
|
||||
*/
|
||||
nsresult GetDefaultCompleteResult(PRInt32 aResultIndex,
|
||||
nsIAutoCompleteResult** _result,
|
||||
PRInt32* _defaultIndex);
|
||||
|
||||
/**
|
||||
* Gets the defaultComplete value to be suggested to the user.
|
||||
*
|
||||
* @param aResultIndex
|
||||
* Index of the defaultComplete result to be used.
|
||||
* @param aPreserveCasing
|
||||
* Whether user casing should be preserved.
|
||||
* @param _retval
|
||||
* The value to be completed.
|
||||
*/
|
||||
nsresult GetDefaultCompleteValue(PRInt32 aResultIndex, bool aPreserveCasing,
|
||||
nsAString &_retval);
|
||||
|
||||
/**
|
||||
* Gets the defaultComplete value to be used when the user navigates or
|
||||
* confirms the current match.
|
||||
* The value is returned only if it case-insensitively matches the current
|
||||
* input text, otherwise the method returns NS_ERROR_FAILURE.
|
||||
* This happens because we don't want to override user casing in case of a
|
||||
* navigation key (unless the text is the same), or to replace text if the
|
||||
* user backspaces just before Enter.
|
||||
*
|
||||
* @param _retval
|
||||
* The value to be completed.
|
||||
*/
|
||||
nsresult GetFinalDefaultCompleteValue(nsAString &_retval);
|
||||
|
||||
nsresult ClearResults();
|
||||
|
||||
nsresult RowIndexToSearch(PRInt32 aRowIndex,
|
||||
|
@ -718,7 +718,12 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 14 uses schema version 20.
|
||||
if (currentSchemaVersion < 21) {
|
||||
rv = MigrateV21Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 14 uses schema version 21.
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
|
||||
@ -1839,6 +1844,39 @@ Database::MigrateV20Up()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::MigrateV21Up()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Add a prefix column to moz_hosts.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT prefix FROM moz_hosts"
|
||||
), getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_hosts ADD COLUMN prefix"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Update prefixes.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> updatePrefixesStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_hosts SET prefix = ( "
|
||||
HOSTS_PREFIX_PRIORITY_FRAGMENT
|
||||
") "
|
||||
), getter_AddRefs(updatePrefixesStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
rv = updatePrefixesStmt->ExecuteAsync(nsnull, getter_AddRefs(ps));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Database::Shutdown()
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
// This is the schema version. Update it at any schema change and add a
|
||||
// corresponding migrateVxx method below.
|
||||
#define DATABASE_SCHEMA_VERSION 20
|
||||
#define DATABASE_SCHEMA_VERSION 21
|
||||
|
||||
// Fired after Places inited.
|
||||
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
|
||||
@ -270,6 +270,7 @@ protected:
|
||||
nsresult MigrateV18Up();
|
||||
nsresult MigrateV19Up();
|
||||
nsresult MigrateV20Up();
|
||||
nsresult MigrateV21Up();
|
||||
|
||||
nsresult UpdateBookmarkRootTitles();
|
||||
nsresult CheckAndUpdateGUIDs();
|
||||
|
@ -1287,7 +1287,7 @@ urlInlineComplete.prototype = {
|
||||
// want to complete up to and including a URL separator.
|
||||
this.__syncQuery = this._db.createStatement(
|
||||
"/* do not warn (bug no): could index on (typed,frecency) but not worth it */ "
|
||||
+ "SELECT host || '/' "
|
||||
+ "SELECT host || '/', prefix || host || '/' "
|
||||
+ "FROM moz_hosts "
|
||||
+ "WHERE host BETWEEN :search_string AND :search_string || X'FFFF' "
|
||||
+ "AND frecency <> 0 "
|
||||
@ -1378,11 +1378,12 @@ urlInlineComplete.prototype = {
|
||||
let lastSlashIndex = this._currentSearchString.lastIndexOf("/");
|
||||
if (lastSlashIndex == -1) {
|
||||
var hasDomainResult = false;
|
||||
var domain;
|
||||
var domain, untrimmedDomain;
|
||||
try {
|
||||
hasDomainResult = query.executeStep();
|
||||
if (hasDomainResult) {
|
||||
domain = query.getString(0);
|
||||
untrimmedDomain = query.getString(1);
|
||||
}
|
||||
} finally {
|
||||
query.reset();
|
||||
@ -1390,7 +1391,9 @@ urlInlineComplete.prototype = {
|
||||
|
||||
if (hasDomainResult) {
|
||||
// We got a match for a domain, we can add it immediately.
|
||||
result.appendMatch(this._strippedPrefix + domain, "");
|
||||
// TODO (bug 754265): this is a temporary solution introduced while
|
||||
// waiting for a propert dedicated API.
|
||||
result.appendMatch(this._strippedPrefix + domain, untrimmedDomain);
|
||||
|
||||
this._finishSearch();
|
||||
return;
|
||||
@ -1481,7 +1484,10 @@ urlInlineComplete.prototype = {
|
||||
handleResult: function UIC_handleResult(aResultSet)
|
||||
{
|
||||
let row = aResultSet.getNextRow();
|
||||
let url = fixupSearchText(row.getResultByIndex(0));
|
||||
let value = row.getResultByIndex(0);
|
||||
let url = fixupSearchText(value);
|
||||
|
||||
let prefix = value.slice(0, value.length - url.length);
|
||||
|
||||
// We must complete the URL up to the next separator (which is /, ? or #).
|
||||
let separatorIndex = url.slice(this._currentSearchString.length)
|
||||
@ -1494,8 +1500,10 @@ urlInlineComplete.prototype = {
|
||||
url = url.slice(0, separatorIndex);
|
||||
}
|
||||
|
||||
// Add the result
|
||||
this._result.appendMatch(this._strippedPrefix + url, "");
|
||||
// Add the result.
|
||||
// TODO (bug 754265): this is a temporary solution introduced while
|
||||
// waiting for a propert dedicated API.
|
||||
this._result.appendMatch(this._strippedPrefix + url, prefix + url);
|
||||
|
||||
// handleCompletion() will cause the result listener to be called, and
|
||||
// will display the result in the UI.
|
||||
|
@ -134,6 +134,7 @@
|
||||
", host TEXT NOT NULL UNIQUE" \
|
||||
", frecency INTEGER" \
|
||||
", typed INTEGER NOT NULL DEFAULT 0" \
|
||||
", prefix TEXT" \
|
||||
")" \
|
||||
)
|
||||
|
||||
|
@ -46,6 +46,34 @@
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* Select the best prefix for a host, based on existing pages registered for it.
|
||||
* Prefixes have a priority, from the top to the bottom, so that secure pages
|
||||
* have higher priority, and more generically "www." prefixed hosts come before
|
||||
* unprefixed ones.
|
||||
* Each condition just checks if a page exists for a specific prefixed host,
|
||||
* and if so returns the relative prefix.
|
||||
*/
|
||||
#define HOSTS_PREFIX_PRIORITY_FRAGMENT \
|
||||
"SELECT CASE " \
|
||||
"WHEN EXISTS( " \
|
||||
"SELECT 1 FROM moz_places WHERE url BETWEEN 'https://www.' || host || '/' " \
|
||||
"AND 'https://www.' || host || '/' || X'FFFF' " \
|
||||
") THEN 'https://www.' " \
|
||||
"WHEN EXISTS( " \
|
||||
"SELECT 1 FROM moz_places WHERE url BETWEEN 'https://' || host || '/' " \
|
||||
"AND 'https://' || host || '/' || X'FFFF' " \
|
||||
") THEN 'https://' " \
|
||||
"WHEN EXISTS( " \
|
||||
"SELECT 1 FROM moz_places WHERE url BETWEEN 'ftp://' || host || '/' " \
|
||||
"AND 'ftp://' || host || '/' || X'FFFF' " \
|
||||
") THEN 'ftp://' " \
|
||||
"WHEN EXISTS( " \
|
||||
"SELECT 1 FROM moz_places WHERE url BETWEEN 'http://www.' || host || '/' " \
|
||||
"AND 'http://www.' || host || '/' || X'FFFF' " \
|
||||
") THEN 'www.' " \
|
||||
"END "
|
||||
|
||||
/**
|
||||
* These triggers update the hostnames table whenever moz_places changes.
|
||||
*/
|
||||
@ -54,12 +82,17 @@
|
||||
"AFTER INSERT ON moz_places FOR EACH ROW " \
|
||||
"WHEN LENGTH(NEW.rev_host) > 1 " \
|
||||
"BEGIN " \
|
||||
"INSERT OR REPLACE INTO moz_hosts (id, host, frecency, typed) " \
|
||||
"INSERT OR REPLACE INTO moz_hosts (id, host, frecency, typed, prefix) " \
|
||||
"VALUES (" \
|
||||
"(SELECT id FROM moz_hosts WHERE host = fixup_url(get_unreversed_host(NEW.rev_host))), " \
|
||||
"fixup_url(get_unreversed_host(NEW.rev_host)), " \
|
||||
"MAX(IFNULL((SELECT frecency FROM moz_hosts WHERE host = fixup_url(get_unreversed_host(NEW.rev_host))), -1), NEW.frecency), " \
|
||||
"MAX(IFNULL((SELECT typed FROM moz_hosts WHERE host = fixup_url(get_unreversed_host(NEW.rev_host))), 0), NEW.typed) " \
|
||||
"MAX(IFNULL((SELECT typed FROM moz_hosts WHERE host = fixup_url(get_unreversed_host(NEW.rev_host))), 0), NEW.typed), " \
|
||||
"(" HOSTS_PREFIX_PRIORITY_FRAGMENT \
|
||||
"FROM ( " \
|
||||
"SELECT fixup_url(get_unreversed_host(NEW.rev_host)) AS host " \
|
||||
") AS match " \
|
||||
") " \
|
||||
"); " \
|
||||
"END" \
|
||||
)
|
||||
@ -75,6 +108,11 @@
|
||||
"WHERE rev_host = get_unreversed_host(host || '.') || '.' " \
|
||||
"OR rev_host = get_unreversed_host(host || '.') || '.www.' " \
|
||||
"); " \
|
||||
"UPDATE moz_hosts " \
|
||||
"SET prefix = (" \
|
||||
HOSTS_PREFIX_PRIORITY_FRAGMENT \
|
||||
") " \
|
||||
"WHERE host = fixup_url(get_unreversed_host(OLD.rev_host)); " \
|
||||
"END" \
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
const CURRENT_SCHEMA_VERSION = 20;
|
||||
const CURRENT_SCHEMA_VERSION = 21;
|
||||
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
const NS_APP_PROFILE_DIR_STARTUP = "ProfDS";
|
||||
|
@ -23,7 +23,7 @@ add_autocomplete_test([
|
||||
add_autocomplete_test([
|
||||
"Searching for cased entry 3",
|
||||
"mozilla.org/T",
|
||||
{ autoFilled: "mozilla.org/Test/", completed: "mozilla.org/Test/" },
|
||||
{ autoFilled: "mozilla.org/Test/", completed: "http://mozilla.org/Test/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://mozilla.org/Test/" });
|
||||
}
|
||||
@ -41,7 +41,7 @@ add_autocomplete_test([
|
||||
add_autocomplete_test([
|
||||
"Searching for cased entry 5",
|
||||
"mOzilla.org/T",
|
||||
{ autoFilled: "mOzilla.org/Test/", completed: "mozilla.org/Test/" },
|
||||
{ autoFilled: "mOzilla.org/Test/", completed: "http://mozilla.org/Test/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://mozilla.org/Test/" });
|
||||
},
|
||||
@ -59,7 +59,7 @@ add_autocomplete_test([
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed cased entry with www",
|
||||
"http://www.mOz",
|
||||
{ autoFilled: "http://www.mOzilla.org/", completed: "http://www.mozilla.org/" },
|
||||
{ autoFilled: "http://www.mOzilla.org/", completed: "www.mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://www.mozilla.org/Test/" });
|
||||
},
|
||||
|
134
toolkit/components/places/tests/inline/test_trimming.js
Normal file
134
toolkit/components/places/tests/inline/test_trimming.js
Normal file
@ -0,0 +1,134 @@
|
||||
/* 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/. */
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed https://www entry",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "https://www.mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://www.mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed https://www entry with path",
|
||||
"mozilla.org/t",
|
||||
{ autoFilled: "mozilla.org/test/", completed: "https://www.mozilla.org/test/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://www.mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed https:// entry",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "https://mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed https:// entry with path",
|
||||
"mozilla.org/t",
|
||||
{ autoFilled: "mozilla.org/test/", completed: "https://mozilla.org/test/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed http://www entry",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "www.mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed http://www entry with path",
|
||||
"mozilla.org/t",
|
||||
{ autoFilled: "mozilla.org/test/", completed: "http://www.mozilla.org/test/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed ftp:// entry",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "ftp://mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "ftp://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Searching for untrimmed ftp:// entry with path",
|
||||
"mozilla.org/t",
|
||||
{ autoFilled: "mozilla.org/test/", completed: "ftp://mozilla.org/test/" },
|
||||
function () {
|
||||
addBookmark({ url: "ftp://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Ensuring correct priority 1",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "https://www.mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://www.mozilla.org/test/" });
|
||||
addBookmark({ url: "https://mozilla.org/test/" });
|
||||
addBookmark({ url: "ftp://mozilla.org/test/" });
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
addBookmark({ url: "http://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Ensuring correct priority 2",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "https://mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "https://mozilla.org/test/" });
|
||||
addBookmark({ url: "ftp://mozilla.org/test/" });
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
addBookmark({ url: "http://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Ensuring correct priority 3",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "ftp://mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "ftp://mozilla.org/test/" });
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
addBookmark({ url: "http://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Ensuring correct priority 4",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.org/", completed: "www.mozilla.org/" },
|
||||
function () {
|
||||
addBookmark({ url: "http://www.mozilla.org/test/" });
|
||||
addBookmark({ url: "http://mozilla.org/test/" });
|
||||
},
|
||||
]);
|
||||
|
||||
add_autocomplete_test([
|
||||
"Ensuring longer domain can't match",
|
||||
"mo",
|
||||
{ autoFilled: "mozilla.co/", completed: "mozilla.co/" },
|
||||
function () {
|
||||
// The .co should be preferred, but should not get the https from the .com.
|
||||
// The .co domain must be added later to activate the trigger bug.
|
||||
addBookmark({ url: "https://mozilla.com/" });
|
||||
addBookmark({ url: "http://mozilla.co/" });
|
||||
addBookmark({ url: "http://mozilla.co/" });
|
||||
},
|
||||
]);
|
@ -6,5 +6,6 @@ tail =
|
||||
[test_casing.js]
|
||||
[test_do_not_trim.js]
|
||||
[test_keywords.js]
|
||||
[test_trimming.js]
|
||||
[test_typed.js]
|
||||
[test_zero_frecency.js]
|
||||
|
@ -282,7 +282,7 @@ function test_moz_hosts()
|
||||
{
|
||||
// This will throw if the column does not exist
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT host, frecency, typed "
|
||||
"SELECT host, frecency, typed, prefix "
|
||||
+ "FROM moz_hosts "
|
||||
);
|
||||
stmt.finalize();
|
||||
|
@ -32,10 +32,10 @@ function isHostInMozPlaces(aURI)
|
||||
return result;
|
||||
}
|
||||
|
||||
function isHostInMozHosts(aURI, aTyped)
|
||||
function isHostInMozHosts(aURI, aTyped, aPrefix)
|
||||
{
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT host, typed "
|
||||
"SELECT host, typed, prefix "
|
||||
+ "FROM moz_hosts "
|
||||
+ "WHERE host = fixup_url(:host) "
|
||||
+ "AND frecency NOTNULL "
|
||||
@ -43,10 +43,7 @@ function isHostInMozHosts(aURI, aTyped)
|
||||
let result = false;
|
||||
stmt.params.host = aURI.host;
|
||||
if (stmt.executeStep()) {
|
||||
if (aTyped != null)
|
||||
result = aTyped == stmt.row.typed;
|
||||
else
|
||||
result = true;
|
||||
result = aTyped == stmt.row.typed && aPrefix == stmt.row.prefix;
|
||||
}
|
||||
stmt.finalize();
|
||||
return result;
|
||||
@ -54,15 +51,18 @@ function isHostInMozHosts(aURI, aTyped)
|
||||
|
||||
let urls = [{uri: NetUtil.newURI("http://visit1.mozilla.org"),
|
||||
expected: "visit1.mozilla.org",
|
||||
typed: 0
|
||||
typed: 0,
|
||||
prefix: null
|
||||
},
|
||||
{uri: NetUtil.newURI("http://visit2.mozilla.org"),
|
||||
expected: "visit2.mozilla.org",
|
||||
typed: 0
|
||||
typed: 0,
|
||||
prefix: null
|
||||
},
|
||||
{uri: NetUtil.newURI("http://www.foo.mozilla.org"),
|
||||
expected: "foo.mozilla.org",
|
||||
typed: 1
|
||||
typed: 1,
|
||||
prefix: "www."
|
||||
},
|
||||
];
|
||||
|
||||
@ -96,9 +96,9 @@ function test_moz_hosts_update()
|
||||
do_throw("gHistory.updatePlaces() failed");
|
||||
},
|
||||
handleCompletion: function () {
|
||||
do_check_true(isHostInMozHosts(urls[0].uri, urls[0].typed));
|
||||
do_check_true(isHostInMozHosts(urls[1].uri, urls[1].typed));
|
||||
do_check_true(isHostInMozHosts(urls[2].uri, urls[2].typed));
|
||||
do_check_true(isHostInMozHosts(urls[0].uri, urls[0].typed, urls[0].prefix));
|
||||
do_check_true(isHostInMozHosts(urls[1].uri, urls[1].typed, urls[1].prefix));
|
||||
do_check_true(isHostInMozHosts(urls[2].uri, urls[2].typed, urls[2].prefix));
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
@ -112,7 +112,7 @@ function test_remove_places()
|
||||
|
||||
waitForClearHistory(function (){
|
||||
for (let idx in urls) {
|
||||
do_check_false(isHostInMozHosts(urls[idx].uri));
|
||||
do_check_false(isHostInMozHosts(urls[idx].uri, urls[idx].typed, urls[idx].prefix));
|
||||
}
|
||||
run_next_test();
|
||||
});
|
||||
@ -135,8 +135,8 @@ function test_bookmark_changes()
|
||||
waitForClearHistory(function (){
|
||||
let newUri = NetUtil.newURI(NEW_URL);
|
||||
do_check_true(isHostInMozPlaces(newUri));
|
||||
do_check_true(isHostInMozHosts(newUri));
|
||||
do_check_false(isHostInMozHosts(NetUtil.newURI("http://test.mozilla.org")));
|
||||
do_check_true(isHostInMozHosts(newUri, false, null));
|
||||
do_check_false(isHostInMozHosts(NetUtil.newURI("http://test.mozilla.org"), false, null));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
@ -148,7 +148,7 @@ function test_bookmark_removal()
|
||||
let newUri = NetUtil.newURI(NEW_URL);
|
||||
PlacesUtils.bookmarks.removeItem(itemId);
|
||||
waitForClearHistory(function (){
|
||||
do_check_false(isHostInMozHosts(newUri));
|
||||
do_check_false(isHostInMozHosts(newUri, false, null));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
@ -170,7 +170,7 @@ function test_moz_hosts_typed_update()
|
||||
do_throw("gHistory.updatePlaces() failed");
|
||||
},
|
||||
handleCompletion: function () {
|
||||
do_check_true(isHostInMozHosts(TEST_URI, true));
|
||||
do_check_true(isHostInMozHosts(TEST_URI, true, null));
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
@ -196,7 +196,8 @@ function test_moz_hosts_www_remove()
|
||||
},
|
||||
handleCompletion: function () {
|
||||
PlacesUtils.history.removePage(aURIToRemove);
|
||||
do_check_true(isHostInMozHosts(aURIToKeep));
|
||||
let prefix = /www/.test(aURIToKeep.spec) ? "www." : null;
|
||||
do_check_true(isHostInMozHosts(aURIToKeep, false, prefix));
|
||||
waitForClearHistory(aCallback);
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user